ls증권 히스토리 구독 넣음
This commit is contained in:
@@ -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] = []
|
||||
|
||||
Reference in New Issue
Block a user