MLB Prediction System

Predicted
versus played

slate 2026-10-07settled 4KPI applied 4run error 3.500 to 4.750winners 2 to 3
The card

Predicted versus played

4 games, all settled. The middle column is this run, with the KPI layer applied to 4 of them. The column before it is what production published for the same slate, without any KPI layer, read from the local canonical artifact.

MatchupPrior VPSRegenerated ActualPickRun errTotal errResult
CLE @ CHW5-45-49-3CLE 54%53hit unmoved
LAD @ ATL6-46-44-1LAD 51%55hit unmoved
MIL @ SD6-56-53-1MIL 50%77hit unmoved
TB @ NYY3-43-44-3NYY 54%20miss unmoved
3 of 4 winners, 75.0%. Picking the home team in every game would have returned 0/4, 0.0%. The card is 3 games ahead of the coin, +75.0%. On 4 games that margin is well inside what chance produces, so it is a good day rather than a demonstration. The walk-forward is where the question is settled.
Where accuracy is won and lost

Every stage, same games

The same fifteen games scored five times. Each row is a real intermediate value recorded in the artifact, not a reconstruction.

StageRun errTotal err WinnersAccuracyBrier
Production baseline
before the KPI layer touched it
3.5002.5002/40.5000.2553
KPI-only forecast
44 KPI features alone
4.3553.2690/40.0000.3973
Blended, continuous
at the fitted weights, before rounding
3.7742.7832/40.5000.2553
Published
after rounding and probability reconciliation
4.7503.7503/40.7500.2500
Prior VPS card
what production published, no KPI layer
4.7503.7503/40.7500.2500
The recorded pipeline moved run error from 3.500 to 4.750, a gain of -1.250 runs per game. This compares an intermediate KPI baseline with the final published output. It is diagnostic only. This slate has 1 controlled paired final forecasts and 3 stage-only comparisons.
The comparison against the prior card is not the same measurement. It is read from the local canonical artifact. That card ran on older lineups and an older Savant bundle, so its 4.750 carries a data refresh as well as the missing KPI layer. The honest statement is that this card is better by +0.000 runs and +0 winners. The intermediate-to-final movement is -1.250, but it is not causal KPI attribution.

Two things the stage table exposes

The publication step

Rounding is no longer the problem

The previous settlement report found the publication step was costing accuracy. It is worth re-measuring rather than assuming, because the step now sits after a different layer.

Rounding the continuous blend to publishable integers changed run error from 3.774 to 4.750, a move of +0.976 runs, and flipped 1 winners. On this card the rounding step is harmless. The earlier finding does not reproduce, and the reconciliation that forces the integer score and the probability onto the same side is doing its job without distorting either.

The probability is still being pulled toward 0.5

Published win probability is shrunk toward 0.5 in proportion to verified skill. That is deliberate and documented. It is worth showing the size of it, because it is large enough on some games to matter and a reader comparing the blend to the published number will otherwise think something is broken.

GameBlendedPublished ShiftDirection
TB @ NYY0.5660.544-0.022toward 0.5
CLE @ CHW0.4510.465+0.013toward 0.5
MIL @ SD0.5050.495-0.010away from 0.5
LAD @ ATL0.4920.493+0.001toward 0.5

3 of 4 shifts move toward 0.5, which is the intended direction. The largest is TB @ NYY at -0.022. Brier went from 0.2553 blended to 0.2500 published, a cost of -0.0053. On fifteen games that is noise, and the shrinkage is justified by season-long calibration rather than by one card.

Coverage

What the gates did

The layer applied to 4 of 4 settled games.

Luna: historical_not_requested 4. This was a rerun after first pitch, so no live request was made and Luna moved nothing on this card. Every difference between the prior VPS column and the regenerated column comes from the refreshed inputs and the KPI layer.
Reading this honestly

What fifteen games can and cannot say

  1. It can say the layer moved almost every game. That was the open question and it is now answered: 4 of 4 games moved, and the one that did not was refused by a gate with its reason recorded.
  2. It cannot say the layer is good. Run error improved by -1.250 on this card, which is the right sign and the right rough size against the walk-forward's +0.0358 and +0.1093 per-target gains over ? games, but a fifteen-game sample has an interval far wider than the effect.
  3. It cannot say anything about winners. Every stage ties the always-home baseline at 0.0%. The winner target is inconclusive on the walk-forward too, at weight 0.14, and this card is consistent with that.
  4. The prior-card comparison is contaminated by the lineup and bundle refresh and should not be quoted as the layer's effect.
Next

What to fix, in order

  1. Accumulate prospective pairs. The only thing that settles this is more settled days with the layer live. Nothing in the code needs changing to get them.
  2. Watch the KPI model's winner calibration. Its standalone Brier of 0.3973 against a baseline 0.2553 is the weakest number in the table. If that does not improve as archives accumulate, the winner weight should go to zero rather than stay at 0.14.
  3. Raise lineup coverage, or lower the floor deliberately. One game in fifteen was refused for thin lineup samples. That rate is acceptable; a rising rate late in a season, when call-ups multiply, would not be.
  4. Leave the rounding step alone. It was flagged before and does not reproduce as a problem here. Re-measure it rather than re-fixing it.
generated 2026-10-08T09:14:28.418545+00:00 · settlement_comparison_v2
regenerated artifacts: output/games/revisions/<game>/*.json · prior card: output/games/<game>.json
stage values read from game.enhanced_prediction_analysis.kpi_layer · finals from statsapi.mlb.com
every number in this document was read from those files at generation time