이번에 들어간 내용
한투 호가 = 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 키 정리도 같이 들어갔습니다. 파일 단위로 나눌 수 없어서입니다.
This commit is contained in:
@@ -9,7 +9,10 @@ import logging
|
||||
from collections import defaultdict
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple
|
||||
|
||||
from kis_trader.utils.env import get_env_bool, get_env_from_db
|
||||
from kis_trader.engine.feed_fallback import (
|
||||
live_feed_fallback_max_age_sec,
|
||||
orderbook_row_lag_seconds,
|
||||
)
|
||||
from kis_trader.ws.orderbook_cache import OrderbookSnapshot, orderbook_snapshot_from_storage
|
||||
from kis_trader.ws.program_cache import ProgramSnapshot, program_snapshot_from_storage
|
||||
from kis_trader.ws.trigger_eval_recorder import FILTER_EVAL_SOURCE
|
||||
@@ -332,6 +335,63 @@ def _index_log_verdict_row(
|
||||
})
|
||||
|
||||
|
||||
def _merge_ls_orderbook_fallback(
|
||||
out: Dict[str, Dict[str, List[OrderbookSnapshot]]],
|
||||
db,
|
||||
start_key: str,
|
||||
end_key: str,
|
||||
codes: Optional[Set[str]],
|
||||
market: str,
|
||||
kiwoom_valid_minutes: Dict[str, Dict[str, str]],
|
||||
) -> int:
|
||||
"""메인 호가 없거나 2초 초과인 분에 ls_ws_orderbook 을 넣음. 빈 스냅=필터 통과 금지."""
|
||||
added = 0
|
||||
try:
|
||||
rows = _load_orderbook_rows(
|
||||
db, start_key, end_key, codes, market=market,
|
||||
sources=LS_BODY_SOURCES, strategy="",
|
||||
table="ls_ws_orderbook", use_strategy_col=False,
|
||||
)
|
||||
if not rows:
|
||||
rows = _load_orderbook_rows(
|
||||
db, start_key, end_key, codes, market=market,
|
||||
sources=tuple(), strategy="",
|
||||
table="ls_ws_orderbook", use_strategy_col=False,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.debug("ls_ws_orderbook 폴백 로드 스킵: %s", e)
|
||||
return 0
|
||||
age = live_feed_fallback_max_age_sec()
|
||||
ls_latest: Dict[str, Dict[str, Any]] = defaultdict(dict)
|
||||
for r in rows:
|
||||
code = str(r.get("code") or "").strip()
|
||||
st = str(r.get("snap_time") or "").strip()
|
||||
minute_key = _minute_key(st)
|
||||
if not code or not minute_key:
|
||||
continue
|
||||
lag = orderbook_row_lag_seconds(r)
|
||||
if age > 0 and lag is not None and lag > age:
|
||||
continue
|
||||
prev = ls_latest[code].get(minute_key)
|
||||
if prev is None or str(st) >= str(prev.get("snap_time") or ""):
|
||||
ls_latest[code][minute_key] = r
|
||||
for code, minutes in ls_latest.items():
|
||||
valid = kiwoom_valid_minutes.get(code) or {}
|
||||
for mk, r in minutes.items():
|
||||
if mk in valid:
|
||||
continue
|
||||
snap = orderbook_snapshot_from_storage(r)
|
||||
bucket = out.setdefault(code, {}).setdefault(mk, [])
|
||||
if not bucket:
|
||||
bucket.append(snap)
|
||||
added += 1
|
||||
else:
|
||||
bucket[-1] = snap
|
||||
if added:
|
||||
logger.info("📌 호가 3차 LS 폴백: +%s분 (메인 없거나 2초 초과)", added)
|
||||
return added
|
||||
|
||||
|
||||
def load_orderbook_snapshots_by_code(
|
||||
db,
|
||||
start_key: str,
|
||||
@@ -446,6 +506,10 @@ def load_orderbook_snapshots_by_code(
|
||||
seen_eval.add((code, st[:14]))
|
||||
total += 1
|
||||
elif src == KIWOOM_BODY_SOURCE:
|
||||
lag = orderbook_row_lag_seconds(r)
|
||||
age = live_feed_fallback_max_age_sec()
|
||||
if age > 0 and lag is not None and lag > age:
|
||||
continue
|
||||
# 분당 최신 1건만 (rows 는 snap_time ASC 정렬 → 뒤가 최신)
|
||||
prev = kiwoom_latest[code].get(minute_key)
|
||||
snap = orderbook_snapshot_from_storage(r)
|
||||
@@ -469,6 +533,9 @@ def load_orderbook_snapshots_by_code(
|
||||
bucket.append(snap)
|
||||
total += 1
|
||||
|
||||
total += _merge_ls_orderbook_fallback(
|
||||
out, db, start_key, end_key, codes, mkt, kiwoom_latest,
|
||||
)
|
||||
return dict(out), total, dict(log_verdict)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user