How the Model Works

What This Actually Is

Summary:

Predictium runs B13, a 3-head blend prediction system that generates NBA spread and total forecasts. It uses 204 features — team stats, exponentially-weighted moving averages, player tracking data, lineup disruption features, matchup interactions, and RAPM (Regularized Adjusted Plus-Minus) roster projections. Spreads blend an ElasticNet head (α=0.1, L1=0.9) with a RAPM Ridge head (0.57/0.43 weights). Totals use the same blend approach (0.77/0.23 weights). 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 roughly 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. B13's RAPM blend added +0.0125 spread R² and +0.0097 total R² over the standalone ElasticNet baseline.

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. That's the game.

Data API:

The Data API gives programmatic access to our full feature pipeline — rolling RAPM (O/D/Pace), shot quality metrics, team features, and all 185 model inputs via REST API. Plug them into your own models, build custom dashboards, or integrate with your existing workflow.

Model Architecture: Split-Head Prediction

Separate feature sets optimized per target

Why separate models with separate features? Because spreads and totals have different dynamics — and different features matter for each:

  • Spreads (185 features → Ridge): Relative team strength. Includes 21 team RAPM roster features that project team-level offensive, defensive, and pace ratings from individual player RAPM weighted by projected minutes. Linear relationships dominate.
  • Totals (204 features → ElasticNet + RAPM Ridge blend): 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 and teaches the model how teams score regardless of home/away position. A RAPM Ridge head is blended in at 0.23 weight for additional player-level signal.

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.

3-Head Blend: B13's Architecture

B13 blends two specialist heads per target: an ElasticNet head (trained on symmetric split-score data) and a RAPM Ridge head (25 pure RAPM features). Spread blend weights are 0.57/0.43; total blend is 0.77/0.23. The RAPM head added +0.0125 spread R² once 135 zero-RAPM games were corrected in the data rebuild — the blend was neutral until the data was clean. Linear models continue to dominate over tree-based approaches.

Feature Engineering: 204 Features

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 (spreads)21Team RAPM offense/defense/pace projected from player ratings × minutes
RAPM Features (totals)~30Baseline/projected/delta RAPM for offense, defense, and net — all included via symmetric stacking
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 163 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 (L5, L10, L40) treat all games in the window equally. EWMA (Exponentially Weighted Moving Averages) 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 (fast adaptation, captures hot/cold streaks)
  • h20: 50% weight from last 20 games (medium, balances recency and stability)
  • h40: 50% weight from last 40 games (slow, stable long-term trends)

This gives the model multiple "time resolutions"—it sees both immediate form (h10) and established identity (h40) simultaneously. When league dynamics shift, h10 features adapt in ~10 games while h40 provides stable context.

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. Each player has BOTH offensive and defensive impact, so lineup changes affect BOTH teams' expected scores.

The Formula:

home_off_delta = Σ (player_off_impact × (tonight_minutes - baseline_minutes) / 48)
home_def_delta = Σ (player_def_impact × (tonight_minutes - baseline_minutes) / 48)

Key Concepts

  • Baseline Rotation: The minute distribution the model "thinks" has been playing (50% L10 + 25% L15 + 15% L5 + 10% L40 blend). This represents what's already baked into the team EWMA features.
  • Scenario Rotation: Tonight's projected minutes based on injury reports, lineup confirmations, or synthetic projection.
  • Delta: The difference between scenario and baseline. If a player is playing their usual minutes, delta = 0 (no adjustment). If they're out, delta is negative. If they're returning, delta is positive.

Impact Ratings (Box Score Formula):

off_impact = (PTS + 0.5*AST - 0.5*TOV) / minutes * 48 - league_avg
def_impact = (STL + BLK + 0.5*DREB) / minutes * 48 - league_avg

Elite players have offensive impacts of +3 to +5 per 48 minutes, defensive impacts of +2 to +3.

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

This is why the model uses four delta features per game: home_off_delta, home_def_delta, away_off_delta, away_def_delta. Every lineup change affects both teams' expected scores, not just one.

Availability Discounts:

  • OUT: 0.0 (definitely not playing)
  • DOUBTFUL: 0.15 (unlikely to play)
  • QUESTIONABLE: 0.50 (conservative 50% split)
  • PROBABLE: 0.95 (slight minutes reduction)
  • ACTIVE: 1.0 (full expected minutes)
  • UNKNOWN: 0.80 (no report — assume likely to play)

Projected minutes are computed as: scenario_minutes = baseline_minutes × discount. The delta between scenario and baseline minutes drives the four adjustment features (home_off_delta, home_def_delta, away_off_delta, away_def_delta).

These deltas are pre-prediction features, not post-prediction adjustments. They're included in the feature vector that Ridge/XGBoost sees at training and inference time. The model learns the appropriate coefficient for each delta — how much a given minutes shift actually affects the spread or total.

