refactor: enhance Optuna backtesting framework, optimize orderbook filtering, and update database management utilities.
This commit is contained in:
@@ -3,11 +3,12 @@
|
||||
돌파매매 백테스트 공통 로더 — backtest_web / param_search 가
|
||||
동일한 캔들·유니버스·손익 계산을 쓰도록 단일 진입점.
|
||||
|
||||
청산: ``check_sell_signal_breakout_live`` — EOD → 익절 → 어깨 → 손절 → 트레일.
|
||||
청산: ``check_sell_signal_breakout_live`` — EOD → 익절 → 어깨 → 호가컷/손절호가(OFF) → 손절 → 트레일.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
import os
|
||||
|
||||
from kis_trader.backtest.backtest_portfolio_common import (
|
||||
attach_scalp_trade_pnl,
|
||||
@@ -209,6 +210,23 @@ def get_breakout_defaults_from_env_row(env: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"max_spread_pct": pick(
|
||||
("BREAKOUT_ORDERBOOK_MAX_SPREAD_PCT",), 0.45, float,
|
||||
),
|
||||
# 수익구간 호가매도 / 손절호가 (UI: 이익·손실은 % 표시 · 기본 OFF)
|
||||
"exit_ob_enabled": (
|
||||
str(env.get("BREAKOUT_EXIT_OB_ENABLED") or "").strip().lower()
|
||||
in ("1", "true", "t", "y", "yes", "on")
|
||||
),
|
||||
"exit_ob_ratio_min": pick(("BREAKOUT_EXIT_OB_RATIO_MIN",), 0.4, float),
|
||||
"exit_ob_ma_window": pick(("BREAKOUT_EXIT_OB_MA_WINDOW",), 5, lambda v: int(float(v))),
|
||||
"exit_ob_min_profit_pct": pct_ui(pick(("BREAKOUT_EXIT_OB_MIN_PROFIT_PCT",), 0.005, float)),
|
||||
"exit_ob_min_hold_bars": pick(("BREAKOUT_EXIT_OB_MIN_HOLD_BARS",), 3, lambda v: int(float(v))),
|
||||
"stop_ob_enabled": (
|
||||
str(env.get("BREAKOUT_STOP_OB_ENABLED") or "").strip().lower()
|
||||
in ("1", "true", "t", "y", "yes", "on")
|
||||
),
|
||||
"stop_ob_ratio_min": pick(("BREAKOUT_STOP_OB_RATIO_MIN",), 0.4, float),
|
||||
"stop_ob_ma_window": pick(("BREAKOUT_STOP_OB_MA_WINDOW",), 5, lambda v: int(float(v))),
|
||||
"stop_ob_min_loss_pct": pct_ui(pick(("BREAKOUT_STOP_OB_MIN_LOSS_PCT",), 0.003, float)),
|
||||
"stop_ob_min_hold_bars": pick(("BREAKOUT_STOP_OB_MIN_HOLD_BARS",), 2, lambda v: int(float(v))),
|
||||
}
|
||||
|
||||
|
||||
@@ -362,6 +380,8 @@ def load_breakout_candles_by_code(
|
||||
db, start_key, end_key, min_bars=min_bars,
|
||||
)
|
||||
|
||||
candle_src = os.environ.get("CANDLE_SOURCE", "kis") or "kis"
|
||||
|
||||
ind_cols = ws_candles_select_indicator_cols(db)
|
||||
codes_raw = db.conn.execute(
|
||||
"SELECT DISTINCT code FROM ws_candles WHERE timeframe=1 "
|
||||
@@ -375,10 +395,10 @@ def load_breakout_candles_by_code(
|
||||
|
||||
for code in codes:
|
||||
rows = db.conn.execute(
|
||||
f"SELECT candle_time, open, high, low, close, volume{ind_cols} "
|
||||
"FROM ws_candles WHERE timeframe=1 AND code=%s "
|
||||
"AND candle_time >= %s AND candle_time <= %s AND is_confirmed=1 "
|
||||
"ORDER BY candle_time ASC",
|
||||
f"SELECT candle_time, open, high, low, close, volume {ind_cols} "
|
||||
f"FROM ws_candles WHERE timeframe=1 AND code=%s "
|
||||
f"AND candle_time >= %s AND candle_time <= %s AND is_confirmed=1 "
|
||||
f"ORDER BY candle_time ASC",
|
||||
[code, start_key, end_key],
|
||||
).fetchall()
|
||||
if len(rows) < min_bars:
|
||||
|
||||
Reference in New Issue
Block a user