How the Model Works

A transparent look at the math, features, and validation behind our NBA predictions. No hype — just the methodology.

What This Actually Is

Summary:

Predictium runs B13, a 3-head blend prediction system that generates NBA spread and total forecasts, plus player prop projections. Head A is an ElasticNet (α=0.1, L1=0.9) with 204 features for spreads and an ElasticNet symmetric split-score (α=0.5, L1=0.1) with 229 features for totals. Head B is a RAPM-only Ridge model (α=1.0) with 25 features — 21 base RAPM roster features plus 4 engineered composites — that captures player-level roster quality signal independently. The two heads are blended: 57% ElasticNet / 43% RAPM for spreads, 77% ElasticNet / 23% RAPM for totals. After blending, a B6 RAPM post-prediction calibration layer catches residual signal. The feature set includes team stats, exponentially-weighted moving averages, player tracking data, 16 travel features (distance, timezone crossings, cumulative load, jet lag, schedule density), 13 lineup disruption features, 3 matchup interaction features, and RAPM roster projections. Trained on 5 seasons of data, predictions refresh continuously.

Why it Works:

Sports prediction is hard. NBA games have inherent randomness that no model can eliminate. Our walk-forward R² is 0.2089 for spreads and 0.1247 for totals — meaning we explain about 12–21% of the variance in game outcomes. Those numbers are honest: they come from strict temporal validation where the model only ever trains on past data and predicts unseen future games. The 3-head blend architecture and B6 RAPM post-prediction calibration squeeze additional edge by combining independent prediction signals.

We don't need to predict everything — we just need to be slightly more accurate than the betting market's implied probabilities. A small, consistent edge compounded over hundreds of bets with proper bankroll management produces returns.

Model Architecture: 3-Head Blend

Independent prediction heads combined for maximum signal

Why three heads? Because different model architectures capture different signals — and blending independent predictions outperforms any single model:

  • Head A — Spreads (204 features → ElasticNet): Relative team strength from team-level stats. Uses ElasticNet (α=0.1, L1=0.9) with aggressive L1 sparsity — most features get zeroed out, letting a smaller set of strong predictors dominate. Includes 21 team RAPM roster features, 13 lineup disruption features, and 3 matchup interaction features.
  • Head A — Totals (229 features → Symmetric Split-Score ElasticNet): Instead of predicting the total directly, B13 predicts each team's score separately using one model trained on "canonical" data — every game contributes two rows by swapping home/away into offensive/opponent columns. This doubles the training signal. Uses Ridge-like regularization (L1=0.1) that keeps many weak features alive.
  • Head B — RAPM Ridge (25 features): A completely independent prediction path using only player-level RAPM data. Ridge regression (α=1.0) on 21 base RAPM features (baseline/projected/delta for offense, defense, and net — plus differentials) and 4 engineered composites (quality diff, offense matchup, defense matchup, baseline quality diff). This head captures roster quality changes instantly — when a star is traded or injured, RAPM adjusts on day one while team-level rolling stats take 10+ games to reflect the change.

Blend weights (optimized via walk-forward grid search with bootstrap confidence intervals):

  • Spreads: 57% Head A + 43% Head B → R² = 0.2089 (+6.4% vs Head A alone)
  • Totals: 77% Head A + 23% Head B → R² = 0.1247 (+8.4% vs Head A alone)

3-Head Blend Architecture

HEAD A — SPREAD

ElasticNet (α=0.1, L1=0.9)

204 features
Aggressive L1 sparsity
Team-level rolling stats
HEAD B — RAPM

Ridge (α=1.0)

25 RAPM features
Player-level ratings
Instant roster changes
HEAD A — TOTAL

ElasticNet (α=0.5, L1=0.1)

229 features (symmetric)
Ridge-like regularization
2x training data
57%Head A+43%Head B

Blended Spread

R² = 0.2089

MAE ~11.0 pts

77%Head A+23%Head B

Blended Total

R² = 0.1247

MAE ~15.0 pts

Head B (RAPM) captures player-level roster quality instantly — trades and injuries are reflected on day one, while Head A rolling stats take 10+ games to adjust.

B13's Key Insights

Insight 1 — Opposite regularization: Spreads benefit from aggressive L1 sparsity (L1=0.9) that zeros out weak features. Totals benefit from Ridge-like regularization (L1=0.1) that keeps many weak features alive. Same ElasticNet framework, opposite tuning.

Insight 2 — Independent RAPM signal: RAPM features inside the ElasticNet get pruned (correlated with net_rtg, r=0.44). But as a separate head, RAPM captures independent signal — especially during roster disruption (trades, injuries). The 43% RAPM weight on spreads is nearly equal, reflecting how much independent information player-level ratings carry.

