backtest: add min target-probability sweep
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 40s
Deploy / deploy (push) Successful in 26s

Re-applies the activation gate at several min_target_probability thresholds
(60→30, other conditions fixed) over the already-replayed candidates, so the
trade-off between how many setups qualify and their expectancy is visible in one
table — the cheap "optimize" half of Phase 2. Candidates now carry meets_core +
best_prob so the sweep needs no re-replay. New sweep table in BacktestPanel with
the current threshold starred.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 06:13:30 +02:00
parent 9d2e1e74bf
commit 050abc6f71
4 changed files with 81 additions and 3 deletions
@@ -158,6 +158,53 @@ export function BacktestPanel() {
</table>
</div>
{report.sweep && report.sweep.length > 0 && (
<div>
<p className="mb-2 text-xs font-medium uppercase tracking-widest text-gray-500">
Min target-probability sweep
</p>
<p className="mb-2 text-[11px] text-gray-500">
How many setups qualify and how they perform at each gate threshold (other
gate conditions held fixed). Lower = more trades, watch that expectancy holds.
Your current setting is highlighted; set it in Admin Settings Activation.
</p>
<div className="glass overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-white/[0.06] text-left text-xs uppercase tracking-wider text-gray-500">
<th className="px-4 py-2.5">Min Target Prob</th>
<th className="px-4 py-2.5 text-right">Qualified</th>
<th className="px-4 py-2.5 text-right">Wins</th>
<th className="px-4 py-2.5 text-right">Losses</th>
<th className="px-4 py-2.5 text-right">Hit Rate</th>
<th className="px-4 py-2.5 text-right">Avg R</th>
<th className="px-4 py-2.5 text-right">Total R</th>
</tr>
</thead>
<tbody>
{report.sweep.map((row) => {
const current = Math.abs(row.min_target_probability - report.min_target_probability) < 0.5;
return (
<tr key={row.min_target_probability} className={`border-b border-white/[0.04] ${current ? 'bg-blue-400/10' : ''}`}>
<td className="num px-4 py-2.5 text-gray-200">
{current && <span className="mr-1 text-blue-300"></span>}
{row.min_target_probability}%
</td>
<td className="num px-4 py-2.5 text-right text-gray-200">{row.total}</td>
<td className="num px-4 py-2.5 text-right text-emerald-400">{row.wins}</td>
<td className="num px-4 py-2.5 text-right text-red-400">{row.losses}</td>
<td className="num px-4 py-2.5 text-right text-gray-200">{fmtPct(row.hit_rate)}</td>
<td className={`num px-4 py-2.5 text-right font-semibold ${rColor(row.avg_r)}`}>{fmtR(row.avg_r)}</td>
<td className={`num px-4 py-2.5 text-right ${rColor(row.total_r)}`}>{fmtR(row.total_r)}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
)}
<div>
<p className="mb-2 text-xs font-medium uppercase tracking-widest text-gray-500">
Probability calibration