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

@@ -29,8 +29,8 @@ try:
except ImportError:
se = None
from ..utils.env import get_env_bool, get_env_float, get_env_int
from .base import BaseStrategy
from ..utils.env import get_env_bool, get_env_float, get_env_from_db, get_env_int
from .base import BaseStrategy, is_live_eod_now
class ScalpingStrategy(BaseStrategy):
@@ -63,6 +63,9 @@ class ScalpingStrategy(BaseStrategy):
self.rsi_oversold = get_env_float("SCALP_RSI_OVERSOLD", 25.0)
self.rsi_overbought = get_env_float("SCALP_RSI_OVERBOUGHT", 75.0)
self.slot_money = get_env_int("SLOT_MONEY_DEFAULT", 3000000)
# 실매↔BT 공통 EOD (기존 하드코딩 15:25 → env)
self.eod_enabled = get_env_bool("SCALP_EOD_ENABLED", True)
self.eod_hm = get_env_from_db("SCALP_EOD_HM", "15:25")
if se is not None:
try:
@@ -126,6 +129,10 @@ class ScalpingStrategy(BaseStrategy):
candles_raw = self.ws.get_candles(code, self.candle_tf, n=50)
if len(candles_raw) < 5:
try:
self.ws.fill_gap([code], force=True)
except Exception:
pass
return None
candles = [self._norm_candle(c) for c in candles_raw]
@@ -254,7 +261,12 @@ class ScalpingStrategy(BaseStrategy):
signals: List[Dict] = []
now = dt.now()
is_eod = (now.hour == 15 and now.minute >= 25) or now.hour > 15
is_eod = is_live_eod_now(
getattr(self, "eod_enabled", True),
getattr(self, "eod_hm", "15:25"),
now,
default_hm="15:25",
)
try:
params = se.get_scalping_defaults_from_db()
@@ -274,6 +286,8 @@ class ScalpingStrategy(BaseStrategy):
"shoulder_min_high": float(params.get("shoulder_min_high", 0.005)),
"shoulder_cut_pct": float(params.get("shoulder_cut_pct", 0.003)),
"min_hold_sec": float(get_env_int("SCALP_MIN_HOLD_SEC", 30)),
"eod_enabled": getattr(self, "eod_enabled", True),
"eod_hm": getattr(self, "eod_hm", "15:25"),
})
for code, holding in list(self.holdings.items()):