ls증권 히스토리 구독 넣음

This commit is contained in:
Your Name
2026-07-30 18:05:07 +09:00
parent 61bec4bd1d
commit 67eab24603
1593 changed files with 135733 additions and 1232 deletions

View File

@@ -46,6 +46,41 @@ def live_universe_slot_align_enabled(strategy_id: str) -> bool:
return _env_flag("LIVE_UNIVERSE_SLOT_ALIGN", True)
def resolve_live_universe_history_source(
strategy_id: str,
*,
universe_source: Optional[str] = None,
) -> str:
"""실매 슬롯 정합이 읽을 이력 테이블.
- ``ls_condition`` 유니버스 → ``ls_candidates_history``
- 그 외 → ``target_candidates_history`` (키움/KIS)
키움 이력과 LS 실후보를 교집합하면 전원 탈락(20→0) 한다.
"""
sid = (strategy_id or "").upper()
# 전략·전역 명시 오버라이드
for key in (
f"{sid}_LIVE_UNIVERSE_HISTORY_SOURCE",
"LIVE_UNIVERSE_HISTORY_SOURCE",
):
raw = get_env_from_db(key, "")
if raw not in (None, "", "None"):
s = str(raw).strip().lower()
if s in ("ls", "ls_condition", "ls_afr"):
return "ls"
if s in ("kiwoom", "target", "kis", "condition"):
return "kiwoom"
src = str(universe_source or "").strip().lower()
if not src:
src = str(
get_env_from_db(f"{sid}_UNIVERSE_SOURCE", "") or ""
).strip().lower()
if src in ("ls_condition", "ls", "ls_afr"):
return "ls"
return "kiwoom"
def live_portfolio_budget_align_enabled(strategy_id: str) -> bool:
sid = (strategy_id or "").upper()
per_key = f"{sid}_LIVE_PORTFOLIO_BUDGET_ALIGN"
@@ -113,19 +148,39 @@ def history_universe_codes_at(
db: Any,
strategy_id: str,
when: Optional[dt] = None,
*,
history_source: str = "kiwoom",
universe_source: Optional[str] = None,
) -> Optional[Set[str]]:
"""
``target_candidates_history`` — ``at_time`` 이전 최신 스냅샷 종목 집합.
이력 스냅샷 — ``at_time`` 이전 최신 event_time 종목 집합.
- kiwoom → ``target_candidates_history``
- ls → ``ls_candidates_history``
스냅샷 없으면 ``None`` (필터 생략 = 실시간 후보 유지).
"""
when = when or dt.now()
at_time = when.strftime("%Y-%m-%d %H:%M:%S")
sid = (strategy_id or "").upper()
src = str(history_source or "").strip().lower()
if universe_source is not None:
src = resolve_live_universe_history_source(
sid, universe_source=universe_source,
)
elif src in ("", "auto"):
src = resolve_live_universe_history_source(sid, universe_source=None)
if src not in ("ls", "kiwoom"):
src = "kiwoom"
getter = getattr(db, "get_universe_at", None)
if getter is None:
return None
try:
rows = getter(strategy_id=sid, at_time=at_time) or []
# TradeDBExt 는 history_source 지원. FakeDB 등 구시그니처는 무시.
try:
rows = getter(
strategy_id=sid, at_time=at_time, history_source=src,
) or []
except TypeError:
rows = getter(strategy_id=sid, at_time=at_time) or []
except Exception:
return None
if not rows:
@@ -144,11 +199,24 @@ def filter_candidates_by_history_universe(
strategy_id: str,
*,
when: Optional[dt] = None,
history_source: Optional[str] = None,
universe_source: Optional[str] = None,
) -> Tuple[List[Dict], int]:
"""실시간 후보 ∩ history 스냅샷. (filtered, dropped_count)."""
if not candidates:
return [], 0
allowed = history_universe_codes_at(db, strategy_id, when)
hs = history_source
if hs is None:
hs = resolve_live_universe_history_source(
strategy_id, universe_source=universe_source,
)
allowed = history_universe_codes_at(
db,
strategy_id,
when,
history_source=hs or "kiwoom",
universe_source=None,
)
if allowed is None:
return candidates, 0
out: List[Dict] = []