Improve Trader entry quality training diagnostics

This commit is contained in:
Codex
2026-06-28 00:50:37 +08:00
parent 87849a66a7
commit 340d1dd91b
11 changed files with 1895 additions and 110 deletions
+19 -12
View File
@@ -194,7 +194,7 @@ def _plan_side_rows(
gross = np.where(target_first, target_bps, np.where(stop_first, -stop_bps, timeout_return))
price_plan_net = gross - cost_bps
expected_net = max_achievable_gross - cost_bps
positive = expected_net >= min_expected_edge_bps
positive = price_plan_net >= min_expected_edge_bps
ambiguous = target_any & stop_any & (target_index == stop_index)
rows: list[dict[str, Any]] = []
@@ -264,21 +264,25 @@ def _plan_summary(rows: pd.DataFrame) -> pd.DataFrame:
split_rows["avg_price_plan_edge_eval"] = split_rows[
[f"avg_price_plan_net_edge_bps_{split}" for split in (TUNE_SPLIT, VALIDATION_LOCKED_SPLIT, LATEST_STRESS_SPLIT)]
].mean(axis=1)
split_rows["min_price_plan_edge_eval"] = split_rows[
[f"avg_price_plan_net_edge_bps_{split}" for split in (TUNE_SPLIT, VALIDATION_LOCKED_SPLIT, LATEST_STRESS_SPLIT)]
].min(axis=1)
split_rows["min_margin_eval"] = split_rows[
[f"target_rate_margin_{split}" for split in (TUNE_SPLIT, VALIDATION_LOCKED_SPLIT, LATEST_STRESS_SPLIT)]
].min(axis=1)
# The search score is not an上线门槛. It only chooses the next experiment:
# enough positive samples, less negative average edge, and stable behavior
# across tune/validation/stress.
# The search score is not an上线门槛. It only chooses the next experiment.
# Fixed price-plan net edge is weighted most heavily; max future edge is
# retained only as a weak tie-breaker because it can be optimistic.
positive_rate_penalty = (
(0.08 - split_rows["min_positive_label_rate_eval"]).clip(lower=0.0) * 80.0
+ (split_rows["max_positive_label_rate_eval"] - 0.45).clip(lower=0.0) * 30.0
(0.03 - split_rows["min_positive_label_rate_eval"]).clip(lower=0.0) * 120.0
+ (split_rows["max_positive_label_rate_eval"] - 0.55).clip(lower=0.0) * 20.0
)
spread_bonus = np.log1p((split_rows["target_bps"] - split_rows["stop_bps"]).clip(lower=0.0))
split_rows["score"] = (
split_rows["avg_edge_eval"]
+ split_rows["avg_price_plan_edge_eval"] * 0.5
+ split_rows["min_margin_eval"] * 20.0
split_rows["avg_price_plan_edge_eval"] * 8.0
+ split_rows["min_price_plan_edge_eval"] * 3.0
+ split_rows["min_margin_eval"] * 80.0
+ split_rows["avg_edge_eval"] * 0.05
- positive_rate_penalty
+ spread_bonus
)
@@ -287,8 +291,10 @@ def _plan_summary(rows: pd.DataFrame) -> pd.DataFrame:
def _select_best_plan(summary: pd.DataFrame) -> dict[str, Any]:
candidates = summary[
(summary["min_positive_label_rate_eval"] >= 0.08)
& (summary["max_positive_label_rate_eval"] <= 0.45)
(summary["min_positive_label_rate_eval"] >= 0.03)
& (summary["max_positive_label_rate_eval"] <= 0.55)
& (summary["avg_price_plan_edge_eval"] > 0.0)
& (summary["min_price_plan_edge_eval"] > -1.0)
& (summary["target_bps"] > summary["stop_bps"])
]
if candidates.empty:
@@ -305,6 +311,7 @@ def _select_best_plan(summary: pd.DataFrame) -> dict[str, Any]:
"score": float(row["score"]),
"avg_edge_eval": float(row["avg_edge_eval"]),
"avg_price_plan_edge_eval": float(row["avg_price_plan_edge_eval"]),
"min_price_plan_edge_eval": float(row["min_price_plan_edge_eval"]),
"min_margin_eval": float(row["min_margin_eval"]),
"min_positive_label_rate_eval": float(row["min_positive_label_rate_eval"]),
"max_positive_label_rate_eval": float(row["max_positive_label_rate_eval"]),
@@ -332,7 +339,7 @@ def _markdown_report(payload: dict[str, Any], summary: pd.DataFrame) -> str:
"",
_markdown_table(top),
"",
"说明:positive_label_rate 和 avg_expected_net_edge_bps 按“未来窗口最大可拿净收益”统计;target_hit_rate、stop_hit_rate、avg_price_plan_net_edge_bps 只用来检查固定止盈止损计划是否顺手。这里选的是下一轮实验用的价格计划,不是上线结论。真正能不能上线仍然看模型训练、PM 搜索、validation_locked 和 latest_stress 回测。",
"说明:positive_label_rate 和 avg_price_plan_net_edge_bps 按固定止盈止损计划统计;avg_expected_net_edge_bps 只是辅助观察未来最大可拿空间,不能单独决定价格计划。这里选的是下一轮实验用的价格计划,不是上线结论。真正能不能上线仍然看模型训练、PM 搜索、validation_locked 和 latest_stress 回测。",
"",
]
return "\n".join(lines)