한투 호가 = 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 키 정리도 같이 들어갔습니다. 파일 단위로 나눌 수 없어서입니다.
101 lines
2.9 KiB
Python
101 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
import sys
|
|
sys.path.insert(0, "/home/hoon/kis_bot")
|
|
from database import TradeDB
|
|
|
|
SINCE = "2026-08-18 09:00:00"
|
|
TICK_SINCE = "20260818090000"
|
|
|
|
db = TradeDB()
|
|
try:
|
|
print("=== active_trades ===")
|
|
rows = db.conn.execute(
|
|
"""SELECT strategy, code, name, status, current_qty, target_qty,
|
|
avg_buy_price, buy_date, updated_at
|
|
FROM active_trades ORDER BY updated_at DESC"""
|
|
).fetchall()
|
|
if not rows:
|
|
print(" (없음)")
|
|
for r in rows:
|
|
d = dict(r)
|
|
print(
|
|
f" [{d['strategy']}] {d['code']} {d.get('name','')} "
|
|
f"status={d['status']} qty={d['current_qty']}/{d['target_qty']} "
|
|
f"avg={d['avg_buy_price']} buy={d['buy_date']} upd={d['updated_at']}"
|
|
)
|
|
|
|
print("\n=== trade_history 오늘 (sell_date) ===")
|
|
rows = db.conn.execute(
|
|
"""
|
|
SELECT sell_date, strategy, code, name, qty, buy_price, sell_price, sell_reason
|
|
FROM trade_history
|
|
WHERE sell_date >= %s
|
|
ORDER BY sell_date DESC
|
|
LIMIT 30
|
|
""",
|
|
(SINCE,),
|
|
).fetchall()
|
|
if not rows:
|
|
print(" (없음)")
|
|
for r in rows:
|
|
d = dict(r)
|
|
print(
|
|
f" {d['sell_date']} [{d['strategy']}] {d['code']} {d['name']} "
|
|
f"qty={d['qty']} {d['buy_price']}→{d['sell_price']} {d['sell_reason']}"
|
|
)
|
|
|
|
print("\n=== ws_ticks 오늘만 (09:00~) source별 ===")
|
|
rows = db.conn.execute(
|
|
"""
|
|
SELECT source, COUNT(*) n, COUNT(DISTINCT code) codes,
|
|
MIN(tick_time) tmin, MAX(tick_time) tmax,
|
|
MAX(recv_ts) max_recv
|
|
FROM ws_ticks
|
|
WHERE tick_time >= %s
|
|
GROUP BY source
|
|
""",
|
|
(TICK_SINCE,),
|
|
).fetchall()
|
|
for r in rows:
|
|
print(dict(r))
|
|
|
|
print("\n=== ws_ticks 10:00 이후 source별 ===")
|
|
rows = db.conn.execute(
|
|
"""
|
|
SELECT source, COUNT(*) n, MAX(tick_time) tmax, MAX(recv_ts) max_recv
|
|
FROM ws_ticks
|
|
WHERE tick_time >= '20260818100000'
|
|
GROUP BY source
|
|
""",
|
|
).fetchall()
|
|
for r in rows:
|
|
print(dict(r))
|
|
|
|
print("\n=== SHORT history 오늘 ===")
|
|
r = db.conn.execute(
|
|
"""
|
|
SELECT COUNT(*) n, MIN(event_time) tmin, MAX(event_time) tmax
|
|
FROM target_candidates_history
|
|
WHERE strategy_id='SHORT' AND event_time >= %s
|
|
""",
|
|
(SINCE,),
|
|
).fetchone()
|
|
print(dict(r))
|
|
|
|
print("\n=== env (수집) ===")
|
|
for k in (
|
|
"WS_TICK_SAVE_ENABLED",
|
|
"WS_ORDERBOOK_SAVE_ENABLED",
|
|
"WS_ORDERBOOK_COLLECT_ENABLED",
|
|
"STRATEGY_SHORT_ENABLED",
|
|
"STRATEGY_BREAKOUT_ENABLED",
|
|
):
|
|
row = db.conn.execute(
|
|
"SELECT config_value FROM env_config_ext WHERE config_key=%s LIMIT 1", (k,)
|
|
).fetchone()
|
|
v = dict(row)["config_value"] if row else "(no row)"
|
|
print(f" {k} = {v}")
|
|
|
|
finally:
|
|
db.close()
|