#!/usr/bin/env python3 """활발 종목 + 키움만 멈춘 구간 (한투는 계속).""" 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 TT = """ STR_TO_DATE( CASE WHEN CHAR_LENGTH(tick_time) >= 14 THEN LEFT(tick_time, 14) ELSE NULL END, '%%Y%%m%%d%%H%%i%%s' ) """ db = TradeDB() t0 = "2026-08-19 09:00:00" t1 = "2026-08-19 09:35:00" print("== 활발 종목(키움 n>=100) recv 최대공백 키움 vs 한투 ==") rows = db.conn.execute( f""" SELECT k.code, k.n_kw, s.n_kis, k.max_recv max_recv_kw, s.max_recv max_recv_kis, (k.max_recv - IFNULL(s.max_recv,0)) delta_recv, k.max_tt max_tt_kw, s.max_tt max_tt_kis FROM ( SELECT code, COUNT(*) n_kw, MAX(recv_gap) max_recv, MAX(tt_gap) max_tt FROM ( SELECT code, TIMESTAMPDIFF(SECOND, LAG(recv_ts) OVER (PARTITION BY code ORDER BY id), recv_ts) recv_gap, TIMESTAMPDIFF(SECOND, LAG({TT}) OVER (PARTITION BY code ORDER BY {TT}, id), {TT}) tt_gap FROM ws_ticks WHERE source='kiwoom' AND recv_ts >= %s AND recv_ts < %s ) a GROUP BY code HAVING n_kw >= 100 ) k LEFT JOIN ( SELECT code, COUNT(*) n_kis, MAX(recv_gap) max_recv, MAX(tt_gap) max_tt FROM ( SELECT code, TIMESTAMPDIFF(SECOND, LAG(recv_ts) OVER (PARTITION BY code ORDER BY id), recv_ts) recv_gap, TIMESTAMPDIFF(SECOND, LAG({TT}) OVER (PARTITION BY code ORDER BY {TT}, id), {TT}) tt_gap FROM ws_ticks WHERE source='kis' AND recv_ts >= %s AND recv_ts < %s ) b GROUP BY code ) s ON s.code = k.code ORDER BY delta_recv DESC """, (t0, t1, t0, t1), ).fetchall() print("n_active", len(rows)) for r in rows[:20]: print(dict(r)) print("\n== 전종목: 키움 0건인데 한투>0 인 초(연속 침묵) ==") rows = db.conn.execute( """ SELECT recv_ts, SUM(source='kis') n_kis, SUM(source='kiwoom') n_kw FROM ws_ticks WHERE recv_ts >= %s AND recv_ts < %s AND source IN ('kis','kiwoom') GROUP BY recv_ts HAVING SUM(source='kiwoom') = 0 AND SUM(source='kis') > 0 ORDER BY recv_ts """, (t0, t1), ).fetchall() print("silent_seconds", len(rows)) # streak streaks = [] prev = None start = None n_kis = 0 sec = 0 from datetime import datetime as dt def parse(s): return dt.strptime(str(s)[:19], "%Y-%m-%d %H:%M:%S") for r in rows: ts = parse(r["recv_ts"]) nk = int(r["n_kis"]) if prev is None or (ts - prev).total_seconds() != 1: if start is not None: streaks.append((start, prev, sec, n_kis)) start = ts sec = 1 n_kis = nk else: sec += 1 n_kis += nk prev = ts if start is not None: streaks.append((start, prev, sec, n_kis)) streaks.sort(key=lambda x: -x[2]) print("streaks>=5s:") for s, e, sec, nk in streaks: if sec >= 5: print(f" {s} ~ {e} {sec}s kis_ticks={nk}") print("\n== 025980 키움 recv_gap>=10 구간 (그 사이 한투 건수) ==") kw = db.conn.execute( """ SELECT id, tick_time, recv_ts, TIMESTAMPDIFF(SECOND, LAG(recv_ts) OVER (ORDER BY id), recv_ts) recv_gap, LAG(recv_ts) OVER (ORDER BY id) prev_recv FROM ws_ticks WHERE source='kiwoom' AND code=%s AND recv_ts >= %s AND recv_ts < %s """, ("025980", t0, t1), ).fetchall() gaps = [dict(r) for r in kw if r["recv_gap"] is not None and int(r["recv_gap"]) >= 10] print("n_gaps", len(gaps)) for g in gaps: prev = g["prev_recv"] cur = g["recv_ts"] kis_n = db.conn.execute( "SELECT COUNT(*) n FROM ws_ticks WHERE source=%s AND code=%s " "AND recv_ts > %s AND recv_ts < %s", ("kis", "025980", prev, cur), ).fetchone() print({ "prev": str(prev), "cur": str(cur), "kw_gap": g["recv_gap"], "kw_tick_time": g["tick_time"], "kis_during": kis_n["n"] if kis_n else 0, })