Long-time lurker, first post sharing actual backtesting work. Built a situational model for NHL and wanted to share the methodology with this forum since the SBR crowd understands closing line value better than anywhere else.
Data
What I tried first — ML model
Trained XGBoost on Corsi, SV%, expected goals, score state, rest features. Temporal holdout evaluation (no lookahead bias). AUC: 0.49. The market is efficient. A general predictive model adds nothing against Pinnacle closing lines. Moved on.
Signal 1 — Rest Differential
Tested away B2B alone: -1.9% ROI. Market prices fatigue in fully. Edge only surfaces with the rest differential added.
Signal 2 — Goalie Load Proxy on B2B
Low load = backup starting = edge. High load (tired starter) is negative ROI — market prices starter fatigue but not backup quality.
What doesn't hold up
Travel distance, rolling SV% differential, goalie fatigue alone — all tested, all near zero or negative against closing lines. Market has it.
Limitations
Signal 2 is 39 games. Wide confidence intervals. Goalie load is a proxy metric — shots-faced rolling window, not confirmed starter data. Getting actual starter confirmation tightens the filter considerably. Signal 1 at 48 games is more solid but still early validation.
I built a free tracker that flags both situations daily before puck drop: icecoldanalytics.ca
Happy to post the Python scripts or discuss methodology. Interested in whether anyone here has tested similar rest differential edges in other sports.
Data
- Game data: MoneyPuck (22,500 games, 17 seasons)
- Odds: Pinnacle EU closing lines via The Odds API historical endpoint
- Evaluation period: 2021–2023 seasons (where Pinnacle EU data is available)
- ROI calculated on flat $100 unit bets to Pinnacle closing, with DraftKings as secondary confirmation
What I tried first — ML model
Trained XGBoost on Corsi, SV%, expected goals, score state, rest features. Temporal holdout evaluation (no lookahead bias). AUC: 0.49. The market is efficient. A general predictive model adds nothing against Pinnacle closing lines. Moved on.
Signal 1 — Rest Differential
| Sample | 48 games (2021–2023) |
| Hit rate | 60.4% |
| ROI vs Pinnacle closing | +8.7% |
| ROI vs DraftKings closing | +7.4% |
| Frequency | ~77 games/season |
Signal 2 — Goalie Load Proxy on B2B
| Sample | 39 games (2021–2023) |
| Hit rate | 71.8% |
| ROI vs Pinnacle closing | +38.7% |
| 2021 ROI | +48.4% |
| 2022 ROI | +4.0% |
| 2023 ROI | +56.4% |
What doesn't hold up
Travel distance, rolling SV% differential, goalie fatigue alone — all tested, all near zero or negative against closing lines. Market has it.
Limitations
Signal 2 is 39 games. Wide confidence intervals. Goalie load is a proxy metric — shots-faced rolling window, not confirmed starter data. Getting actual starter confirmation tightens the filter considerably. Signal 1 at 48 games is more solid but still early validation.
I built a free tracker that flags both situations daily before puck drop: icecoldanalytics.ca
Happy to post the Python scripts or discuss methodology. Interested in whether anyone here has tested similar rest differential edges in other sports.
