# Rolling Projections Milestone Ship Summary

Date: 2026-05-17

## Commit Ladder

- `b4e2dfd` — Rolling Projections Step 1: Bayesian framework + methodology
- `c90cfa6` — Rolling Projections Step 2: per-team rolling compute
- `70b86b9` — Rolling Projections Step 3: per-player rolling compute
- `e9bf106` — Rolling Projections Step 4: per-game projection from rolling context
- `d4ec0ca` — Rolling Projections Step 5: game totals rolling context note
- `563923a` — Rolling Projections Step 6: standings three-projection display
- `51b6e94` — Rolling Projections Step 7: team detail rolling projections
- `cbfacd4` — Rolling Projections Step 8: player profile rolling projections
- `ba108a2` — Rolling Projections Step 9: home projection movers
- `b81f9d2` — Rolling Projections Step 10: methods methodology section
- Step 11 — verification + ship summary

## Methodology

Canonical methodology: `docs/codex_context/rolling_projections_methodology.md`.

Core formula:

```text
observed_weight = opportunities / (opportunities + regression_constant)
rolling_projection = prior * (1 - observed_weight) + current_pace * observed_weight
```

Regression constants shipped:

- Team wins: 60 games
- Team runs: 50 games
- Hitter rate stats: 220 PA
- Hitter counting stats: 140 PA
- Pitcher rate stats: 240 BF
- Pitcher counting stats: 180 BF

Methodology win: the per-game stack now combines Bayesian rolling team talent, opponent matchup context, probable-starter rolling ERA, bullpen FIP, and lineup status. On the 2026-05-17 slate, that closed the systematic model-versus-market game-total bias to `-0.176` runs, replacing the prior geometric-mean placeholder with a calibrated rolling-context pipeline.

## New Artifacts

- `data/derived/live/team_rolling_projections_<date>.parquet`
- `data/derived/live/hitter_rolling_projections_<date>.parquet`
- `data/derived/live/pitcher_rolling_projections_<date>.parquet`
- Updated `data/derived/betting/game_lines_<date>.parquet` with rolling-context projection metadata

Daily scheduler integration:

- `compute_team_rolling_projections` in `morning_core`
- `compute_player_rolling_projections` in `morning_core`
- `build_game_lines` now consumes rolling-context inputs

## Sample Team Outputs

2026-05-17 snapshot:

| Team | Preseason | Current Pace | Rolling p50 | Rolling Band |
| --- | ---: | ---: | ---: | --- |
| NYM | 91.0 | 70.4 | 82.1 | 71.6-92.5 |
| ATL | 89.0 | 110.3 | 98.4 | 86.2-110.6 |
| TB | 73.0 | 108.0 | 88.0 | 76.0-100.0 |
| NYY | 95.0 | 96.5 | 95.7 | 84.1-107.2 |
| COL | 69.0 | 62.0 | 65.9 | 56.1-75.7 |

Mets sanity check: the framework no longer treats the preseason 91-win projection as current truth. With roughly 43% observed-season weight, the current pace pulls the rolling projection down into the low-80s while preserving uncertainty.

## Sample Player Outputs

Hitters, xwOBA:

| Player | Team | Preseason | Current Pace | Rolling |
| --- | --- | ---: | ---: | ---: |
| James Wood | WSH | .361 | .429 | .397 |
| Zach Neto | LAA | .332 | .321 | .326 |
| Drake Baldwin | ATL | .344 | .406 | .376 |
| Elly De La Cruz | CIN | .331 | .377 | .354 |
| Sal Stewart | CIN | .288 | .373 | .331 |

Pitchers, ERA:

| Player | Team | Preseason | Current Pace | Rolling |
| --- | --- | ---: | ---: | ---: |
| Sandy Alcantara | MIA | 4.75 | 3.53 | 4.07 |
| Cristopher Sanchez | PHI | 3.12 | 1.82 | 2.42 |
| Tanner Bibee | CLE | 4.08 | 4.15 | 4.12 |
| George Kirby | SEA | 3.59 | 2.84 | 3.19 |
| Gavin Williams | CLE | 3.66 | 3.74 | 3.70 |

## Surfaces Updated

- `/betting/totals-runlines`: rolling-context method note plus market O/U and gap columns.
- `/projections/standings`: three-projection display with Preseason / Pace / Rolling / Move.
- `/projections/team/<team>` and `/teams/<team_id>`: rolling team card with p10-p90 band and reasoning chips.
- `/projections/hitter/<player_id>`, `/projections/pitcher/<player_id>`, `/players/<player_id>`: rolling player card with primary metric and p10-p90 bands.
- `/`: projection movers rail with rolling risers and fallers.
- `/models`: rolling projections methodology section.

## Verification

- Route smoke: `/`, `/projections/standings`, `/projections/team/NYM`, `/teams/121`, `/projections/hitter/671732`, `/projections/pitcher/605130`, `/players/671732`, `/models`, `/betting/totals-runlines` all returned 200.
- Tests: `python -m unittest discover tests` passed, 94 tests.
- Forced `morning_core` scheduler cycle: all selected tasks succeeded in 108-112 seconds.
- Note: global post-cycle health check flags stale tasks from other named cycles when only `morning_core` is force-run. The morning cycle itself succeeded cleanly.
- Route timings sampled: `/` 1.377s, `/projections/standings` 0.105s, `/projections/team/NYM` 0.074s, `/projections/hitter/671732` 0.205s, `/models` 2.164s.
- OneDrive runtime-path scan: zero Python/JSON hits.
- Chalk discipline: no new template chalk usage; existing chalk references remain Daily/design-token scoped.

## Carried Debts

- Regression constants are heuristically tuned; a future year-by-year calibration pass can tighten them.
- Player rolling projections do not yet account for mid-season park, lineup-role, or playing-time changes beyond the observed sample.
- Per-game projection still needs normalized market-total consensus, weather, true bullpen fatigue, and starter leash to reduce absolute residual gaps.
- True 50/100 PA rolling-window xwOBA charts still require an event-level per-PA data layer.
- Defense + baserunning percentile metrics remain queued separately.
- Head-movement biomechanics remains a future research project requiring video / pose-estimation infrastructure.

## Explicit Non-Goals

- No new metric category expansion.
- No new chart types.
- No three-lane methodology changes.
- No betting-page structural rebuild.
