/* ============================================================ gp-verify.jsx — the linkage proofs. Pure functions that re-derive the engine's claims from the raw candidate field, so the UI never has to trust a pre-baked "winner" flag — it proves (or disproves) it live. Three checks, plus a robustness read: 1. COMPOSITE composite_score == sharpe * win_rate_frac (objective) 2. FLOOR winner.win_rate_frac >= group win_rate_floor 3. TOP-RANK no candidate outscores the stamped winner 4. ROBUSTNESS how many near-by combos also score highly (plateau vs spike) ============================================================ */ (function () { const EPS = 0.0015; // tolerance for display-rounding on composite const METRICS = [ { key: "composite_score", label: "Composite", short: "COMP", fmt: (v) => v == null ? "—" : v.toFixed(3), higher: true, hero: true }, { key: "sharpe", label: "Sharpe", short: "SHRP", fmt: (v) => v == null ? "—" : v.toFixed(2), higher: true }, { key: "win_rate_frac", label: "Win rate", short: "WIN", fmt: (v) => v == null ? "—" : (v * 100).toFixed(1) + "%", higher: true }, { key: "total_return", label: "Total return", short: "RET", fmt: (v) => v == null ? "—" : (v > 0 ? "+" : "") + (v * 100).toFixed(1) + "%", higher: true }, { key: "max_drawdown", label: "Max drawdown", short: "MDD", fmt: (v) => v == null ? "—" : (v * 100).toFixed(1) + "%", higher: false }, ]; function recomposite(c) { if (c.sharpe == null || c.win_rate_frac == null) return null; return c.sharpe * c.win_rate_frac; } // ---- the three checks for one decision ---- function checkDecision(d) { const winner = d.winner; const cands = d.sweep.candidates; const floor = d.win_rate_floor; const valid = cands.filter((c) => c.composite_score != null); // 1. composite recompute const recomputed = recomposite(winner); const compositeOk = recomputed != null && Math.abs(recomputed - winner.composite_score) <= EPS; const composite = { id: "composite", label: "Composite = Sharpe × Win-rate", pass: compositeOk, stored: winner.composite_score, recomputed, detail: recomputed == null ? "winner has no computable score" : `${winner.sharpe.toFixed(2)} × ${winner.win_rate_frac.toFixed(3)} = ${recomputed.toFixed(3)}`, mismatch: recomputed == null ? null : winner.composite_score - recomputed, }; // 2. floor const floorOk = winner.win_rate_frac != null && winner.win_rate_frac >= floor - 1e-9; const floorChk = { id: "floor", label: `Clears group floor (≥ ${(floor * 100).toFixed(0)}%)`, pass: floorOk, detail: winner.win_rate_frac == null ? "no win-rate" : `${(winner.win_rate_frac * 100).toFixed(1)}% vs ${(floor * 100).toFixed(0)}% floor`, margin: winner.win_rate_frac == null ? null : winner.win_rate_frac - floor, }; // 3. top-rank — does anything beat the stamped winner on composite? const maxComposite = Math.max(...valid.map((c) => c.composite_score)); const beaters = valid .filter((c) => c.composite_score > winner.composite_score + EPS) .sort((a, b) => b.composite_score - a.composite_score); // rank of winner among all valid candidates by composite const sortedDesc = [...valid].sort((a, b) => b.composite_score - a.composite_score); const winnerRank = sortedDesc.findIndex((c) => c.composite_score === winner.composite_score && JSON.stringify(c.params) === JSON.stringify(winner.params)) + 1; const topRankOk = beaters.length === 0; const topRank = { id: "toprank", label: `Top-ranked of ${valid.length} scored combos`, pass: topRankOk, rank: winnerRank > 0 ? winnerRank : 1, total: valid.length, beaters, detail: topRankOk ? `#1 by composite of ${valid.length}` : `${beaters.length} combo${beaters.length > 1 ? "s" : ""} outscore the stamped winner (best ${maxComposite.toFixed(3)})`, }; const checks = [composite, floorChk, topRank]; const verdict = checks.every((c) => c.pass) ? "VERIFIED" : "FLAGGED"; const failed = checks.filter((c) => !c.pass); return { checks, verdict, failed, winnerRank: topRank.rank, validCount: valid.length }; } // ---- robustness: is the winner a plateau or a lone spike? ---- function robustness(d) { const winner = d.winner; const cands = d.sweep.candidates; const valid = cands.filter((c) => c.composite_score != null); if (winner.composite_score == null || !valid.length) { return { kind: "UNKNOWN", neighborsHigh: 0, neighborsTotal: 0, pctOfPeak: 0, meanNeighbor: 0, clearFloorHigh: 0 }; } const peak = winner.composite_score; const winnerKey = JSON.stringify(winner.params); // "near the top" = within 11% of peak composite const band = peak * 0.89; const strong = valid.filter((c) => c.composite_score >= band); // neighbors = strong combos OTHER than the winner itself const neighbors = strong.filter((c) => JSON.stringify(c.params) !== winnerKey); const clearFloorNeighbors = neighbors.filter((c) => c.win_rate_frac >= d.win_rate_floor); const meanStrong = strong.reduce((s, c) => s + c.composite_score, 0) / strong.length; const pctOfPeak = meanStrong / peak; const supporters = neighbors.length; let kind; if (supporters >= 6 && clearFloorNeighbors.length >= 4) kind = "PLATEAU"; else if (supporters >= 3) kind = "SUPPORTED"; else if (supporters >= 1) kind = "NARROW"; else kind = "SPIKE"; return { kind, neighborsHigh: supporters, neighborsTotal: valid.length - 1, clearFloorHigh: clearFloorNeighbors.length, pctOfPeak, meanNeighbor: meanStrong, band, }; } // ---- 1-D slice along the primary param for the landscape view ---- function paramSlice(d) { const strat = window.GP.STRATEGIES.find((s) => s.id === d.strategy_id); const param = strat.primaryParam; const cands = d.sweep.candidates.filter((c) => c.composite_score != null); // group by primary param value -> best composite at each value (envelope) const byVal = new Map(); for (const c of cands) { const v = c.params[param]; const cur = byVal.get(v); if (!cur || c.composite_score > cur.best) byVal.set(v, { best: c.composite_score, mean: 0, n: 0 }); } // means const acc = new Map(); for (const c of cands) { const v = c.params[param]; const a = acc.get(v) || { sum: 0, n: 0, max: -1, all: [] }; a.sum += c.composite_score; a.n++; a.max = Math.max(a.max, c.composite_score); a.all.push(c.composite_score); acc.set(v, a); } const space = strat.paramSpace[param]; const points = space.map((v) => { const a = acc.get(v); return { value: v, best: a ? a.max : null, mean: a ? a.sum / a.n : null, n: a ? a.n : 0, isWinner: d.winner.params[param] === v, }; }); return { param, points }; } // ---- summary across all decisions ---- function summary(decisions) { let verified = 0, flagged = 0; const flags = []; for (const d of decisions) { const r = checkDecision(d); if (r.verdict === "VERIFIED") verified++; else { flagged++; flags.push({ id: d.id, asset: d.asset, failed: r.failed.map((f) => f.id) }); } } return { total: decisions.length, verified, flagged, flags }; } window.GP = window.GP || {}; window.GP.verify = { METRICS, EPS, recomposite, checkDecision, robustness, paramSlice, summary, metricByKey: (k) => METRICS.find((m) => m.key === k), }; })();