feat(옵투나): score·min_trades·후처리 재탐색 및 웹 job 개선
PnL/(MDD+ADD) score·legacy 정렬·거래일×min_trades 게이트를 공통화한다. 후처리 ob_modes·study store·4전략 TPE 순차 스크립트와 문서를 갱신한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -420,15 +420,17 @@ def _make_sampler(name: str, seed: Optional[int]):
|
||||
return TPESampler(seed=seed, multivariate=True, warn_independent_sampling=False)
|
||||
|
||||
|
||||
def _momentum_objective_value(result: Dict[str, Any], sort_by: str) -> float:
|
||||
pnl = float(result["total_pnl"])
|
||||
if sort_by == "score":
|
||||
mdd_floor = get_env_float("MOMENTUM_SCORE_MDD_FLOOR", 10000.0)
|
||||
mdd = float(result.get("mdd") or 0)
|
||||
return pnl / max(mdd, mdd_floor)
|
||||
if sort_by == "win_rate":
|
||||
return float(result["win_rate"])
|
||||
return pnl
|
||||
def _momentum_objective_value(
|
||||
result: Dict[str, Any],
|
||||
sort_by: str,
|
||||
*,
|
||||
start: Any = None,
|
||||
end: Any = None,
|
||||
) -> float:
|
||||
from kis_trader.backtest.optuna_common import optuna_objective_value
|
||||
return float(optuna_objective_value(
|
||||
result, sort_by, start=start, end=end, strategy="momentum",
|
||||
))
|
||||
|
||||
|
||||
def run_momentum_optuna(
|
||||
@@ -495,17 +497,18 @@ def run_momentum_optuna(
|
||||
if result is None:
|
||||
trial.set_user_attr("gates_ok", False)
|
||||
return _FAIL_OBJECTIVE
|
||||
obj = _momentum_objective_value(result, sort_by)
|
||||
trial.set_user_attr("gates_ok", True)
|
||||
trial.set_user_attr("total_pnl", float(result["total_pnl"]))
|
||||
trial.set_user_attr("win_rate", float(result["win_rate"]))
|
||||
trial.set_user_attr("pf", float(result.get("pf") or 0))
|
||||
trial.set_user_attr("mdd", float(result.get("mdd") or 0))
|
||||
trial.set_user_attr("score", float(obj if sort_by == "score" else _momentum_objective_value(result, "score")))
|
||||
trial.set_user_attr("total_trades", int(result["total_trades"]))
|
||||
trial.set_user_attr("merged_json", json.dumps(result.get("merged_params") or {}, ensure_ascii=False))
|
||||
from kis_trader.backtest.optuna_common import optuna_store_trial_score_user_attrs
|
||||
set_optuna_trial_stability_attrs(trial, result)
|
||||
return float(obj)
|
||||
return optuna_store_trial_score_user_attrs(
|
||||
trial, result, sort_by, start=ctx.start, end=ctx.end, strategy="momentum",
|
||||
)
|
||||
|
||||
logger.info(
|
||||
"🔬 Optuna MOMENTUM | study=%s | trials=%d | sort=%s",
|
||||
@@ -525,6 +528,8 @@ def run_momentum_optuna(
|
||||
)
|
||||
elapsed = time.time() - t0
|
||||
|
||||
from kis_trader.backtest.optuna_common import optuna_score_fields_from_trial
|
||||
from kis_trader.backtest.optuna_common import optuna_score_fields_from_trial
|
||||
passing: List[Dict[str, Any]] = []
|
||||
for trial in study.trials:
|
||||
if trial.state != optuna.trial.TrialState.COMPLETE:
|
||||
@@ -544,7 +549,8 @@ def run_momentum_optuna(
|
||||
"total_pnl": float(trial.user_attrs.get("total_pnl") or 0),
|
||||
"pf": float(trial.user_attrs.get("pf") or 0),
|
||||
"mdd": float(trial.user_attrs.get("mdd") or 0),
|
||||
"score": float(trial.user_attrs.get("score") or 0),
|
||||
**optuna_score_fields_from_trial(trial),
|
||||
"period_daily_avg_pnl": float(trial.user_attrs.get("period_daily_avg_pnl") or 0),
|
||||
"optuna_trial_number": trial.number,
|
||||
}
|
||||
row.update(stability_fields_from_trial_attrs(trial))
|
||||
@@ -576,6 +582,8 @@ def run_momentum_optuna(
|
||||
"elapsed_sec": round(elapsed, 1),
|
||||
**tiers,
|
||||
}
|
||||
from kis_trader.backtest.optuna_common import annotate_optuna_period_daily_avg
|
||||
annotate_optuna_period_daily_avg(out_data)
|
||||
|
||||
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
_mk = str(getattr(ctx, "market", "") or "").strip().upper()
|
||||
|
||||
Reference in New Issue
Block a user