#!/usr/bin/env python3 """어제(8/18) 키움 FID20 동결·지연 틱 버그가 오늘(8/19)에도 있는지 DB 검증.""" 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 def main() -> None: db = TradeDB() cols = [r["Field"] for r in db.conn.execute("SHOW COLUMNS FROM ws_ticks").fetchall()] print("ws_ticks cols:", cols) need = {"code", "tick_time", "recv_ts", "source", "volume", "price"} missing = need - set(cols) if missing: print("MISSING", missing) return has_raw = "tick_time_raw" in cols raw_sel = "tick_time_raw" if has_raw else "NULL AS tick_time_raw" print("tick_time_raw:", has_raw) # recv_ts 초 단위, tick_time 은 HHMMSS 또는 YYYYMMDDHHMMSS lag_expr = """ 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 ) """ windows = [ ("어제동결창 10:40-12:00", "2026-08-18 10:40:00", "2026-08-18 12:00:00"), ("어제아침 09:00-09:15", "2026-08-18 09:00:00", "2026-08-18 09:15:00"), ("오늘아침 09:00-now", "2026-08-19 09:00:00", "2026-08-19 23:59:59"), ("오늘전체 recv", "2026-08-19 00:00:00", "2026-08-19 23:59:59"), ] for title, a, b in windows: sql = ( "SELECT COUNT(*) AS n, " "MIN(recv_ts) AS min_recv, MAX(recv_ts) AS max_recv, " f"MIN({lag_expr}) AS min_lag, " f"MAX({lag_expr}) AS max_lag, " f"AVG({lag_expr}) AS avg_lag, " f"SUM(CASE WHEN {lag_expr} > 5 THEN 1 ELSE 0 END) AS n_lag5, " f"SUM(CASE WHEN {lag_expr} > 120 THEN 1 ELSE 0 END) AS n_lag120, " f"SUM(CASE WHEN {lag_expr} > 600 THEN 1 ELSE 0 END) AS n_lag600 " "FROM ws_ticks WHERE source=%s AND recv_ts >= %s AND recv_ts < %s" ) row = db.conn.execute(sql, ("kiwoom", a, b)).fetchone() print(f"\n== {title} kiwoom ==") print(dict(row) if row else None) sql2 = ( "SELECT COUNT(*) AS n, " f"MAX({lag_expr}) AS max_lag, " f"AVG({lag_expr}) AS avg_lag, " f"SUM(CASE WHEN {lag_expr} > 5 THEN 1 ELSE 0 END) AS n_lag5 " "FROM ws_ticks WHERE source=%s AND recv_ts >= %s AND recv_ts < %s" ) rowk = db.conn.execute(sql2, ("kis", a, b)).fetchone() print(" kis:", dict(rowk) if rowk else None) # 오늘 키움: tick_time 최빈(동결 시 한 시각에 몰림) print("\n== 오늘 키움 tick_time 상위 8 ==") top = db.conn.execute( "SELECT tick_time, COUNT(*) AS n, MIN(recv_ts) AS min_recv, MAX(recv_ts) AS max_recv " "FROM ws_ticks WHERE source=%s AND recv_ts >= %s " "GROUP BY tick_time ORDER BY n DESC LIMIT 8", ("kiwoom", "2026-08-19 09:00:00"), ).fetchall() for r in top or []: print(dict(r)) print("\n== 어제동결창 키움 tick_time 상위 5 ==") top_y = db.conn.execute( "SELECT tick_time, COUNT(*) AS n, MIN(recv_ts) AS min_recv, MAX(recv_ts) AS max_recv " "FROM ws_ticks WHERE source=%s AND recv_ts >= %s AND recv_ts < %s " "GROUP BY tick_time ORDER BY n DESC LIMIT 5", ("kiwoom", "2026-08-18 10:40:00", "2026-08-18 12:00:00"), ).fetchall() for r in top_y or []: print(dict(r)) print("\n== 오늘 키움 lag>120 샘플 8 ==") samples = db.conn.execute( "SELECT code, tick_time, " + raw_sel + ", recv_ts, price, volume, " + lag_expr + " AS lag_sec " "FROM ws_ticks WHERE source=%s AND recv_ts >= %s " f"AND {lag_expr} > 120 " "ORDER BY recv_ts DESC LIMIT 8", ("kiwoom", "2026-08-19 09:00:00"), ).fetchall() if not samples: print("(없음)") for r in samples or []: print(dict(r)) print("\n== 오늘 키움 최근 5건 ==") recent = db.conn.execute( "SELECT code, tick_time, " + raw_sel + ", recv_ts, price, " + lag_expr + " AS lag_sec " "FROM ws_ticks WHERE source=%s AND recv_ts >= %s " "ORDER BY recv_ts DESC LIMIT 5", ("kiwoom", "2026-08-19 09:00:00"), ).fetchall() for r in recent or []: print(dict(r)) if __name__ == "__main__": main()