proj-v1 sanity fixes (caught in the real-data induction)

1. matchupRead fly-ball signal: the batter metrics `gb_pct_bb`/`fb_ld_pct` are
   MISLABELED — they're exit velocities by batted-ball type (Judge fb_ld_pct =
   100.3 mph, not a rate), not ground/fly RATES. Switched fly-ball lean to
   avg_launch_angle (league p10/p50/p90 = 7.1/13.9/20.1°), the correct signal.
2. Absolute rate now fits the FULL season (recency-weighted), not a 20-game
   window: the window under-sampled rare stats — Judge HR projected 0.11 vs his
   0.28 season rate (a fake -32pt edge). Now point=0.27 (matches season); the
   last-5-2x recency lean is preserved.

Post-fix induction (real statsapi logs + real statcast): Judge HR 0.27 (P>=1
0.235 vs book 0.42 -> flags the juiced over), Judge TB P>=2 0.548 vs 0.48
(+6.8pt), thin-hot 3-game P>=1 0.726 / P>=3 0.164 (credible low, thin high),
.300 hitter != 3.0. proj-v1 suites 23/23.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCNgGSt5qvcLxaeQqa7Zpj
This commit is contained in:
Kev
2026-07-23 04:05:23 -04:00
parent 6386e737b9
commit 316b79733e
3 changed files with 21 additions and 15 deletions
+3 -3
View File
@@ -14,9 +14,9 @@ const FB_ARM = mr.classifyArsenal([
{ type: 'FC', usage_pct: 20, whiff_pct: 18, hard_hit_pct: 40 },
{ type: 'CU', usage_pct: 15, whiff_pct: 20, hard_hit_pct: 30 },
]);
// A fly-ball, hard-hit hitter; and a whiff-prone one.
const flyBat = { whiff_pct: 22, chase_pct: 28, hard_hit_pct: 46, metrics: { gb_pct_bb: 30, fb_ld_pct: 55 } };
const whiffBat = { whiff_pct: 34, chase_pct: 34, hard_hit_pct: 34, metrics: { gb_pct_bb: 45, fb_ld_pct: 40 } };
// A fly-ball (high launch angle), hard-hit hitter; and a whiff-prone, flatter one.
const flyBat = { whiff_pct: 22, chase_pct: 28, hard_hit_pct: 46, avg_launch_angle: 20 };
const whiffBat = { whiff_pct: 34, chase_pct: 34, hard_hit_pct: 34, avg_launch_angle: 10 };
describe('arsenal classification', () => {
it('buckets usage by pitch family + carries whiff/hard-hit tendency', () => {