c2c7abbb65
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
102 lines
4.0 KiB
JavaScript
102 lines
4.0 KiB
JavaScript
/**
|
|
* 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/);
|
|
}
|
|
});
|
|
});
|