""" kis_trader/utils/universe_source.py — {SID}_UNIVERSE_SOURCE 단일 해석 ====================================================================== 매니저 폴링·history·전략 후보 로드가 같은 규칙을 쓰도록 공통 helper. 운영 스위치는 env **하나**: ``{STRATEGY_ID}_UNIVERSE_SOURCE`` → ``ranking`` | ``condition`` | ``kiwoom_condition`` 비활성 전략(``STRATEGY_{SID}_ENABLED=false``)은 main 이 매니저에 등록하지 않으므로 별도 UNIVERSE_SOURCE 설정 불필요. """ from __future__ import annotations from typing import FrozenSet from .env import get_env_from_db VALID_UNIVERSE_SOURCES: FrozenSet[str] = frozenset( {"ranking", "condition", "kiwoom_condition"} ) # BaseStrategy.DEFAULT_UNIVERSE_SOURCES · main._DEFAULT_SOURCE 와 동기화 _DEFAULT_SOURCES: dict[str, str] = { "SCALP": "condition", "SHORT": "kiwoom_condition", "BREAKOUT": "kiwoom_condition", "MOMENTUM": "kiwoom_condition", "UPDOW": "condition", "RANGE_BREAK": "condition", "DBBAND": "condition", } def resolve_universe_source(strategy_id: str, *, default: str | None = None) -> str: """DB/env 에서 전략 유니버스 소스 해석. 잘못된 값이면 default 로 폴백.""" sid = (strategy_id or "").strip().upper() if not sid: return "ranking" fb = default if default is not None else _DEFAULT_SOURCES.get(sid, "ranking") if fb not in VALID_UNIVERSE_SOURCES: fb = "ranking" key = f"{sid}_UNIVERSE_SOURCE" src = (get_env_from_db(key, fb) or fb).strip().lower() if src not in VALID_UNIVERSE_SOURCES: return fb return src def universe_source_active(strategy_id: str, want: str) -> bool: """현재 active UNIVERSE_SOURCE 가 want 와 같을 때만 True (REST/WS 반영 gate).""" want_norm = (want or "").strip().lower() if want_norm not in VALID_UNIVERSE_SOURCES: return False return resolve_universe_source(strategy_id) == want_norm