fix: Gate-Check 4 — Fenster <5 Trades maskieren keine Verstöße mehr

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 21:12:11 +00:00
parent 986ec4446d
commit 26166c5f3c
2 changed files with 29 additions and 6 deletions

View File

@@ -62,6 +62,16 @@ export interface GateResult {
checks: GateCheck[];
}
/** Schlechtestes Test-Fenster UNTER den für Check 4 relevanten (>= 5 Trades). */
export function pickWorstEligibleWindow(metricsList: { profitFactor: number; trades: number }[]): { profitFactor: number; trades: number } {
return metricsList
.filter((m) => m.trades >= 5)
.reduce(
(acc, m) => (m.profitFactor < acc.profitFactor ? { profitFactor: m.profitFactor, trades: m.trades } : acc),
{ profitFactor: Infinity, trades: 0 },
);
}
export function evaluateGate(g: GateInput): GateResult {
const overfitRatio = g.oosProfitFactor > 0 ? g.avgTrainPf / g.oosProfitFactor : Infinity;
const windowFail = g.worstWindow.trades >= 5 && g.worstWindow.profitFactor < 0.5;
@@ -145,11 +155,7 @@ export function runWalkForward(
}
const oosMetrics = computeMetrics(oosTrades, oosEquityCurve, baseCfg.startCapital);
const windowsWithTrades = results.filter((r) => r.testMetrics.trades > 0);
const worst = windowsWithTrades.reduce(
(acc, r) => (r.testMetrics.profitFactor < acc.profitFactor ? { profitFactor: r.testMetrics.profitFactor, trades: r.testMetrics.trades } : acc),
{ profitFactor: Infinity, trades: 0 },
);
const worst = pickWorstEligibleWindow(results.map((r) => r.testMetrics));
const finiteTrainPfs = results.map((r) => Math.min(r.trainMetrics.profitFactor, 10)); // Infinity kappen
const avgTrainPf = finiteTrainPfs.reduce((s, v) => s + v, 0) / Math.max(1, finiteTrainPfs.length);