Under the hood

How it works

Data collection, feature building, the models, calibration and simulation — the whole pipeline, including the parts that limit it.

1.The shape of the system

SportzPRED is four layers stacked on top of each other. Data is collected and refreshed on a schedule; features are built from it when you ask a question; neural network heads turn those features into a shape rather than a number; and that shape is sampled tens of thousands of times to answer whatever you ask next.

The important design decision is the last one. Most prediction tools compute a number and stop. This one computes a distribution and keeps the samples around, which is why changing a line or a range re-answers instantly instead of re-running a model.

4

Pipeline layers

Data → features → heads → simulation

9

Models

One matchup, seven props, one combiner

13

Nightly refresh phases

20k+

Simulations per run

Where every probability comes from

2.Layer 1 — where the data comes from

Several licensed data sources feed a single database that everything else reads from.

Live statistical feeds

Commercial sports-data providers supply schedules, rosters, team box-score totals and per-player game logs for both the NBA and college basketball. Each feed is polled on its own schedule and rate limit, then normalised into one internal shape so the models never have to care which provider a given number came from.

Player statistical profiles

Live stats tell you what a player has done; they say much less about a player with no recent record — a rookie, a returning injury, an incoming freshman. So each player also carries a rated statistical profile covering shooting, finishing, defence, rebounding, playmaking, athleticism and durability.

Those statistics capture ability that recent game logs cannot. Interior and perimeter defensive strength is what lets the model respond when you swap one rim protector for another, even if neither has faced this player recently.

Derived layers

On top of the raw feeds, the database holds computed layers rebuilt on a schedule: team offensive and defensive ratings, per-minute production, form scores, per-stat feature caches and opponent-environment caches.

3.Layer 1b — the nightly refresh

A scheduled job runs at 06:00 US Eastern every day and walks thirteen phases in order. It is incremental: each phase looks for what is missing rather than rebuilding the season, so a normal night touches only the games that actually happened.

PhaseWhat it doesCalls the live feed
ATeam game totals for all 30 teams, threaded 5 waysYes
A.5Roster sync for all 30 teamsYes
GRecompute team offensive and defensive ratingsNo
BPlayer stats for teams with new games, with a totals-comparison fallbackYes
CRetry any database writes that failed in phase BNo
DRecompute per-minute production for every active player cardNo
EHotness: game logs, player form, and player-versus-opponent historyYes
FPoints dynamic-feature cache + opponent defensive-rating cacheNo
HRebounds dynamic-feature cache + opponent rebounding-environment cacheNo
I3-point dynamic-feature cacheNo
JBlocks dynamic-feature cacheNo
KAssists dynamic-feature cacheNo
LSteals dynamic-feature cache (last five games)No

Two design choices are worth calling out. First, each phase is isolated — if one fails it is logged and the run continues, so a single upstream hiccup cannot cost you the whole night's data. Second, the scheduler is opt-in per host: only the one machine with the scheduler flag set actually fires the job, so running extra replicas never means refreshing the same data several times over.

What this means when you use the tool

Everything the models know was true as of the last completed refresh. Nothing that happened this morning — a late scratch, a rest decision, a trade — is in the numbers yet. See how to misread a SportzPRED number.

4.Layer 2 — building the features

When you press predict, the scenario you described is turned into a numeric feature vector. It draws on both the nightly-refreshed tables and the choices you made on the page:

  • Form and usage — dynamic features computed from recent game logs rather than season averages, so a player in a changed role is not modelled as his October self.
  • Hotness — whether he is running above or below his own season baseline, blending recent games with his history against this specific opponent, and shrinking toward the baseline when the sample is small.
  • Opponent environment — the opposing team's defensive rating, and for rebounds the opposing rebounding environment, cached nightly.
  • The matchup you built — the five opposing starters and their statistical profiles, the defensive scheme, which defender picks him up, who rotates to help.
  • Game context — minutes, home or away, attendance (entered signed by venue, so it carries a home-court effect), and the game environment that decides whether this is a 48-minute or 40-minute game.

Minutes dominate

Minutes are the largest single input to any counting stat. They are auto-filled from recent games where the data exists, and capped by the game environment. If you override them, you are making the most consequential edit available to you.

5.Layer 3 — the model heads

The feature vector goes into trained neural networks. Separate weights are loaded per position, so a centre and a point guard are not scored by the same model.

Each stat runs more than one head, because one head cannot do the whole job:

  1. 1

    Quantile head

    Predicts the entire shape of the outcome in one pass, from the low end to the high end, rather than a single number. This is what makes a distribution possible rather than a point estimate with error bars bolted on.

  2. 2

    Hurdle head

    Predicts two things separately: whether the stat happens at all, and how much of it there is when it does. This matters enormously for low-count stats — blocks and steals are mostly zeros, and a model that treats them as continuous gets both the mean and the shape wrong.

  3. 3

    Combination head

    Blends the quantile and hurdle outputs into the final distribution, weighted by which one the model trusts in this regime.

When a player's recent game logs are too thin to build reliable dynamic features, the pipeline falls back to profile-driven estimates rather than refusing to answer. That is what makes retired players and incoming freshmen predictable at all.

6.Layer 3b — calibration and recentering

