How We Score (per-game model)

An analytical model built for fun and discussion — not advice. Every number is a probability with real uncertainty, not a prediction.

How the Forecasts Work

Simulation Methodology

A technical explainer for readers who want to know how we arrive at the numbers on the league, tournament, and parity pages, including championship odds, playoff-qualification probabilities, and projected final standings.

What this is, and what it isn't. This is an analytical model built for insight and conversation — "how might the season play out, and how sure are we?" It exists purely for entertainment and to explore how well statistical models can describe a youth hockey season — not to inform any decision that matters. Youth hockey is high-variance and our data is thin (about 34 games per team in a season), so every number here is a genuine probability with real uncertainty around it, not a prediction of what will happen.

1. The question the simulation answers

Given the games played so far, we want the probability distribution of ways the rest of the season could go. There is no formula for these numbers — the only honest way to compute them is to play the remaining games thousands of times and count how often each thing happens. That's a Monte Carlo simulation.

Championship probability
How often each team wins its tournament.
Advancement probability
How often a team finishes in a spot that matters — top-2 out of a pool, a parity-tournament bid, a playoff berth.
Projected final standings
The range of places each team could finish.

2. The two kinds of uncertainty (this is the important part)

A good forecast has to account for two separate sources of randomness. This split is a standard idea in uncertainty quantification, and getting it right is the difference between an honest number and an overconfident one.

Game randomness ("aleatoric")

Randomness in the event itself, not in our knowledge of it — even a perfectly-known matchup still has to be played. With only a handful of goals scored in a typical game, an unlucky bounce or two is enough to flip a result that could have gone either way, even between two truly evenly-matched teams.

Rating uncertainty ("epistemic")

Uncertainty in what we know, not in the event — we don't actually know how good each team is, only an estimate from ~34 games, which is not many. The team that looks best on paper might genuinely be the best — or, for example, might have had a friendly early schedule or some good luck go their way.

A simulation that only models the first kind looks far more confident than it should. It effectively says "assume our power ratings are exactly correct, now roll the dice" — and the ratings are not exactly correct. We model both.

Other sources of uncertainty exist too — injuries, lineup changes, a goalie having a hot week — that we don't have the data to quantify directly. We don't pretend to model them by name; instead the bootstrap in Step 2 below naturally widens around any team whose results have been inconsistent, which absorbs some of that unmodeled variance even without identifying its cause.

3. The pipeline, end to end

  1. Rate the teams (Dixon-Coles)

    We fit a Dixon-Coles model, the standard approach for goal-scoring sports. It gives every team an attack rating (how many goals they tend to score) and a defense rating (how many they tend to allow), estimated jointly from every game's final score so that each team's rating is adjusted for the estimated strength of the opponents it actually played — no team's rating is looked up in isolation; all of them are fit together. From any two teams' ratings the model produces the full probability of every possible scoreline. The ratings are then shrunk toward the league average: with only ~34 games of evidence, raw estimates over-react to small samples, so we pull them gently toward "average" by an amount tuned and validated on five years of data. (We're working on a dedicated page walking through why and how — for now, this note is the summary.)

  2. Capture rating uncertainty (the bootstrap)

    To represent the fact that we don't know the ratings, we don't fit them just once. We refit them many times on bootstrap resamples of the season — each resample draws the same number of games at random, with replacement, so each refit sees a slightly different version of the season and produces a slightly different set of ratings. The spread across these refits is our uncertainty about each team's true strength. (In a future version these refits become draws from a Bayesian posterior, which is the same idea done more formally; the bootstrap is the current implementation.)

  3. Play the rest of the season, many times

    For each rating sample from Step 2, we run a share of the Monte Carlo trials. In every trial:

    • Each remaining game is simulated by drawing a random scoreline from the Dixon-Coles probabilities for that matchup.
    • Already-played games are kept as they really happened — we never re-simulate a completed result.
    • Ties that must be broken (a tournament game that can't end level) are resolved by a 50/50 overtime coin flip.
    • Standings are computed with the league's real tiebreaker chain: points → regulation wins → head-to-head (two-way ties only) → goal quotient → regular-season seed.
    • Pool winners advance into the crossover bracket (1A vs 2B, 1B vs 2A), and the bracket is played out to a champion.

    We tally who finished where. Because this step runs across many different rating samples from Step 2, the final tallies fold together both kinds of uncertainty at once.

  4. Turn tallies into probabilities

    A team's championship probability is simply the fraction of all trials in which it won. Advancement and finish-position probabilities are counted the same way.

4. How many simulations, and how precise?

Trials per forecast
50,000
split across the rating samples
Counting error
±0.2pp
far smaller than the rating uncertainty from Step 2

5. How to read the numbers

6. Assumptions and limitations (in plain terms)

7. Reproducibility

Every simulation stores the random seed it used, so any published number can be regenerated exactly. We're working on a technical companion page — pseudocode and diagrams that walk through the simulation step by step — for readers who want to go deeper than this page.

Model Research, coming soon. We're building out a section that will publish the analysis behind the model's design and validation, including the uncertainty-propagation work referenced in Step 2 above.