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:
Your Name
2026-08-27 15:23:44 +09:00
parent 5e44b86f8b
commit 8fbba264ba
30 changed files with 2973 additions and 186 deletions

View File

@@ -880,10 +880,23 @@ def evaluate_breakout_param_combo(
engine_params["_ob_max_spread_pct"] = float(ui_params["max_spread_pct"])
if "min_bid_ask_ratio" in ui_params and ui_params.get("min_bid_ask_ratio") is not None:
engine_params["_ob_min_bid_ask_ratio"] = float(ui_params["min_bid_ask_ratio"])
# TPE ORDERBOOK 축 ask_max_mult — 모멘텀/스캘과 동일 (_ob_ask_max_mult).
# ask_wall_max_qty 만 넣던 구멍 → Optuna ask× 탐색값이 엔진에 안 들어감.
if "ask_max_mult" in ui_params and ui_params.get("ask_max_mult") is not None:
engine_params["_ob_ask_max_mult"] = float(ui_params["ask_max_mult"])
if "ask_wall_max_qty" in ui_params and ui_params.get("ask_wall_max_qty") is not None:
engine_params["_ob_ask_wall_max_qty"] = float(ui_params["ask_wall_max_qty"])
if ui_params.get("_orderbook_filter_enabled") is not None:
engine_params["_orderbook_filter_enabled"] = bool(ui_params["_orderbook_filter_enabled"])
# 스냅/본체 플래그 — breakout_ui_to_engine_params 가 드롭하므로 여기서 재주입
# (TPE need_ob_feed 시 base_fixed 의 True 가 trial 엔진까지 가야 kiwoom_0d 재계산·스냅 사용)
for _snap_k in (
"backtest_use_trigger_snapshot_db",
"backtest_use_kiwoom_body_snapshot",
"_backtest_use_kiwoom_body",
):
if ui_params.get(_snap_k) is not None:
engine_params[_snap_k] = bool(ui_params[_snap_k])
if "skip_hts_scan_dupes" in ui_params:
engine_params["skip_hts_scan_dupes"] = bool(ui_params["skip_hts_scan_dupes"])
elif "skip_hts_scan_dupes" not in engine_params:
@@ -1224,7 +1237,8 @@ def run_search(
log_verdict_by_code: Dict[str, Dict[str, List[Dict]]] = {}
trigger_snap_meta: Dict[str, Any] = {}
# kiwoom_0d 본체 재계산 — 필터 ON + 호가필터 축 **실제 스윕**(값 2개↑) 일 때만.
_ob_axes = ("max_spread_pct", "min_bid_ask_ratio", "ask_wall_max_qty")
# TPE/모멘텀=ask_max_mult · Grid 레거시=ask_wall_max_qty (둘 다 인정)
_ob_axes = ("max_spread_pct", "min_bid_ask_ratio", "ask_max_mult", "ask_wall_max_qty")
_ob_sweeping = any(len(set(grid.get(k) or [])) > 1 for k in _ob_axes)
if _ob_filter_on and _ob_sweeping:
engine_probe["backtest_use_kiwoom_body_snapshot"] = True