How to read the current analytics layer, what data it uses, and how the filtered tables and summary views should be interpreted.
JuniorPuck analytics should be cumulative. The current layer uses transparent, repeatable signals already backed by stored CHL data, then packages them into sortable tables, filtered views, and compact summaries. As more advanced models arrive, they should extend this foundation rather than hide it.
These pages are derived from the live JuniorPuck dataset and should reflect the same season scope as the rest of the site. When a season is selectable, the table or summary should be read in that selected-season context rather than assumed to be current by default.
The current analytics surfaces intentionally rely on existing trustworthy inputs: season totals, game results, roster context, point streaks, and simple matchup comparisons. They are designed as strong public-facing proxies, not a claim that every advanced CHL model already exists in production.
Expected goals (xG) is live for OHL and QMJHL - visible in the player and team analytics tables and on individual shot charts. Each shot is scored by distance and angle using a logistic model trained on CHL play-by-play data. Two metrics build directly on it: finishing (G-xG) on the players page, which measures goals scored above what shot locations predict, and GSAx on the goalies page, which measures goals saved above what the shots faced would predict - per-game expected goals against are attributed to each goalie by their share of that game's shots, and a figure is only published when shot locations cover at least 80% of a goalie's season. Both metrics are calibrated per league and season so that total expected goals match total actual goals - finishing and GSAx are zero-sum within a league, and shootout attempts are excluded.
Team power ratings use the Elo system, computed per league over every stored season (QMJHL from 1990, WHL from 1996, OHL from 1998, playoffs included). Each game moves the winner's rating up and the loser's down by an amount that depends on how surprising the result was: K = 10, scaled by the square root of the goal margin and capped at 2x. Home ice is worth 50 rating points in the expectation, ties (from the pre-overtime era) count half, and between seasons every team regresses one third of the way back to the 1500 league average to reflect junior hockey's roster turnover. Strength of schedule is the average pre-game rating of a team's opponents. Because the three leagues only meet at the Memorial Cup, ratings are calibrated within each league and are never compared across leagues. Playoff odds run 2,000 Monte Carlo simulations of the remaining schedule on top of these ratings: each simulated game's win chance comes from the Elo expectation with home ice, losers keep a point at the league's observed overtime rate, and the top 8 per conference qualify. Before the season's first game, last season's ratings are regressed a third toward average, exactly as the rating system itself does.
Travel totals follow each team's schedule in date order from arena to arena, starting and ending at its home rink, so home stands add nothing and road trips chain city to city. Distances are straight-line kilometres between arenas multiplied by 1.3 to approximate road routes - estimates, not odometer readings. Relocated franchises are placed at their former home city for the seasons before the move. Distances are published from the 2015-16 season onward, where every franchise's home can be reliably placed; a team's total is hidden when less than 90% of its schedule can be placed, and any gap is noted on the table. Memorial Cup games are excluded because they're played at a neutral site. Rest metrics use only game dates: a back-to-back is two games on consecutive days, a 3-in-3 is three games in three nights, and rest days between games are capped at 7 when averaging so holiday breaks don't skew the numbers.