The Predictive Playbook – Weekly QB Fantasy Point Projections

Posted by:

|

On:

|

Welcome to the first weekly QB projection model for the Predictive Playbook series! This post covers the data, features, modeling choices, validation results, and some important Week 1 caveats—plus what’s coming next (WR, RB, TE).

🔗 GitHub repo: https://github.com/ndbryant21-eng/fantasy-football-ml


🎯 TL;DR

  • Goal: Predict weekly QB fantasy points before kickoff.
  • Best model: XGBoost (with light post-hoc calibration).
  • Metrics (holdout): ~RMSE 7.8, MAE 6.3, R² 0.26.
  • Week 1 warning: Prior-season context & role uncertainty can bite; things normalize by Week 2+ as 2025 data rolls in.
  • Roadmap: Replicate the pipeline for WR/RB/TE and publish weekly dashboards + recaps.

🧱 Data & Target

  • Source: nfl_data_py weekly player stats + schedules & betting lines.
  • Target (standard scoring):
    0.04*pass_yds + 4*pass_td − 2*int + 0.1*rush_yds + 6*rush_td
  • Split strategy: Season-wise (train on past seasons, validate on held-out seasons, test on final holdout) to mirror real forecasting.

🧩 Features (what the model “sees”)

Recent form (L3 = last 3 games):

  • 🔹 Volume & efficiency: att, cmp, pass_yds, pass_td, int, sacks, sack_yds
  • 🔹 Rushing: rush_att, rush_yds, rush_td, rush_yds/att
  • 🔹 Rates: yds/att, td_rate, int_rate
  • 🔹 Ball security: fumbles, fumbles_lost (raw + per-attempt variants)

Opponent pass defense (EWM = exponentially weighted):

  • 🔹 Defensive YPA allowed (weighted EMA)
  • 🔹 Defensive pass TD rate allowed (weighted EMA)

Opponent QB rushing defense (EWM):

  • 🔹 QB rush YPA allowed (weighted EMA)
  • 🔹 QB rush TD rate allowed (weighted EMA)

Game context:

  • 🔹 Vegas implied team total
  • 🔹 Home/Away flag

📌 Why EWM? It puts more weight on recent games, so defenses and roles that change are reflected faster.


🤖 Model Bake-Off

  • Random Forest: solid baseline, but slightly worse error and less calibrated tails.
  • XGBoost (winner): best accuracy and ranking; handles feature interactions well.
  • Calibration: a simple linear “calibrate-on-validation” pass tightens residuals (reduces global over/under-bias without overfitting).

Metrics snapshot

  • Validation: RMSE 7.73, MAE 6.12, R² 0.247
  • Test: RMSE 7.84, MAE 6.30, R² 0.260

🧪 How I Evaluate

  • Holdout by season to avoid within-season leakage.
  • Error metrics: RMSE, MAE, R².
  • Sanity checks: Feature importances consistently highlight L3 passing volume/efficiency, opponent YPA/TD rate allowed, QB rushing, and implied total—exactly what you’d expect.

🚨 Week 1 Caveats (Why it’s tricky—and why it’s okay)

  • Starters & roles: Depth charts finalize late; some Week 18s last year were rest weeks for playoff teams.
  • Player movement: New teams/OCs/rookies can shift usage quickly.
  • Fallback logic: If the current slate is sparse, I synthesize Week 1 rows using 2025 schedule + 2024 priors (with an option to manually override expected starters by team).

Good news: From Week 2 onward, rolling windows and defensive EWMs are fed by 2025 data, so the model adapts quickly. By Weeks 2–3, most Week 1 quirks fade.


📈 Output & Tiers

Each weekly CSV includes player_name, team, opp_team, proj_fp, and a tier overlay to make decisions digestible:

  • ⭐ Elite: ≥ 20 FP
  • 💪 Strong: 16–20 FP
  • ✅ Start: 12–16 FP
  • 🧰 Stream: 8–12 FP

Tiers are just an overlay for readability—you can always sort by raw projection.


📂 What’s in the Repo

  • Notebooks: data collection, exploration, and the weekly runner
  • Artifacts: XGBoost model (.json), calibration (.joblib), feature list (.json)
  • Outputs: weekly CSVs in outputs/ (e.g., qb_2025_wk01_projections_pregame.csv)

🔗 GitHub repo (again for easy click): https://github.com/ndbryant21-eng/fantasy-football-ml


🛣️ Roadmap

  • Weekly publish & recap: Post projections pre-slate and a short post comparing projections vs actuals after games.
  • Dashboard (🚧): A lightweight page that loads the latest CSV, supports start/sit comparisons, and shows matchup/context snippets.
  • Next positions: I’ll spin up WR, RB, and TE using the same methodology:
    • L3 role/usage (targets, share, YPRR for WR/TE; carries + targets for RB)
    • Opponent defensive rates by position (EWM)
    • Context (implied totals, pace proxies)
    • Model bake-off → likely XGBoost + calibration again

🧠 Closing Thoughts

This v1 QB predictor is accurate enough to be useful and transparent enough to iterate fast. Week 1 is always the most assumption-heavy; that’s fine. The pipeline is built to learn quickly from new data.

Next up: 🧠 WR, 🧠 RB, and 🧠 TE weekly projections, plus a clean dashboard to make start/sit decisions more grounded.


📥 Download & Data — Week 1 CSV

Posted by

in