0/70 completed
Sports Model Interactive

Player Projections

Build player stat projections using usage, matchup, and context features. The foundation for pricing player props and DFS projections.

๐Ÿ€ Select Player

Projection Weights

Season Average 0.4
0 0.8
Recent Form (Last 5) 0.4
0 0.8
Matchup Factor 0.2
0 0.5
Total Weight
100%

Contextual Adjustments

Minutes Adjustment 0 min
-5 min 5 min
Matchup Quality 0
-5 5
Pace Factor 0
-5 5
Rest Days Bonus 0
-2 3
Vegas Total 225
200 250

๐Ÿ“Š Projection for Jayson Tatum

Season Avg
26.5
Recent Form
28.4
Adjusted Projection
27.7
Line: 26.0 | OVER Prob
60.4%
Line: 26.0 | UNDER Prob
39.6%

Projection Distribution

5th Percentile
17.7
Median
27.6
95th Percentile
37.9

Recent Game Log

๐Ÿ”ง Projection Feature Categories

Usage Features

  • โ€ข Minutes per game
  • โ€ข Usage rate
  • โ€ข Field goal attempts
  • โ€ข Touches per game
  • โ€ข Shot distribution (paint/mid/3pt)

Matchup Features

  • โ€ข Opponent defensive rating
  • โ€ข Position-specific defense rank
  • โ€ข Opponent pace
  • โ€ข Recent opponent performance vs position
  • โ€ข Key defender assignments

Context Features

  • โ€ข Vegas total / spread (implied game script)
  • โ€ข Home / away
  • โ€ข Rest days
  • โ€ข Back-to-back indicator
  • โ€ข Teammate injuries

โš–๏ธ Weighting Strategies

Recency Weighting

Recent games often more predictive. Common approaches:

  • โ€ข Linear decay: Weight = (N - game_age) / N
  • โ€ข Exponential: Weight = ฮป^game_age
  • โ€ข Rolling window: Last 10-20 games only

Regression to Mean

Extreme recent performance tends to regress. Apply shrinkage:

  • โ€ข Bayesian: Prior = season avg, update with recent
  • โ€ข James-Stein: Shrink toward group mean
  • โ€ข Empirical: Calibrate on historical variance

R Code Equivalent

# Player projection model
library(dplyr)

# Feature engineering
player_features <- player_games %>%
  group_by(player_id) %>%
  mutate(
    # Rolling averages
    season_avg = mean(points),
    last5_avg = zoo::rollmean(points, k = 5, fill = NA, align = "right"),
    
    # Recency weighting (exponential)
    recency_weight = 0.9 ^ row_number(),
    weighted_avg = sum(points * recency_weight) / sum(recency_weight)
  ) %>%
  ungroup()

# Build projection
build_projection <- function(player, game_context) { 
  proj <- 0.4 * player$season_avg +
          0.4 * player$last5_avg +
          0.2 * (player$season_avg + game_context$matchup_adj)
  
  # Apply adjustments
  proj <- proj + game_context$minutes_adj * 0.8
  proj <- proj + (game_context$vegas_total - 220) / 20 * 1.5
  
  return(proj)
}

# Simulate distribution
simulate_player <- function(projection, std_dev, n = 10000) { 
  sims <- rnorm(n, mean = projection, sd = std_dev)
  over_prob <- mean(sims > player$line)
  return(list(projection = projection, over_prob = over_prob, sims = sims))
}

โœ… Key Takeaways

  • โ€ข Blend season average with recent form
  • โ€ข Usage features are most predictive (minutes!)
  • โ€ข Vegas totals encode valuable information
  • โ€ข Apply regression to mean for hot/cold streaks
  • โ€ข Simulate distribution, not just point estimate
  • โ€ข Calibrate weights on out-of-sample data

Pricing Models & Frameworks Tutorial

Built for mastery ยท Interactive learning