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

@@ -581,19 +581,27 @@ class TradeDBExt:
# ------------------------------------------------------------------
# 백테스트 헬퍼: 특정 시점의 유니버스 복원
# ------------------------------------------------------------------
@staticmethod
def _universe_history_table(history_source: str = "kiwoom") -> str:
from kis_trader.backtest.universe_history_source import history_table_for_source
return history_table_for_source(history_source)
def get_universe_at(
self, *, strategy_id: str, at_time: str
self, *, strategy_id: str, at_time: str, history_source: str = "kiwoom",
) -> List[Dict]:
"""
``at_time`` ('YYYY-MM-DD HH:MM:SS') 시점에 봇이 보던 유니버스를 복원.
= 그 시각 이전의 가장 최근 event_time 스냅샷.
``history_source``: ``kiwoom``(target_candidates_history) | ``ls``(ls_candidates_history)
"""
self._ensure_history_columns()
table = self._universe_history_table(history_source)
try:
row = self.conn.execute(
"""
f"""
SELECT MAX(event_time) AS et
FROM target_candidates_history
FROM {table}
WHERE strategy_id=%s AND event_time <= %s
""",
(strategy_id, at_time),
@@ -602,8 +610,8 @@ class TradeDBExt:
if not et:
return []
rows = self.conn.execute(
"""
SELECT code, name FROM target_candidates_history
f"""
SELECT code, name FROM {table}
WHERE strategy_id=%s AND event_time=%s
ORDER BY code
""",
@@ -611,7 +619,7 @@ class TradeDBExt:
).fetchall()
return [{"code": r["code"], "name": r["name"]} for r in rows]
except Exception as e:
logger.error("get_universe_at 실패: %s", e)
logger.error("get_universe_at 실패(src=%s): %s", history_source, e)
return []
def iter_universe_events(
@@ -621,6 +629,7 @@ class TradeDBExt:
start_time: str,
end_time: str,
preserve_insert_order: bool = False,
history_source: str = "kiwoom",
) -> List[Dict]:
"""
``[start_time, end_time]`` 구간의 모든 스냅샷 이벤트를 시간순 반환.
@@ -629,14 +638,16 @@ class TradeDBExt:
``preserve_insert_order=True``: 스냅샷 내 종목 순서를 DB insert(id) 순으로
유지 (백테 매수 우선순위 정합). 기본 False 는 code 가나다순.
``history_source``: ``kiwoom`` | ``ls``
"""
self._ensure_history_columns()
table = self._universe_history_table(history_source)
order_clause = "event_time, id" if preserve_insert_order else "event_time, code"
try:
rows = self.conn.execute(
f"""
SELECT event_time, code, name
FROM target_candidates_history
FROM {table}
WHERE strategy_id=%s
AND event_time BETWEEN %s AND %s
ORDER BY {order_clause}
@@ -654,7 +665,7 @@ class TradeDBExt:
for et, items in sorted(grouped.items())
]
except Exception as e:
logger.error("iter_universe_events 실패: %s", e)
logger.error("iter_universe_events 실패(src=%s): %s", history_source, e)
return []
@staticmethod
@@ -673,6 +684,7 @@ class TradeDBExt:
strict: bool = False,
strict_lag_minutes: int = 1,
exit_debounce_sec: int = 0,
history_source: str = "kiwoom",
) -> Dict[str, List[str]]:
"""
백테스트 편의용 — 1분봉 캔들 시각(YYYYMMDDHHMM)을 키로 하는 유니버스 dict.
@@ -695,6 +707,7 @@ class TradeDBExt:
strict: 종목별 첫 event_time 기준 편입 지연 적용
strict_lag_minutes: 첫 편입 분 이후 추가 대기 분 (기본 1)
exit_debounce_sec: 짧은 EXIT→재편입 무시(초). 0=OFF.
history_source: ``kiwoom`` | ``ls``
Returns:
``{candle_time(YYYYMMDDHHMM): [code, ...]}`` —
@@ -703,12 +716,23 @@ class TradeDBExt:
"""
self._ensure_history_columns()
from kis_trader.backtest.universe_history_source import (
apply_ls_session_filter_to_start,
normalize_universe_history_source,
)
history_source = normalize_universe_history_source(history_source)
# 조회 범위: 전일 마지막 스냅샷도 포함하기 위해 시작일 00:00:00 이전 1건은
# 엔진 쪽에서 "이전에 유효했던 유니버스" 로 물려받는 게 자연스럽다.
# 단순화를 위해 start_ymd 00:00:00 ~ end_ymd 23:59:59 범위로 쿼리.
# LS + SESSION_ONLY: 장전 sticky 스냅 제외 → 당일 09:00 부터.
start_time = (
f"{start_ymd[:4]}-{start_ymd[4:6]}-{start_ymd[6:8]} 00:00:00"
)
start_time = apply_ls_session_filter_to_start(
start_time, source=history_source,
)
end_time = (
f"{end_ymd[:4]}-{end_ymd[4:6]}-{end_ymd[6:8]} 23:59:59"
)
@@ -718,6 +742,7 @@ class TradeDBExt:
start_time=start_time,
end_time=end_time,
preserve_insert_order=True,
history_source=history_source,
)
if not events:
return {}
@@ -768,6 +793,7 @@ class TradeDBExt:
try:
prev_items = self.get_universe_at(
strategy_id=strategy_id, at_time=start_time,
history_source=history_source,
)
prev_codes_set = {
str(it["code"]) for it in prev_items if it.get("code")