Files
kis_trader/scratch/compare_kiwoom_only_stalls.py
Your Name 0ecac7cb95 이번에 들어간 내용
한투 호가 = 2번째 앱키 전용
키 없거나 start 실패 시 메인에 H0STASP0 안 붙임. 운영설정 WS_ORDERBOOK_SAVE_KIS 빨간 danger.

LS RAM 합집합
후보∪보유∪영구∪grace. sync_targets와 split reconcile 둘 다. 틱 DB 영구 게이트는 그대로.

분봉 쓰레기 → 다음 소스 봉 통째
그 분 틱 0건이거나 전부 봉끝 대비 LIVE_FEED_FALLBACK_MAX_AGE_SEC 초과면 구멍. 메인 WS → 2차 → LS → REST → rollup. CANDLE_GARBAGE_FALLBACK 기본 true.

파일: feed_fallback.py(신규), ws_manager.py, kis_ws.py, candle_series.py, bt_candle_source.py, live_config_schema.py, database.py, 스모크, MD 2개.

같은 ws_manager/database/kis_ws/live_config에는 직전 커밋 이후 쌓여 있던 시세 폴백·ENV 키 정리도 같이 들어갔습니다. 파일 단위로 나눌 수 없어서입니다.
2026-08-19 22:11:31 +09:00

138 lines
4.1 KiB
Python

#!/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,
})