Files
kis_bot/scratch/explain_025980_lag28.py
Your Name 1d69c217e2 fix(정합성): 틱 lag wall-clock 정합 + 3벤더 DB 저장 스위치 통일
- feed_fallback.bar_is_garbage: 봉끝 기준 → 각 틱의 recv_ts wall-clock 기준으로 정정
  실매 RAM 3초컷과 동일 논리 → 유동성 낮은 종목 부당 스킵 해소
- candle_garbage_fallback_enabled: 기본 True 복원 (wall-clock 정정 후 안전)
- param_search_optuna·run_tail_backtest_cli: CANDLE_GARBAGE_FALLBACK·BACKTEST_USE_RUST
  강제 os.environ 세팅 제거 → DB env·CLI 플래그로만 관리 (UI 존중)
- WS_TICK_DB_SAVE_LAG_CUT_ENABLED 신설 (bool, 기본 false, 3벤더 공통)
  OFF=키움/KIS/LS 모든 틱 lag 무관 전부 저장 (벤더 통계·재현·백테 정합)
  ON=lag > LIVE_FEED_FALLBACK_MAX_AGE_SEC 이면 미저장 (미래 A안)
- KIWOOM_TICK_LIVE_MAX_LAG_SEC 완전 폐기 → 위 스위치로 통일
- kiwoom_ws: _skip_persist 로직 새 스위치로 교체
- kis_ws·ls_ws: _skip_persist_kis/_ls 신규 (벤더별 상이했던 정책 통일)
- docs/정합성.md §9 신설 (문제·결정·시나리오·향후 A안 전환법)
- docs/rust_engine_parity_port_plan.md (신규 설계)

실매 스모크: logs/test_live_execution_validation_20260906_191845.log
  → 최종: 통과 · 👑 완결
브라우저 검증: http://192.168.0.149:5050/#liveconfig → 새 스위치 노출, JS 오류 없음

영향: 실매(DB 저장 정책 통일, RAM 컷 변경 없음) + 백테/Optuna(실매 정합)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-06 19:23:01 +09:00

116 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""025980 lag~28s vs 어제 아침 max~5s — 스키마 확인 후 1회 조회."""
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from database import TradeDB
from kis_trader.utils.env import get_env_from_db
LAG = """
TIMESTAMPDIFF(
SECOND,
STR_TO_DATE(
CASE
WHEN CHAR_LENGTH(tick_time) >= 14 THEN LEFT(tick_time, 14)
WHEN CHAR_LENGTH(tick_time) = 6 THEN CONCAT(DATE_FORMAT(recv_ts, '%%Y%%m%%d'), tick_time)
ELSE NULL
END,
'%%Y%%m%%d%%H%%i%%s'
),
recv_ts
)
"""
db = TradeDB()
cols = [r["Field"] for r in db.conn.execute("SHOW COLUMNS FROM ws_ticks").fetchall()]
print("ws_ticks cols:", cols)
print("DB_CUT_ON", get_env_from_db("WS_TICK_DB_SAVE_LAG_CUT_ENABLED")) # 2026-09-06 통일 (구 KIWOOM_TICK_LIVE_MAX_LAG_SEC)
print("TIME_MAX", get_env_from_db("KIWOOM_TICK_TIME_MAX_LAG_SEC"))
print("FLUSH", get_env_from_db("WS_TICK_DB_FLUSH_SEC"))
print("BATCH", get_env_from_db("WS_TICK_DB_BATCH_SIZE"))
sel = [
c
for c in (
"id",
"code",
"tick_time",
"tick_time_raw",
"recv_ts",
"price",
"volume",
"source",
)
if c in cols
]
sel_sql = ", ".join(sel)
print("\n== 오늘 kiwoom lag>5 ==")
rows = db.conn.execute(
f"SELECT {sel_sql}, {LAG} AS lag_sec FROM ws_ticks "
"WHERE source=%s AND recv_ts >= %s AND recv_ts < %s AND "
f"{LAG} > 5 ORDER BY lag_sec DESC LIMIT 20",
("kiwoom", "2026-08-19 09:00:00", "2026-08-19 09:15:00"),
).fetchall()
for r in rows:
print(dict(r))
print("\n== 025980 09:04:50~09:06:00 (id순) ==")
rows = db.conn.execute(
f"SELECT {sel_sql}, {LAG} AS lag_sec FROM ws_ticks "
"WHERE source=%s AND code=%s AND recv_ts >= %s AND recv_ts <= %s "
"ORDER BY id",
("kiwoom", "025980", "2026-08-19 09:04:50", "2026-08-19 09:06:00"),
).fetchall()
print("n", len(rows))
for r in rows:
print(dict(r))
# 같은 recv 초에 몰린 종목 수 (WS 스레드 스톨 흔적)
print("\n== 오늘 09:05:30~09:05:40 recv 초별 건수/종목 ==")
rows = db.conn.execute(
"SELECT recv_ts, COUNT(*) n, COUNT(DISTINCT code) codes "
"FROM ws_ticks WHERE source=%s AND recv_ts >= %s AND recv_ts <= %s "
"GROUP BY recv_ts ORDER BY recv_ts",
("kiwoom", "2026-08-19 09:05:30", "2026-08-19 09:05:40"),
).fetchall()
for r in rows:
print(dict(r))
print("\n== 오늘 09:00~09:10 lag 분포 ==")
rows = db.conn.execute(
f"SELECT {LAG} AS lag_sec, COUNT(*) n FROM ws_ticks "
"WHERE source=%s AND recv_ts >= %s AND recv_ts < %s "
f"GROUP BY {LAG} ORDER BY lag_sec DESC LIMIT 15",
("kiwoom", "2026-08-19 09:00:00", "2026-08-19 09:10:00"),
).fetchall()
for r in rows:
print(dict(r))
print("\n== 어제 09:00~09:15 lag 분포 top ==")
rows = db.conn.execute(
f"SELECT {LAG} AS lag_sec, COUNT(*) n FROM ws_ticks "
"WHERE source=%s AND recv_ts >= %s AND recv_ts < %s "
f"GROUP BY {LAG} ORDER BY lag_sec DESC LIMIT 15",
("kiwoom", "2026-08-18 09:00:00", "2026-08-18 09:15:00"),
).fetchall()
for r in rows:
print(dict(r))
print("\n== 어제 10:51~12:00 (잔존) lag 분포 top ==")
rows = db.conn.execute(
f"SELECT {LAG} AS lag_sec, COUNT(*) n FROM ws_ticks "
"WHERE source=%s AND recv_ts >= %s AND recv_ts < %s "
f"GROUP BY {LAG} ORDER BY lag_sec DESC LIMIT 10",
("kiwoom", "2026-08-18 10:51:00", "2026-08-18 12:00:00"),
).fetchall()
for r in rows:
print(dict(r))