SportsOwl

Where the data comes from

Every number starts as an official per-game NFL stat line — targets, receptions, yards, touchdowns, carries — from nflverse, the open-source NFL data project used across the analytics community (licensed CC-BY 4.0, pulled via the nflreadpy package). No scraped websites, no hand-entered stats, no expert opinions. The pipeline pulls seasons 2021–2025, verifies them against known references, and caches them locally. Every run is deterministic: the same inputs always produce these exact numbers, byte for byte.

How a projection is built

Score every real game. Each player’s actual game logs are converted to fantasy points under the exact scoring format you’ve selected — the four formats are computed separately, which is why rankings genuinely change when you toggle.
Weight recent seasons more. Games decay by season (half-life ≈ 1 season): a 2025 game counts about 4× a 2023 game. The half-life was tuned on the leakage-safe backtest to best order the draft-relevant top-100 — more weight on recent form (and recent decline).
Age-adjust every game. Each sampled game is translated from the age the player produced it at to his 2026 age along an empirical positional aging curve (QB/RB/WR/TE), fit on 2011–2025 within-player production — RBs and WRs decline sharply after 30, QBs and TEs gently. This corrects the old model’s over-ranking of aging veterans; it is backtested math, never a per-player hand tweak.
Re-base players who changed teams. A player who switched teams produced his past numbers in a different offense. We re-base his projected volume to his 2026 team’s tendencies — that team’s targets and carries per game — times his own recent role share, holding his efficiency. So a receiver joining a run-heavy offense is projected on fewer targets, not his old team’s. Backtested; players who stayed put are untouched.
Model availability. How many of 17 games the player is likely to play, from their own missed-game history shrunk toward position base rates (RBs miss more than QBs) — no subjective “injury grades.”
Simulate 10,000 seasons. Each simulated season draws a number of games played, then samples that many real games from the player’s weighted history and sums them. The result is the full curve you see in each player’s profile — not a single guess.
Read off floor, median, ceiling. Floor = 10th percentile, median = 50th, ceiling = 90th. Rookies use historical outcomes of similarly drafted players; thin samples blend toward positional archetypes — both always flagged.
Rank by value over replacement (VOR). A player’s median minus the median of the best freely available player at his position in a 10-team lineup. VOR is what makes cross-position ranks comparable — it measures the points you gain over what you could get anyway.

Is it accurate? The backtest, honestly

Before trusting the model, we made it predict the past: for each season 2022–2025 it projected players using only data available before that season (enforced by automated leakage tests), then was scored against what actually happened. Here is the honest weakness first, then where it holds up.

Known weakness: the ranges are too narrow

The floor→ceiling bands should contain ~80% of real outcomes; in backtests they contained ~43%, and the misses skew low — real seasons collapse (injury clusters, benchings, role loss) more often than the model’s independent-game math allows. Trust the order of players more than the width of the bands, and mentally extend floors downward, especially for injury-prone players. The M1 model update targets exactly this.

Update (M1): the over-ranking of aging veterans this section used to flag is largely addressed — projections are age-adjusted along empirical positional curves and weight recent form more heavily (see the steps above), which cut the 30-and-older cohort’s backtest error without hurting rank accuracy. One lever remains: the model does not yet reflect a player’s role or opportunity. Where we still rank a 30+ player well above his market ADP, that gap — flagged with a — may be a role signal the model can’t see yet; the roles update targets it. Band width (the ~43% above) is also still open.

Where it does hold up — draft ordering is strong and consistent across positions:

Rank accuracy (Spearman)
0.72
projected vs actual finish, pooled Double PPR, 4 seasons — strong draft ordering
Median error
51 pts
avg. miss on season totals (≈3 pts/game in Double PPR)
Consistent by position
.67–.75
QB .67 · RB .73 · WR .75 · TE .75
Double PPR by season (leakage-safe, 10,000 sims/player)
SeasonSubsetnSpearmanMAE80% cov50% cov
2022overall5040.72551.80.420.23
2022top-1001000.48978.10.370.24
2023overall4850.72153.10.410.25
2023top-1001000.55968.50.480.34
2024overall4990.72853.00.400.22
2024top-1001000.22776.20.400.28
2025overall5030.74747.00.470.27
2025top-1001000.29281.40.480.26
POOLEDoverall19910.73251.20.430.24
POOLEDtop-1001000.37185.30.410.30
Pooled Double PPR by position (all backtest seasons)
PosnSpearmanMAE80% cov50% cov
QB2700.67365.30.320.21
RB5120.72751.10.430.26
WR7620.75154.10.440.25
TE4470.75137.80.460.23

Spearman = rank correlation between projected median and actual total (higher is better). MAE = average absolute error in fantasy points (lower is better). 80% / 50% cov = share of actual totals inside the projected [p10,p90] / [p25,p75] bands (well-calibrated ≈ 0.80 / 0.50; below target = bands too narrow).

What the flags mean

R — rookie prior. No NFL games exist, so the projection is built from historical rookie seasons of players drafted at a similar slot and position. Honest but wide; backtests show these run ~19 points conservative on average.
LS — low sample. Under 16 NFL games since 2021; blended toward a positional archetype so a hot 10-game stretch can’t top the board.
NT — new team. History was produced elsewhere; the model deliberately does not adjust for scheme/team changes yet (M1 will). Apply your own judgment here.

What this model deliberately ignores (for now)

No strength of schedule, no coaching-scheme projections, no preseason hype, no expert consensus, no opponent/matchup logic. That is a feature at this stage: everything in these ranks is traceable to real games and arithmetic you can audit. The roadmap layers context on in stages, each validated by the same backtest before it ships:

M1 — opportunity & context. Team/scheme and opportunity inputs plus a clustered availability model to widen and lower floors — directly targeting the calibration weakness above.
M2 — comparable-player career modeling. Analog-based trajectories for aging curves and breakouts.
M3 — market signals. Draft-market information folded in as a check, never as the projection itself.

Transparency is the brand — the goal is that every number on this site is traceable to real games and arithmetic you can audit.