feat(옵투나·웹): 후처리 재탐색·ob_modes·적용감사·수집통계
- Optuna web jobs/TPE/apply snapshot·틱로더 정합, jobs limit·감사로그 - 백테 UI 호가모드·후보 적용 흐름, feed_collect_stats API/탭 - 가설검증·교차검증 룰, 4전략 스모크·OB slot41 진단 스크립트 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
"""
|
||||
optuna_breakout_tpe_space.py — 돌파 Optuna 연속(TPE) 탐색 공간
|
||||
기존 ``_breakout_grids()`` categorical 경로는 유지. ``skip_hts`` 항상 False.
|
||||
|
||||
호가 ON/OFF 는 trial 축이 아님 — CLI ``--orderbook-filter on|off`` 스터디 스위치.
|
||||
(fixed/atr 손절과 같이 한 스터디에 섞지 않음 → 최대 fixed|atr × off|on = 4순차)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -10,9 +13,11 @@ from typing import Any, Dict, List, Optional
|
||||
import optuna
|
||||
|
||||
from kis_trader.backtest.optuna_tpe_common import (
|
||||
ORDERBOOK_TPE_THRESHOLD_KEYS,
|
||||
RATCHET_TPE_AXIS_KEYS,
|
||||
r1,
|
||||
r2,
|
||||
suggest_orderbook_thresholds_tpe,
|
||||
suggest_ratchet_tiers_pct,
|
||||
)
|
||||
|
||||
@@ -36,7 +41,11 @@ _BREAKOUT_BASE_KEYS: List[str] = [
|
||||
"body_min_pct",
|
||||
"max_hold_bars",
|
||||
]
|
||||
BREAKOUT_TPE_AXIS_KEYS: List[str] = list(_BREAKOUT_BASE_KEYS) + list(RATCHET_TPE_AXIS_KEYS)
|
||||
# 돌파: 본축 + 래칫. 호가 ON/OFF·임계는 스터디 스위치(아래 breakout_tpe_axis_keys).
|
||||
# 휩쏘는 전략 특성상 TPE 스킵 — 기존과 동일.
|
||||
BREAKOUT_TPE_AXIS_KEYS: List[str] = (
|
||||
list(_BREAKOUT_BASE_KEYS) + list(RATCHET_TPE_AXIS_KEYS)
|
||||
)
|
||||
|
||||
|
||||
def normalize_tpe_breakout_sl_mode(raw: Optional[Any] = None) -> str:
|
||||
@@ -47,19 +56,43 @@ def normalize_tpe_breakout_sl_mode(raw: Optional[Any] = None) -> str:
|
||||
return "fixed"
|
||||
|
||||
|
||||
def breakout_tpe_axis_keys(sl_mode: Optional[str] = None) -> List[str]:
|
||||
"""fixed=sl_pct 만, atr=atr_sl_mult 만. 한 스터디에 둘 다 넣지 않음."""
|
||||
def normalize_tpe_breakout_ob_mode(raw: Optional[Any] = None) -> str:
|
||||
"""돌파 TPE 호가 스터디 스위치. off | on (auto→on). trial 축 아님."""
|
||||
s = str(raw or "off").strip().lower()
|
||||
if s in ("on", "1", "true", "yes", "auto"):
|
||||
return "on"
|
||||
return "off"
|
||||
|
||||
|
||||
def breakout_tpe_study_extra(
|
||||
sl_mode: Optional[str] = None,
|
||||
orderbook_filter: Optional[str] = None,
|
||||
) -> str:
|
||||
"""study 이름용 — 예: fixed_ob_off / atr_ob_on (한 스터디에 손절·호가 안 섞음)."""
|
||||
sm = normalize_tpe_breakout_sl_mode(sl_mode)
|
||||
om = normalize_tpe_breakout_ob_mode(orderbook_filter)
|
||||
return f"{sm}_ob_{om}"
|
||||
|
||||
|
||||
def breakout_tpe_axis_keys(
|
||||
sl_mode: Optional[str] = None,
|
||||
orderbook_filter: Optional[str] = None,
|
||||
) -> List[str]:
|
||||
"""fixed=sl_pct 만, atr=atr_sl_mult 만. 호가 ON 스터디만 임계값 축 추가."""
|
||||
keys = list(BREAKOUT_TPE_AXIS_KEYS)
|
||||
if normalize_tpe_breakout_sl_mode(sl_mode) == "atr":
|
||||
keys.append("atr_sl_mult")
|
||||
else:
|
||||
keys.append("sl_pct")
|
||||
if normalize_tpe_breakout_ob_mode(orderbook_filter) == "on":
|
||||
keys.extend(list(ORDERBOOK_TPE_THRESHOLD_KEYS))
|
||||
return keys
|
||||
|
||||
|
||||
def suggest_breakout_params_tpe(
|
||||
trial: optuna.Trial,
|
||||
sl_mode: Optional[str] = None,
|
||||
orderbook_filter: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
combo: Dict[str, Any] = {}
|
||||
combo["max_daily_chg"] = r1(trial.suggest_float("max_daily_chg", 20.0, 55.0, step=1.0))
|
||||
@@ -110,4 +143,10 @@ def suggest_breakout_params_tpe(
|
||||
combo["max_hold_bars"] = trial.suggest_int("max_hold_bars", 0, 180, step=10)
|
||||
|
||||
combo["skip_hts_scan_dupes"] = False
|
||||
# 호가: 스터디 스위치 (trial categorical ON/OFF 금지 — TPE가 OFF만 편애하던 구멍)
|
||||
ob_on = normalize_tpe_breakout_ob_mode(orderbook_filter) == "on"
|
||||
combo["_orderbook_filter_enabled"] = ob_on
|
||||
combo["ob_filter_enabled"] = ob_on
|
||||
if ob_on:
|
||||
combo.update(suggest_orderbook_thresholds_tpe(trial))
|
||||
return combo
|
||||
|
||||
Reference in New Issue
Block a user