Feature Engineering: Up to 229 Features + 25 RAPM Head

What the model actually sees

Feature Breakdown:

CategoryCountExamples
Team Ratings~40Offensive rating L5/L10/L15/L40, defensive rating, net rating
EWMA Features28Exponentially-weighted moving averages with h10/h20/h40 half-lives
Pace & Style~15Pace L5/L10/L40, expected pace, pace mismatch
Rest & Schedule~8Rest days, back-to-backs, rest advantage
Scoring Patterns~15Points per game, points allowed, game totals (various windows)
Matchup Features~8Home offense vs away defense, expected game total
Tracking Stats14Drives, paint touches, pace miles (from NBA advanced tracking)
Player Deltas4home_off_delta, home_def_delta, away_off_delta, away_def_delta
RAPM Roster (Head A)21Team RAPM offense/defense/pace projected from player ratings × minutes
RAPM Head B Features2521 base RAPM + 4 engineered (quality diff, offense/defense matchup, baseline diff) — separate Ridge model blended with Head A
RAPM Features (totals)~30Baseline/projected/delta RAPM for offense, defense, and net — all included via symmetric stacking
Lineup Disruption13Missing star proxy, minutes disruption, replacement gap, top player out
Matchup Interactions3Harmonic game total, analytical expected total, combined expected pts
Misc~16Efficiency metrics, turnover rates, bench depth

1. RAPM: Regularized Adjusted Plus-Minus

RAPM is the foundation of B13's player-level intelligence. It decomposes every player's impact into three components — Offense, Defense, and Pace — by solving a massive regularized regression over play-by-play data.

For each possession:
  points_scored = Σ(player_on_court × player_coefficient) + home_court + ε

Regularized with Ridge (α=500) to prevent overfitting.
Computed across 166 biweekly snapshots spanning 5 NBA seasons.

The α=500 regularization is critical: without it, role players with small sample sizes get wildly unstable ratings. Heavy regularization shrinks uncertain estimates toward zero while letting high-minute stars' true impact show through.

Why RAPM Matters for Prediction

  • Trades are immediately captured. When Trae Young was traded to Washington, his individual RAPM ratings carried with him. The model didn't need to wait for team-level stats to adjust — it projected Washington's new team-level RAPM from the updated roster on day one.
  • Injuries are decomposed. Losing a player doesn't just mean "team gets worse" — it means specific offensive, defensive, and pace impacts based on who absorbs those minutes.
  • Context-independent. A player's RAPM rating reflects their impact regardless of teammates, isolating individual contribution from team effects.

2. Team RAPM Roster Features

Individual RAPM ratings become team-level features by projecting tonight's roster:

team_rapm_offense = Σ(player_rapm_offense × projected_minutes) / total_minutes
team_rapm_defense = Σ(player_rapm_defense × projected_minutes) / total_minutes
team_rapm_pace    = Σ(player_rapm_pace × projected_minutes) / total_minutes

This produces 21 features for the spread model: home/away × offense/defense/pace × various aggregations (plus differentials). For totals, the symmetric split-score approach includes all RAPM features through canonical column mapping — each team's offensive and defensive RAPM projections become "off_" and "opp_" features, giving the model a richer view of the matchup.

3. EWMA Features (Adaptive Rolling Averages)

Standard rolling windows treat all games equally. EWMA gives recent games progressively more weight:

EWMA_today = α × today's_game + (1-α) × EWMA_yesterday

Where α = 1 - exp(-ln(2) / halflife)

Three Half-Lives:

  • h10: 50% weight from last 10 games (captures hot/cold streaks)
  • h20: 50% weight from last 20 games (balances recency and stability)
  • h40: 50% weight from last 40 games (stable long-term trends)

EWMA Weight Decay Over Time

How much weight does each game receive based on recency?

h10

50% weight in 10 games

h20

50% weight in 20 games

h40

50% weight in 40 games

4. Player Delta Features (Lineup Adjustments)

Four features capture how tonight's projected lineup differs from the baseline the model expects.

Key Concepts

  • Baseline Rotation: The minute distribution the model "thinks" has been playing (50% L10 + 25% L15 + 15% L5 + 10% L40 blend).
  • Scenario Rotation: Tonight's projected minutes based on injury reports and lineup confirmations.
  • Delta: The difference. If a player is playing their usual minutes, delta = 0. If a starter is out, their minutes redistribute and the delta captures the net impact.

Example: Giannis OUT Impact

Off Impact: +4.2 | Def Impact: +2.8 | Baseline Minutes: 35

Total Impact

-1.1 pts on game total

Spread Impact

-5.1 pts vs spread

5. High-Impact Features (SHAP Analysis)

Not all features matter equally. SHAP analysis reveals which features drive predictions:

