feat: Add DART strategy and related configurations

ㅇ
Changes:
- Introduced the DART strategy to the trading system, including its configuration and integration into the existing framework.
- Updated the database schema to include DART-specific tables for disclosures and watchlists.
- Enhanced the backtesting and parameter search functionalities to support the DART strategy.
- Implemented new rules for browser verification and API interactions to ensure compliance with the updated DART strategy.

Impact:
- These additions expand the trading capabilities of the system, allowing for more comprehensive analysis and execution of DART-related strategies, while maintaining system integrity and performance.
This commit is contained in:
Your Name
2026-07-21 07:50:24 +09:00
parent 74db49149f
commit 61bec4bd1d
86 changed files with 4811 additions and 297 deletions

View File

@@ -356,8 +356,8 @@ class WSManager:
for code in sorted(kis_now - kis_want):
# KIS 는 grace 미적용 (영구+보유만) — 즉시 해제
self.ws_cache.unsubscribe(code)
if code not in kw_want and self.candle_agg:
self.candle_agg.remove_code(code)
if code not in kw_want:
self._remove_candle_ram(code)
with self._kiwoom_ws._sub_lock:
kw_now2 = set(self._kiwoom_ws._subscribed)
@@ -366,8 +366,8 @@ class WSManager:
if self._note_leave_for_grace(code):
continue
self._kiwoom_ws.unsubscribe(code)
if code not in kis_want and self.candle_agg:
self.candle_agg.remove_code(code)
if code not in kis_want:
self._remove_candle_ram(code)
with self._lock:
is_perm = code in self._permanent_codes
if self.tick_recorder and code not in kw_want and not is_perm:
@@ -544,8 +544,7 @@ class WSManager:
if not still_refs and not is_permanent and self.ws_cache:
self.ws_cache.unsubscribe(code)
if self.candle_agg:
self.candle_agg.remove_code(code)
self._remove_candle_ram(code)
if self.tick_recorder:
self.tick_recorder.remove_code(code)
if self.trigger_snapshot_recorder:
@@ -651,13 +650,44 @@ class WSManager:
except Exception:
return []
def fill_gap(self, codes: Optional[Iterable[str]] = None) -> None:
"""외부에서 수동으로 갭 보정 트리거 (비동기: 큐 등록 후 즉시 리턴)."""
def fill_gap(
self,
codes: Optional[Iterable[str]] = None,
*,
force: bool = False,
) -> None:
"""외부에서 수동으로 갭 보정 트리거 (비동기: 큐 등록 후 즉시 리턴).
force=True: 이미 ``_gap_filled`` 여도 재큐 (RAM 삭제 후 재ENTER·봉부족 복구).
"""
if codes is None:
self._trigger_bulk_refill_async()
else:
for c in codes:
self._enqueue_gap_fill(c)
self._enqueue_gap_fill(c, force=bool(force), priority=bool(force))
def _clear_gap_fill_state(self, code: str) -> None:
"""RAM 봉 삭제와 짝 — 갭보정 완료 마커 해제.
EXIT→remove_code 후 ``_gap_filled`` 가 남으면 재ENTER 시 갭보정이 스킵되고
WS 실시간 몇 봉만으로 '봉부족'이 난다 (전 전략 공통).
"""
if not code:
return
with self._gap_lock:
self._gap_filled.discard(code)
self._gap_tf_ok.pop(code, None)
def _remove_candle_ram(self, code: str) -> None:
"""구독 해제 시 RAM 봉 정리 + 갭보정 재실행 가능하도록 상태 리셋."""
if not code:
return
if self.candle_agg:
try:
self.candle_agg.remove_code(code)
except Exception:
pass
self._clear_gap_fill_state(code)
# ------------------------------------------------------------------
# 내부: 갭 보정 — 백그라운드 워커 파이프라인