Files
kis_bot/kis_trader/backtest/dart_backtest_common.py
Your Name 61bec4bd1d 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.
2026-07-21 07:50:24 +09:00

143 lines
4.3 KiB
Python

#!/usr/bin/env python3
"""
kis_trader/backtest/dart_backtest_common.py — DART 웹백테 정렬
"""
from __future__ import annotations
from typing import Any, Dict, List, Optional
from database import TradeDB
from kis_trader.backtest import scalping_backtest_common as sbc
from kis_trader.engine import dart_engine as de
def load_dart_events(db: TradeDB, start: str, end: str) -> List[Dict[str, Any]]:
try:
from kis_trader.scan.dart_order_tracker import ensure_dart_disclosure_columns
ensure_dart_disclosure_columns(db)
except Exception:
pass
rows = db.conn.execute(
"""
SELECT rcept_no, stock_code, corp_name, report_nm, rcept_dt, first_seen_at
FROM dart_disclosures
WHERE stock_code <> ''
AND (filter_ok IS NULL OR filter_ok = 1)
AND (
(first_seen_at >= %s AND first_seen_at <= %s)
OR (rcept_dt >= %s AND rcept_dt <= %s)
)
ORDER BY first_seen_at ASC
""",
(
start + " 00:00:00",
end + " 23:59:59",
start.replace("-", ""),
end.replace("-", ""),
),
).fetchall()
return [dict(r) for r in rows]
def event_to_candle_time(ev: Dict[str, Any]) -> str:
fs = str(ev.get("first_seen_at") or "")
if fs:
s = fs.replace("-", "").replace(":", "").replace(" ", "")
if len(s) >= 12:
return s[:12]
rd = str(ev.get("rcept_dt") or "")
if len(rd) == 8:
return rd + "0900"
return ""
def _load_code_candles(db: TradeDB, code: str, start: str, end: str) -> List[Dict]:
sk = start.replace("-", "") + "0900"
ek = end.replace("-", "") + "1530"
rows = db.conn.execute(
"""
SELECT candle_time, open, high, low, close, volume
FROM ws_candles
WHERE timeframe=1 AND code=%s
AND candle_time >= %s AND candle_time <= %s
ORDER BY candle_time ASC
""",
(code, sk, ek),
).fetchall()
out = []
for r in rows:
out.append({
"candle_time": str(r["candle_time"]),
"open": float(r["open"] or 0),
"high": float(r["high"] or 0),
"low": float(r["low"] or 0),
"close": float(r["close"] or 0),
"volume": float(r["volume"] or 0),
"is_confirmed": 1,
})
return out
def run_dart_backtest_web_aligned(
*,
start: str,
end: str,
params: Optional[Dict[str, Any]] = None,
env_row: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
p = dict(params or de.get_dart_defaults_from_db(env_row=env_row))
db = TradeDB()
events: List[Dict[str, Any]] = []
all_trades: List[Dict[str, Any]] = []
try:
fee_rate, sell_tax, slot = sbc.fee_and_slot_from_env(env_row, strategy="DART")
if params and params.get("slot_money"):
slot = float(params["slot_money"])
events = load_dart_events(db, start, end)
codes_done = set()
for ev in events:
code = str(ev.get("stock_code") or "").strip()
if not code:
continue
ect = event_to_candle_time(ev)
if not ect:
continue
key = (code, ect[:8])
if key in codes_done:
continue
codes_done.add(key)
candles = _load_code_candles(db, code, start, end)
if not candles:
continue
trades = de.run_dart_backtest_code(
candles,
p,
event_candle_time=ect,
slot_money=slot,
fee_rate=fee_rate,
sell_tax=sell_tax,
)
for t in trades:
t["code"] = code
t["name"] = ev.get("corp_name") or code
t["rcept_no"] = ev.get("rcept_no")
all_trades.append(t)
finally:
db.close()
wins = sum(1 for t in all_trades if float(t.get("pnl") or 0) > 0)
n = len(all_trades)
pnl = sum(float(t.get("pnl") or 0) for t in all_trades)
return {
"ok": True,
"strategy": "DART",
"start": start,
"end": end,
"trades": all_trades,
"trade_count": n,
"win_rate": (wins / n * 100.0) if n else 0.0,
"total_pnl": pnl,
"events": len(events),
"params": p,
}