5. High-Impact Features (SHAP Analysis)

Not all features matter equally. SHAP (Shapley) analysis reveals which features actually drive predictions:

Top 10 Features by SHAP Importance

Which features have the most impact on predictions?

Higher SHAP values = greater impact on model predictions

Low-Impact Features (SHAP < 0.3): Rest features, momentum features, some redundant L5/L15 windows. We keep them for now (removing features requires full retraining/validation), but they're candidates for pruning.

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 run takes ~90 seconds for 10+ games. Most odds updates don't require new predictions—just price changes, not fundamental changes. Selective re-run (every 1 min) completes in ~10 seconds (only 1-2 affected games), reduces API load, and stays within rate limits. Full refresh (every 5 min) ensures all predictions stay current with latest game results and baseline rotations.

Audit Trail:

Every prediction change generates a log entry:

{
  "timestamp": "2025-12-30T18:45:00Z",
  "game_id": "PHI@MEM_2025-12-30",
  "change_type": "player_status",
  "player": "Joel Embiid",
  "old_status": "QUESTIONABLE",
  "new_status": "OUT",
  "old_total": 226.1,
  "new_total": 224.3,
  "delta_applied": -1.8
}

Every change is traceable, auditable, and timestamped.

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 the RAPM blend added measurable spread and total R² gains after a clean data rebuild. The next iteration is always in development.

Validation: How We Know It Works

The only test that matters

We don't train and test on the same period—that's cheating. Instead, we use strict temporal validation:

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

This simulates real production: the model sees the same information it would have pre-game, nothing more.

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.1515Explains 15.15% of spread variance
Total R²0.1328Explains 13.28% of total variance (+19.5% vs B4)

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.

Leakage Tests (Constitutional Requirement)

Every feature must be computable at prediction_timestamp. We run automated tests that ensure no feature uses data from after the game date:

def test_no_leakage():
    """Ensure no feature uses data from after game_date."""
    game = get_test_game("2025-12-30")
    features = compute_features(game, as_of_date="2025-12-30")
    
    # No actual game outcomes should be in features
    assert "actual_minutes" not in features
    assert all(game_dates < game.game_date for game_dates in feature_history)

If this test fails, the model doesn't ship. No exceptions.

Limitations: What This Model Is Not

Honest assessment of what we can't do

1. It's Not a Crystal Ball

R² of 0.13–0.15 means 85–87% 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.

2. 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.

3. It's Blind to Intangibles

Things we don't model:

  • Locker room chemistry/drama
  • Coaching motivation and adjustments
  • Playoff implications and effort level
  • Referee tendencies
  • Tanking incentives (end of season)

These matter, but they're hard to quantify consistently.

4. Totals Are Harder Than Spreads

Even with B13's improved 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. The RAPM blend and lineup disruption features have narrowed this gap.

5. Late-Breaking News Can Beat Us

If a player is scratched at 6:59 PM for a 7:00 PM tip, we might not catch it in time. The market (sharp bettors with inside information) will move faster than our 1-minute polling cycle. This is an inherent limitation of automated systems.

6. Variance Exists

Even with an edge, you'll have losing weeks. Losing months, even. That's not model failure—that's probability. Variance smooths out over hundreds of bets, not dozens.

Technical Philosophy

How we build and maintain trust

Three Non-Negotiable Rules:

  1. No Data Leakage: Every feature uses only data available before prediction time (enforced by automated tests)
  2. Walk-Forward Validation: All model changes tested on held-out future data, never on training period
  3. Full Auditability: Every prediction, every change, every delta calculation is logged and traceable

What 'EV' Actually Means

EV (Expected Value) is not "the model is always right." EV means the model is systematically more accurate than market-implied probabilities across many bets.

If the model says 55% and the market implies 50% (even money), that 5-point gap is positive EV. You'll still lose ~45% of those bets. But over 1000 similar bets, that 5% gap compounds into returns.

This is a tool for disciplined, probabilistic betting—not a magic 8-ball for tonight's winner.

The Bottom Line

Predictium is a statistical tool built on real engineering, tested honestly, and validated strictly. It's Ridge regression and ElasticNet with RAPM roster projections and symmetric split-score prediction, not magic. It has an R² of 0.13–0.15, not 0.90. It will be wrong often on individual bets.

But over hundreds of bets, a consistent edge compounds. If you're looking for guaranteed picks, this isn't it. If you're looking for probabilistic thinking, disciplined bankroll management, and exploiting small edges over time—that's exactly what this is built for.

No fluff. No promises. Just the math.

Ready to Use the Model?

View today's EV opportunities on the Dashboard or explore detailed game breakdowns.

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