← All projects

October 10, 2026

Building an NFL player prop engine from scratch

How I originate my own lines for QB, RB, WR and TE props with a full-game Monte Carlo simulator. No sportsbook inputs go into the model; prices are only compared afterward.

NFLMonte CarloSimulationPython
Live trackerNFL Player PropsFull tracker →

Record

163-132

Units

+27.50u

ROI

+9.3%

Most prop models start from the sportsbook line and nudge it. I wanted the opposite: an engine that originates a full probability distribution for every player stat using football data alone, then compares it to the market only at the end. If the model never sees a price, it can't learn to agree with one.

Data

The engine sits on a historical warehouse covering more than a decade of NFL football: play-by-play, player and team box scores, participation, and roster history, plus historical sportsbook quotes for pricing. Every input is versioned and cached by content hash, so any run can be reproduced exactly from the same inputs.

Architecture

  1. InputFootball data, as of kickoffNo market inputs
  2. SimulateGame environment + correlated uncertaintyBoth teams move together
  3. AllocatePersonnel → joint opportunityOne fixed budget per roster
  4. ProducePlayer efficiency → full stat distributionsEvery stat from the same game
  5. PriceDistributions vs. the market → the cardStrongest disagreements only
  6. VerifyRunTheSims cross-checkA second, independent engine
01

Game environment

Projects how much offense each team will run and how it splits between dropbacks and runs. Trained only on football information, with market-derived inputs explicitly blocked, so a sportsbook's opinion can't sneak in through the back door.

02

Correlated uncertainty

Props live in the tails, so a point forecast isn't enough. Uncertainty is carried at the game level: a script that inflates one offense's volume shows up on the other side too, the way it does in real football.

03

Personnel

Tracks depth roles and availability as of kickoff, using only information that was public at the time. When a starter is out, his volume goes to whoever inherits the role, and on defense it accounts for how missing players change what an offense can do.

04

Opportunity

Volume is allocated jointly from a fixed budget. A receiver's targets can't rise without someone else's falling, which independent per-player models can't guarantee, and it's a common source of mispriced correlated props.

05

Efficiency

Each player converts opportunities into production through his own history, with sensible behavior when that history is thin. Passing and receiving come from the same simulated events, so a QB's yards always reconcile with what his receivers caught.

06

Pricing

Tens of thousands of simulated games give every player a full distribution for every stat. Each line is priced from it, with pushes and non-participation handled explicitly rather than treated as zeros.

The weeks 1–4 replay on the tracker ran on the base engine, before the personnel layer was added.

Direction over calibration

The engine isn't built to be calibrated. It's built to be right about direction.

Its raw probabilities run more confident than reality, so its expected value isn't a literal forecast of return. Where it shines is directionality: when it strongly disagrees with the market, it's usually right about which side of the line the player lands on.

So the model's EV is a ranking of disagreement, not a promise. Only the strongest disagreements make the card: plays where the model's EV is 40% or more.

Verification: a second layer

A single model can be confidently wrong in ways it can’t see. So every play is cross-checked against RunTheSims, an independent simulation engine.

Both engines agree

Two separate simulations land on the same side of the line, so the pick earns more confidence.

The engines diverge

A signal to dig into the inputs (a role change, a stale injury report, a weird game script) before trusting the number.

The second layer isn’t there to make the model agree with consensus. It’s there to catch the failure modes a single engine is blind to.

Leakage controls

Backtests on sports data leak easily, so most of the engineering went into making history behave like a real pregame snapshot.

  • As-of data onlyEvery input is limited to what was available before kickoff, with a conservative reporting delay on prior games.
  • Frozen player poolThe current game's lineup, snaps and outcomes never decide who gets projected.
  • Perturbation testsScrambling current and future outcomes to extreme values leaves every projection unchanged.
  • Quote integrityEvery market quote is time-checked against kickoff and hashed.
  • Automated testsA large test suite, plus accounting checks on every simulation.

What’s next