Top 10 Features by SHAP Importance

Which features have the most impact on predictions?

Higher SHAP values = greater impact on model predictions

The Continuous Pipeline

How predictions stay fresh

Continuous Pipeline Cycles

Every 1 min
Rapid Update Cycle
1
Scrape live odds~2s
2
Check injury reports~3s
3
Detect material changes~1s
4
Re-predict affected games~10s
5
Log to audit trail~1s
Total: ~17s per cycle | Trigger: Odds shift >2 pts, status change, AI probability Δ >5%
Every 5 min
Full Refresh Cycle
1
Recompute all predictions~90s
2
Rebuild state cache~30s
3
Update baseline rotations~15s
Total: ~135s | Purpose: Incorporate latest game results, stay within API limits

Why Selective Re-Prediction?

Full prediction runs take ~90 seconds. Selective re-runs (every 1 min) complete in ~10 seconds for only affected games. Full refresh every 5 minutes ensures all predictions stay current.

Continuous Improvement

We don't ship a model and walk away

B13 isn't a static artifact. It's the current output of a continuous improvement pipeline designed for rapid iteration:

  • Feature caching: The full feature matrix (~20 minutes to build from raw data) is computed once and cached. New model configurations test against the cached features in seconds, not minutes.
  • Sub-minute iteration: Once features are built, we can test dozens of model configs (hyperparameters, feature subsets, regularization strategies) in under a minute each.
  • Walk-forward discipline: Every candidate model is evaluated with strict temporal validation before it goes live. No peeking at future data, ever.
  • Incremental feature development: New features (like travel features in B4) are validated independently before being added to the production feature set.

We don't ship a model and walk away — we ship a model and keep improving it. B13 replaced B12 when rebuilding RAPM data (filling 135 games with zero coverage) revealed that an independent RAPM head carries significant signal — adding +6.4% spread R² and +8.4% total R² through a simple fixed blend. The next iteration is always in development.

Validation: How We Know It Works

The only test that matters

We use strict temporal validation — the model only sees data available before prediction time:

Walk-Forward Validation Structure

Strict temporal separation prevents data leakage

Training Period
2021-222022-232023-242024-25 (through Dec 10)
Model learns patterns from historical data
TEMPORAL CUTOFF ⚠️

Model cannot see beyond this point during training

Test Period (Held Out)
2024-25 (Dec 11+)2025-26 (all games)
Model performance evaluated on completely unseen future data

Data Flow Direction

Past
Train Model
Predict Future

R² Performance Across Seasons

Walk-forward validation on held-out test data

Spread Model

Blended R²: 0.2089

Stable across seasons. 57% ElasticNet + 43% RAPM blend. RAPM head captures roster changes instantly while rolling stats lag.

Total Model

Blended R²: 0.1247

77% ElasticNet symmetric split-score + 23% RAPM Ridge. Totals are inherently harder — signal is distributed across many weak features.

Current Performance (Walk-Forward Validation):

MetricValueInterpretation
Spread R²0.2089Explains 20.89% of spread variance
Total R²0.1247Explains 12.47% of total variance

About These Numbers

These are honest walk-forward numbers. The model trains on prior seasons and predicts future games it has never seen. Many sports models report in-sample R² (training on and testing against the same data), which produces flattering but meaningless numbers. Our R² is lower because it's real. If someone shows you an NBA model with R² above 0.30 on walk-forward, ask to see their methodology.

Limitations: What This Model Is Not

Honest assessment

It's Not a Crystal Ball

R² of 0.12–0.21 means 79–88% of game variance is noise or unmeasured factors. This is a tool for systematic, probabilistic betting over many games — not for calling tonight's winner with certainty.

RAPM Has Limits

Player impact ratings are estimated from noisy play-by-play data. Role players with limited minutes have uncertain ratings (which is why we use α=500 regularization — it admits uncertainty). Rookie impact is especially hard to estimate before they accumulate minutes.

It's Blind to Intangibles

Locker room chemistry, coaching motivation, playoff implications, referee tendencies, tanking — these matter but are hard to quantify.

Totals Are Harder Than Spreads

Even with B13's total prediction (R² 0.1247 vs 0.2089 for spreads), totals remain harder. Game totals are more volatile and depend on in-game pace dynamics that are difficult to predict before tip-off. B13's Ridge-like regularization (L1=0.1) keeps many weak predictors alive, and the RAPM blend adds +8.4% — but totals signal remains inherently more distributed and harder to capture.

No fluff. No promises. Just the math.

Ready to Use the Model?

Get real-time predictions, edges, and player impact analysis for every NBA game.

Predictium provides analytical tools for informational purposes. All betting carries risk. Gamble responsibly.