Raw model output is not ready to sample from. Several corrections run first:

  • Monotonicity. A quantile vector must never decrease — the 60th percentile cannot be below the 59th. Networks occasionally violate this, so the vector is forced monotonic.
  • Winsorization. Extreme tail quantiles are trimmed so a single wild estimate at the 99th percentile cannot dominate the simulated spread.
  • Head calibration. The hurdle head's output is calibrated against the classical estimate so the two heads are on a comparable scale before blending.
  • Mean anchor. The distribution is pulled toward a blended season-and-recent mean. On by default; it disables itself for legacy cards, which have no current-season mean to anchor to.
  • Probability calibration. Stated probabilities are mapped so they match observed frequencies — the difference between a model that ranks outcomes well and one whose 60% actually happens about 60% of the time.

Why calibration is the part that matters

A model can be excellent at ranking and still be badly wrong about how confident to be. Ranking tells you which side looks better; calibration is what makes the probability attached to it mean anything.

7.Layer 4 — the simulation

The calibrated quantiles are sampled by inverse-transform: draw a uniform number, read off the quantile it lands on, repeat tens of thousands of times. Every probability the site reports is a frequency counted over those samples.

ModelSamples per runNotes
Team Matchup25,000Home and away score samples drawn jointly, with shared game-factor noise
Player props20,000Points, rebounds, assists, 3PT, blocks, steals, turnovers
Combo Props30,000Each stat resampled from its own marginal, then summed
Win simulation1,000Separate head-to-head runs blended with two other estimates

Team games are not two independent teams

For a matchup, sampling home and away scores independently would produce nonsense: real games have a shared character — pace, officiating, whether the ball is going in for anyone. So a shared game-factor noise term is injected into both teams' samples, which correlates them the way real halves of a game are correlated. The spread of the total and the spread of the margin are then calibrated separately against profile-derived targets, because getting the total right does not automatically get the margin right.

Win probability blends three estimates

Rather than trusting one method, win probability combines a head-to-head score simulation, a separately calibrated classifier, and the probability implied by the spread model's own distribution — weighted into a single number. Where the spread distribution is uncertain, the simulation deliberately widens its sampling to avoid false confidence.

8.The three-stage architecture

A prediction is split into three stages so the expensive work happens once and the questions afterwards are nearly free.

  1. 1

    Stage 1 — heavy, once per scenario

    Load model artifacts, build features, run the heads, shape the tails, recenter. This is the part that takes real time.

  2. 2

    Stage 2 — sampling, once per scenario

    Turn the calibrated quantiles into the sample arrays. Moderate cost, and it happens immediately after stage 1.

  3. 3

    Stage 3 — instant, as many times as you like

    Over/under against a line and price, probability of a range, spread cover probabilities, win simulation, box-score allocation. Each is a query over samples that already exist.

The practical consequence

Set the scenario once, then interrogate it. Typing a different sportsbook line, checking a range, or flipping to another analytics tab does not re-run the model — it re-reads the same simulation. That is the whole reason for the split.

9.How a request actually runs

Heavy predictions are not synchronous HTTP calls. The API accepts the request, hands it to a worker pool, and returns a job identifier immediately; the page then polls for progress and renders the result when it lands. That is why you see a progress bar with named steps rather than a spinner and a timeout.

  • POST /api/predict and the per-stat equivalents return { job_id } straight away.
  • GET /api/job/{job_id}/status reports status, a human-readable step and a percentage.
  • Jobs run on a four-worker thread pool and are cleaned up on a time-to-live.
  • Stage 3 endpoints are synchronous — they answer from existing samples, so there is nothing to queue.

Every request and every job is measured: wall time, compute time, time spent waiting on upstream feeds, database query counts, memory and peak memory. That telemetry is what sizes the infrastructure. It contains no information about you — see the Privacy Policy.

10.Attribution — why the number is what it is

A projection on its own does not tell you whether it is high because the player is good or because the defence is bad. Attribution answers that by splitting the projection into three contributions — Dime, Poor Defense and Support Skill — using the Shapley method from cooperative game theory.

The method works by re-evaluating the model across every combination of those three groups and measuring how much each one adds on average across all the orderings. That is genuinely expensive, which is why attribution runs as a separate job you trigger rather than automatically with every prediction.

The result is also reported at a quantile of your choosing, so you can ask what drives a median night versus what drives a 90th-percentile one. They are frequently not the same thing.

11.What this design cannot do

Every architecture buys some things by giving up others. These are the trades this one makes, stated plainly.

  • No live or in-game updating. Predictions are built from data as of the last refresh. Nothing updates while a game is in progress.
  • No news awareness. The models read box scores and rosters, not injury reports, press conferences or beat writers. The market usually knows first.
  • Combo Props assumes independence. Combined lines resample each stat on its own and add them, so correlation between a player's stats is not captured and the combined range is narrower than reality.
  • The scenario is your responsibility. Minutes, starters and scheme are inputs you control and they move the answer substantially. The model cannot tell you that the lineup you built is unrealistic.
  • Simulation noise is real. Results are reproducible for a given seed, not identical across seeds. If an edge disappears when you change the seed, it was noise.
  • Calibration is aggregate, not per-case. A model calibrated across a season is not automatically calibrated for one unusual player in one unusual spot.

Worth repeating

A well-calibrated 60% is supposed to lose four times in ten. None of the machinery above changes that. It is a tool for reasoning about uncertainty, not for removing it.

For what the models do and do not currently reach, see What we cover. For definitions of any term used here, see the Glossary.