Pre-registered before the season opens, honestly evaluated when it closes.
Resolve Research builds projection models for sports and research tools for the broader world. This page is the apex framework: the rules that hold across every model we ship. Per-sport methodology lives on each sport's own subdomain (linked below).
What "honest" means here
Every projection is published with its model spec, its training window, and its out-of-sample (OOS) calibration number, before the predictions are evaluated. We don't tune to live results, we don't quietly swap models mid-season, and when a model misses we say so in the next release notes.
The general loop:
- Pre-registration. Model spec + projection set frozen and timestamped before the relevant games are played. Edits after kickoff are flagged in release notes, not silently shipped.
- Out-of-sample testing. Every engine reports a holdout-set calibration number (Brier score, log-loss, or per-domain equivalent). If we can't measure it on data the model didn't see, we don't claim it works.
- Equity-first roll-out. When we ship a new sport, the women's league ships at the same fidelity as the men's. WNBA, NWSL, PWHL, LPGA, NCAA-W, WTA: same engine class as their counterparts, same release cadence.
- Open release notes. Every model version, what changed, and the date it shipped. No silent edits.
Where our data comes from
Our projection inputs start with public data: official league box scores, schedule feeds, Elo-rateable match results, and (for tennis) the public Wimbledon / ATP / WTA draws. We leverage data from SportsDataIO to bring you the most up-to-date and accurate data for the NFL, NBA and WNBA. We don't scrape paywalled sources, and every model stays auditable end-to-end.
Training windows vary by sport, published per-spoke. For each engine we note the data origin, the season range used to fit, and the season range held out for OOS evaluation.
How we avoid fitting to noise
Sports prediction is a high-variance, low-sample problem. The three guardrails we lean on:
- Separate SE from prediction SE. Confidence intervals on a metric are not the same as confidence intervals on the prediction it feeds. We label both and don't conflate them.
- Per-archetype aging curves. Players age differently by role. Slot-based aging beats one-size-fits-all curves; we publish the per-archetype splits.
- Shrinkage for small samples. First-year college transitions, new-surface tennis appearances, and rookie-NBA priors all use shrinkage toward the relevant population mean. The shrinkage strength is a named lever in the spec, not a hidden constant.
Sport-specific spokes
Each subdomain has its own methodology page detailing the engine, data sources, training window, and OOS calibration for that sport.
Code, data, write-ups
Model code lives on GitHub. Long-form research write-ups (substantive findings, methodology deep-dives, failure post-mortems) are on Substack. Per-sport release notes are linked from each sport's subdomain home.
What we don't claim. We do not have private player-tracking data, biomechanical signals, or an inside line on injuries. Injury and status information comes from SportsDataIO's licensed feeds and the leagues' official reports, and our daily projections are adjusted for the latest listed statuses. Once a pick locks it is never revised: what's pre-registered is what we evaluate against.
Where the limits are. Single-game predictions on a 16-game season (NFL) are wide-CI by construction. Tennis draws are dominated by 5-7 players in any era. Soccer Elo is calibrated on club football and ported to international duty with shrinkage; that port is a known weak point. We label these limits per-page, not just here.