Edge-shading challenger: built + measured. Flooding NOT fixed — input scale is the bug
Challenger only. Champion grade byte-identical (verified by diff). Nothing promoted, no live grade re-lettered, no ledger row deleted or re-settled. BUILT src/services/challengers/efficiencyShading.js (measured-never-served): adjusted_edge = raw_edge * f(efficiency); grade = band(adjusted_edge) against ONE fixed bar (A+>=10, A>=5, B>=3, C>=1, D>=0, F<0) that never moves. f(e) = E_SOFTEST/e bounded to (0,1] — soft markets intact (never amplified), sharp shaded toward but not past zero, unscored -> f=1 and FLAGGED. A fence test asserts no production grade path imports it. Cross-market behaviour is unit-proven: the same raw 6% edge grades A in soft mlb:total_bases and B in sharp nba:points. MEASURED on 1250 live ledger rows — Phase 2.5's answer is NO, the flooding is not gone: challenger 79.0% A and 80.9% A/B (MLB 93.4% A) vs champion 0.2% A. TWO findings explain why, and they are the point of the order: 1. The shading is a NO-OP on the live board: rows_actually_shaded = 0 of 1250. 96.5% of rows are UNSCORED (f=1), and the one scored market present (mlb:total_bases) is the anchor so its f is 1.0 by construction. mlb:strikeouts and nba:points do not appear in the ledger at all (our basketball is wnba, not nba). Challenger vs baseline: 0 rows changed. 2. Placement was never the bug — the INPUT SCALE is. Against a fixed 5% bar the RAW edge already clears A on 100% of MLB doubles, 89.6% of hits, before any shading. MLB median raw edge is 60%, twelve times the bar. Decisive test: apply the sharpest score in the spec (f=0.647) to EVERY row — the maximum the design permits — and 75.8% still clear A (MLB 91.7%). Since f is bounded <= 1, no achievable shading can close a 12x overshoot. Moving the multiply from the threshold to the edge does not change the outcome. This is edge_pct behaving as the 2026-07-29 diagnosis described: a price-free (proj-line)/line gap whose scale is a function of line size. It is not a betting edge, so no fixed betting-edge bar is meaningful against it. 2.6 efficient-market over-suppression: CANNOT DETERMINE — zero live rows are shaded, so there is no efficient market in the data to over-suppress. Phase 3: takeable tagging was completed in the previous order (migration 034, 1246/1254 rows) and is not repeated. The model-version boundary is again NOT applied: nothing promoted, so no boundary exists. Unblocking needs the input replaced, not the multiply moved: p_win vs fair_prob (both already computed) instead of edge_pct, plus scores FIT from our own record for the markets we actually grade. Floor: 313 suites / 3899 tests green (9 new), web build exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QJs13VsyiSKYQP6rj3NNmc
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# SPEC — EDGE-SIDE EFFICIENCY SHADING CHALLENGER (built + measured; NOT promoted)
|
||||
2026-07-31. Champion grade UNCHANGED (byte-identical, verified by diff). Push scoring untouched.
|
||||
|
||||
---
|
||||
|
||||
## REVIEW ZERO
|
||||
|
||||
- **0.1 raw edge — EXISTS.** `analyzeViaEngine1.edgePctFor` = `((proj − line) / line) × 100`,
|
||||
signed by direction; persisted as `ledger_entries.edge`.
|
||||
- **0.1 threshold application — DOES NOT EXIST.** The champion grade is `engine1`'s additive
|
||||
factor index; there is no edge-vs-threshold step on the live path.
|
||||
- **0.1 the flat additive ±0.05 efficiency nudge — DOES NOT EXIST** (third re-check). No
|
||||
`efficiency` reference anywhere in `src/services/intelligence/` or `gradeAdapter`. **There is
|
||||
nothing to remove from the challenger path.**
|
||||
- **0.2 fixed base thresholds — DO NOT EXIST live.** So the challenger DEFINES one and it never
|
||||
moves: **A+ ≥ 10, A ≥ 5, B ≥ 3, C ≥ 1, D ≥ 0, F < 0**, identical for every market. (The spec's
|
||||
per-sport MLB-5%/NBA-7% variant is deliberately NOT used — a bar that differs by sport is a
|
||||
moving bar, which this design forbids.)
|
||||
- **0.3 efficiency scores — 5 exist in spec, and they cover almost nothing we grade.**
|
||||
`nfl:passing_yards .85 · nba:points .80 · mlb:strikeouts .60 · mlb:total_bases .55 ·
|
||||
nba:role_player .55`. Of the **11 live ledger markets**, only `mlb:total_bases` matches.
|
||||
Unscored markets default to **f = 1** and are FLAGGED.
|
||||
|
||||
## THE BUILD (`src/services/challengers/efficiencyShading.js`, measured-never-served)
|
||||
|
||||
adjusted_edge = raw_edge × f(efficiency)
|
||||
grade = band(adjusted_edge) ← ONE fixed bar, never moved
|
||||
|
||||
`f(e) = E_SOFTEST / e`, bounded to **(0, 1]**. At the softest scored market (0.55) `f = 1.0` —
|
||||
the edge is left **intact, never amplified** (the guardrail). Sharper markets shade down
|
||||
monotonically: `f(0.60)=0.917`, `f(0.80)=0.688`, `f(0.85)=0.647`. Unscored → `f = 1`, flagged.
|
||||
Absent edge → `null` (absent, never graded F). A fence test asserts **no production grade path
|
||||
imports this module**.
|
||||
|
||||
**Cross-market behaviour works as designed** (unit-proven): the same raw **6%** edge grades
|
||||
**A** in soft `mlb:total_bases` and **B** in sharp `nba:points`.
|
||||
|
||||
---
|
||||
|
||||
## PHASE 2 — THE MEASUREMENT, AND IT IS A **NO**
|
||||
|
||||
### 2.5 "Confirm the naive-formula pathology is GONE" → **IT IS NOT GONE.**
|
||||
|
||||
| population | n | challenger %A | challenger %A/B | champion %A | champion %A/B |
|
||||
|---|---|---|---|---|---|
|
||||
| MLB | 696 | **93.4** | **93.7** | 0.0 | 57.9 |
|
||||
| WNBA | 554 | 61.0 | 64.8 | 0.5 | 58.3 |
|
||||
| **TOTAL** | **1,250** | **79.0** | **80.9** | 0.2 | 58.1 |
|
||||
|
||||
**80.9% A/B — the flooding the fix was meant to remove is still there** (the naive formula's
|
||||
reported 86% A/B is not meaningfully improved on).
|
||||
|
||||
### TWO FINDINGS THAT EXPLAIN WHY, AND THEY ARE THE POINT OF THIS ORDER
|
||||
|
||||
**(1) The shading is a NO-OP on the live board. `rows_actually_shaded = 0` of 1,250.**
|
||||
**96.5% of rows (1,206) are UNSCORED** → `f = 1`. And the one scored market present
|
||||
(`mlb:total_bases`) is the *anchor*, so its `f` is 1.0 by construction. `mlb:strikeouts` and
|
||||
`nba:points` do not appear in the ledger at all (our basketball is **wnba**, not `nba`).
|
||||
**Challenger vs baseline: 0 rows changed.** The design cannot act on a board it has no scores for.
|
||||
|
||||
**(2) Placement was never the bug — the INPUT SCALE is.** Against a fixed 5% bar, the **raw**
|
||||
edge already clears A on 100% of MLB doubles, 100% stolen_bases, 89.6% hits, 88.6% total_bases —
|
||||
**before any shading at all**. MLB's median raw edge is **60%**, twelve times the bar.
|
||||
|
||||
> **The decisive test: apply the SHARPEST score in the entire spec (f = 0.647) to EVERY row —
|
||||
> the maximum shading the design permits — and 75.8% still clear the A bar** (MLB 91.7%).
|
||||
> Since `f` is bounded ≤ 1, **no achievable shading can fix this.** Moving the multiply from the
|
||||
> threshold to the edge does not change the outcome, because a bounded multiplier cannot close a
|
||||
> 12× overshoot.
|
||||
|
||||
This is `edge_pct` doing exactly what the 2026-07-29 diagnosis said it does: it is a price-free
|
||||
`(proj − line)/line` gap whose scale is a **function of line size**, so on 0.5-lines it explodes
|
||||
(median 60, max 620). **It is not a betting edge, so no fixed betting-edge bar is meaningful
|
||||
against it.**
|
||||
|
||||
### 2.6 efficient-market over-suppression → **CANNOT DETERMINE.** Zero live rows are shaded, so
|
||||
there is no efficient market in the data to over-suppress. The failure mode is untestable here.
|
||||
|
||||
### 2.7 cross-market behaviour → **works in unit test, ZERO live effect** (see finding 1).
|
||||
|
||||
---
|
||||
|
||||
## PHASE 3 — TAGGING
|
||||
|
||||
- **Takeable tagging: ALREADY DONE** in the previous order (migration 034; 1,246 of 1,254 rows
|
||||
tagged, 781 takeable / 465 below floor, `null_despite_price = 0`, floor −160 recorded per row
|
||||
and labelled policy-not-derived). **Not repeated** — re-running would be a no-op.
|
||||
- **Model-version boundary: DELIBERATELY NOT APPLIED, again.** It marks pre/post a scaling
|
||||
change. **Nothing promoted, so no boundary exists** — stamping one would record a model
|
||||
transition that never happened. `config/modelEras.js` is its home the day one promotes.
|
||||
|
||||
---
|
||||
|
||||
## WHAT WOULD ACTUALLY UNBLOCK THIS
|
||||
|
||||
1. **Replace the input, not the multiply.** A bar-based grade needs a quantity that is a real
|
||||
edge — model probability vs the de-vigged market price. That is `p_win` vs `fair_prob`, both
|
||||
already computed and stored. `edge_pct` cannot carry a fixed bar at any shading.
|
||||
2. **Fit the scores from our own record**, per market we actually grade — 9 of 11 live markets
|
||||
have no score, and inventing 9 numbers would be fabricated calibration.
|
||||
3. **Then** re-run this challenger; the mechanic itself (bounded, edge-side, fixed bar) is sound
|
||||
and already built.
|
||||
|
||||
## VERIFY
|
||||
Champion byte-identical (diff empty across `intelligence/`, `gradeSlateService`, `gradeAdapter`,
|
||||
`snapshotService`, `grade_thresholds.json`). Fixed bar never moved — efficiency multiplies the
|
||||
edge only, and a test asserts shading can only lower a grade. **313 suites / 3,899 tests green**
|
||||
(9 new), **web build exit 0**. Nothing promoted, no live grade re-lettered, no ledger row
|
||||
deleted or re-settled. Auth-gated visuals → Chrome audit; nothing visual changed.
|
||||
|
||||
## TAGS
|
||||
VERIFIED: the no-op (0 rows shaded, 96.5% unscored); the flooding (80.9% A/B) and that max
|
||||
shading still leaves 75.8% clearing A; champion untouched. **CANNOT DETERMINE: efficient-market
|
||||
over-suppression (no shaded rows exist).** BLOCKED: promotion — the input scale must change first.
|
||||
@@ -0,0 +1,115 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* EDGE-SIDE EFFICIENCY SHADING — CHALLENGER (2026-07-31, specs/edge-shading-challenger.md).
|
||||
*
|
||||
* MEASURED, NEVER SERVED. Nothing here touches the champion grade.
|
||||
*
|
||||
* THE MECHANIC (the corrected placement):
|
||||
* adjusted_edge = raw_edge × f(efficiency)
|
||||
* grade = band(adjusted_edge) against ONE FIXED bar, identical for every market
|
||||
*
|
||||
* Efficiency shades the EDGE, never the BAR. That is what makes it un-inflatable: `f` is
|
||||
* bounded to (0, 1], so an edge can only ever be shaded TOWARD zero, never amplified, and the
|
||||
* bar never moves. There is NO target distribution — however many props clear the honest bar,
|
||||
* clear it.
|
||||
*
|
||||
* WHY f IS A RATIO OF THE SOFTEST SCORE:
|
||||
* f(e) = E_SOFTEST / e
|
||||
* At the softest market (e = E_SOFTEST) f = 1.0 → the edge is left INTACT, never amplified
|
||||
* above raw (the guardrail). Sharper markets shade down monotonically — f(0.60)=0.917,
|
||||
* f(0.80)=0.688, f(0.85)=0.647 — approaching but never reaching zero. The reasoning: a 3% edge
|
||||
* against a sharp line is more likely illusory, so it counts for less; an edge against a lazy
|
||||
* line is more likely real.
|
||||
*
|
||||
* A market with NO efficiency score gets f = 1 (no adjustment) and is FLAGGED — never silently
|
||||
* scaled by a number we invented.
|
||||
*/
|
||||
|
||||
/** Spec scores. Keyed `sport:stat`; `sport:*` is a sport-wide fallback. */
|
||||
const MARKET_EFFICIENCY = Object.freeze({
|
||||
'nfl:passing_yards': 0.85,
|
||||
'nba:points': 0.80,
|
||||
'mlb:strikeouts': 0.60,
|
||||
'mlb:total_bases': 0.55,
|
||||
'nba:role_player': 0.55,
|
||||
});
|
||||
|
||||
/** The softest scored market — the calibration anchor where f = 1 (edge intact). */
|
||||
const E_SOFTEST = Math.min(...Object.values(MARKET_EFFICIENCY));
|
||||
|
||||
/**
|
||||
* THE FIXED BAR. Identical for every market, and it NEVER moves — efficiency shades the edge,
|
||||
* not this. (The spec's per-sport MLB-5%/NBA-7% variant is deliberately NOT used: a bar that
|
||||
* differs by sport is a moving bar, which this design forbids.)
|
||||
*/
|
||||
const FIXED_BANDS = Object.freeze([
|
||||
{ grade: 'A+', min: 10 },
|
||||
{ grade: 'A', min: 5 },
|
||||
{ grade: 'B', min: 3 },
|
||||
{ grade: 'C', min: 1 },
|
||||
{ grade: 'D', min: 0 },
|
||||
{ grade: 'F', min: -Infinity },
|
||||
]);
|
||||
|
||||
/** Efficiency score for a market, or null when we have none. */
|
||||
function efficiencyFor(sport, stat) {
|
||||
const sp = String(sport || '').toLowerCase();
|
||||
const st = String(stat || '').toLowerCase();
|
||||
const exact = MARKET_EFFICIENCY[`${sp}:${st}`];
|
||||
if (exact != null) return exact;
|
||||
const wide = MARKET_EFFICIENCY[`${sp}:*`];
|
||||
return wide != null ? wide : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* f(efficiency) — BOUNDED to (0, 1]. Soft markets ≤ intact, sharp shaded toward zero.
|
||||
* Unscored markets → 1 (no adjustment).
|
||||
*/
|
||||
function shadingFactor(efficiency) {
|
||||
if (efficiency == null) return 1;
|
||||
const e = Number(efficiency);
|
||||
if (!Number.isFinite(e) || e <= 0) return 1;
|
||||
const f = E_SOFTEST / e;
|
||||
// Hard bound: never amplify above the raw edge, even if a future score sits below E_SOFTEST.
|
||||
return Math.min(1, f);
|
||||
}
|
||||
|
||||
/** Band an adjusted edge against the FIXED bar. */
|
||||
function bandFor(adjustedEdge) {
|
||||
if (adjustedEdge == null || !Number.isFinite(Number(adjustedEdge))) return null;
|
||||
const v = Number(adjustedEdge);
|
||||
for (const b of FIXED_BANDS) if (v >= b.min) return b.grade;
|
||||
return 'F';
|
||||
}
|
||||
|
||||
/**
|
||||
* gradeRow({ sport, stat, edge }) → the challenger verdict for one prop.
|
||||
* `edge` is the SIGNED raw edge (positive = model agrees with the graded side).
|
||||
* Returns null when there is no edge to judge — absent, never zero.
|
||||
*/
|
||||
function gradeRow(row) {
|
||||
if (!row) return null;
|
||||
const raw = row.edge == null || row.edge === '' ? null : Number(row.edge);
|
||||
if (raw == null || !Number.isFinite(raw)) return null; // absent beats fabricated
|
||||
const efficiency = efficiencyFor(row.sport, row.stat);
|
||||
const f = shadingFactor(efficiency);
|
||||
const adjusted = raw * f;
|
||||
return {
|
||||
raw_edge: raw,
|
||||
efficiency,
|
||||
unscored: efficiency == null, // FLAGGED, not silently scaled
|
||||
f,
|
||||
adjusted_edge: Math.round(adjusted * 1000) / 1000,
|
||||
grade: bandFor(adjusted),
|
||||
// the same row graded with NO shading — the isolation baseline, so the delta
|
||||
// attributable to shading alone is measurable rather than conflated with the
|
||||
// switch to edge-vs-threshold grading.
|
||||
baseline_grade: bandFor(raw),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
MARKET_EFFICIENCY, E_SOFTEST, FIXED_BANDS,
|
||||
efficiencyFor, shadingFactor, bandFor, gradeRow,
|
||||
};
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Edge-side efficiency shading CHALLENGER (specs/edge-shading-challenger.md).
|
||||
* MEASURED, NEVER SERVED — these tests lock the properties that make it un-inflatable.
|
||||
*/
|
||||
const c = require('../../src/services/challengers/efficiencyShading');
|
||||
|
||||
describe('f(efficiency) is BOUNDED — this is what makes it un-inflatable', () => {
|
||||
test('soft market is INTACT, never amplified above the raw edge', () => {
|
||||
expect(c.shadingFactor(c.E_SOFTEST)).toBe(1);
|
||||
// even a hypothetical score BELOW the anchor cannot amplify
|
||||
expect(c.shadingFactor(0.10)).toBe(1);
|
||||
expect(c.shadingFactor(0.01)).toBe(1);
|
||||
});
|
||||
|
||||
test('sharper markets shade DOWN monotonically, toward but never past zero', () => {
|
||||
const f55 = c.shadingFactor(0.55), f60 = c.shadingFactor(0.60);
|
||||
const f80 = c.shadingFactor(0.80), f85 = c.shadingFactor(0.85);
|
||||
expect(f55).toBeGreaterThan(f60);
|
||||
expect(f60).toBeGreaterThan(f80);
|
||||
expect(f80).toBeGreaterThan(f85);
|
||||
for (const f of [f55, f60, f80, f85]) {
|
||||
expect(f).toBeGreaterThan(0);
|
||||
expect(f).toBeLessThanOrEqual(1);
|
||||
}
|
||||
});
|
||||
|
||||
test('an UNSCORED market gets f=1 and is FLAGGED, never silently scaled', () => {
|
||||
expect(c.shadingFactor(null)).toBe(1);
|
||||
const row = c.gradeRow({ sport: 'mlb', stat: 'hits', edge: 40 });
|
||||
expect(row.unscored).toBe(true);
|
||||
expect(row.f).toBe(1);
|
||||
expect(row.efficiency).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('the FIXED bar never moves', () => {
|
||||
test('bands are identical regardless of sport or market', () => {
|
||||
const soft = c.gradeRow({ sport: 'mlb', stat: 'total_bases', edge: 5 });
|
||||
const unscored = c.gradeRow({ sport: 'wnba', stat: 'points', edge: 5 });
|
||||
// same raw edge, both f=1 here -> identical band. The bar is one bar.
|
||||
expect(soft.grade).toBe(unscored.grade);
|
||||
expect(c.bandFor(10)).toBe('A+');
|
||||
expect(c.bandFor(5)).toBe('A');
|
||||
expect(c.bandFor(3)).toBe('B');
|
||||
expect(c.bandFor(1)).toBe('C');
|
||||
expect(c.bandFor(0)).toBe('D');
|
||||
expect(c.bandFor(-0.1)).toBe('F');
|
||||
});
|
||||
|
||||
test('shading can only ever LOWER a grade, never raise it', () => {
|
||||
for (const e of [0.55, 0.60, 0.80, 0.85, null]) {
|
||||
for (const edge of [0.5, 2, 4, 6, 12, 60]) {
|
||||
const r = c.gradeRow({ sport: 'x', stat: 'y', edge });
|
||||
const adj = edge * c.shadingFactor(e);
|
||||
expect(adj).toBeLessThanOrEqual(edge + 1e-9); // never amplified
|
||||
expect(r.baseline_grade).toBeTruthy();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('cross-market behaviour (the point of the design)', () => {
|
||||
test('the SAME raw edge grades LOWER in an efficient market than a soft one', () => {
|
||||
const raw = 6;
|
||||
const soft = c.gradeRow({ sport: 'mlb', stat: 'total_bases', edge: raw }); // 0.55 -> f 1.00
|
||||
const sharp = c.gradeRow({ sport: 'nba', stat: 'points', edge: raw }); // 0.80 -> f 0.688
|
||||
expect(soft.grade).toBe('A');
|
||||
expect(sharp.grade).toBe('B');
|
||||
expect(sharp.adjusted_edge).toBeLessThan(soft.adjusted_edge);
|
||||
});
|
||||
});
|
||||
|
||||
describe('absent input is absent, never zero', () => {
|
||||
test('a missing edge returns null rather than grading F', () => {
|
||||
expect(c.gradeRow({ sport: 'mlb', stat: 'hits', edge: null })).toBeNull();
|
||||
expect(c.gradeRow({ sport: 'mlb', stat: 'hits', edge: '' })).toBeNull();
|
||||
expect(c.gradeRow({ sport: 'mlb', stat: 'hits', edge: 'x' })).toBeNull();
|
||||
expect(c.gradeRow(null)).toBeNull();
|
||||
});
|
||||
|
||||
test('a real negative edge DOES grade F (not confused with absent)', () => {
|
||||
expect(c.gradeRow({ sport: 'mlb', stat: 'hits', edge: -5 }).grade).toBe('F');
|
||||
});
|
||||
});
|
||||
|
||||
describe('MEASURED-NEVER-SERVED fence', () => {
|
||||
test('no production grade path imports this challenger', () => {
|
||||
const fs = require('fs'), path = require('path');
|
||||
const files = [
|
||||
'src/services/gradeSlateService.js',
|
||||
'src/services/intelligence/analyzeViaEngine1.js',
|
||||
'src/services/intelligence/engine1.js',
|
||||
'src/services/snapshotService.js',
|
||||
'src/utils/gradeAdapter.js',
|
||||
];
|
||||
for (const f of files) {
|
||||
const src = fs.readFileSync(path.join(__dirname, '../../', f), 'utf8');
|
||||
expect(src).not.toMatch(/efficiencyShading/);
|
||||
}
|
||||
});
|
||||
});
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user