Methodology
How the Luck Index works, sport by sport, and what each number means.
The Core Principle
Every sport has a way to measure what should have happened vs what actually happened. A team that outperforms expectations is lucky. A team that underperforms is unlucky.
The "expected results" model is different for each sport, but the principle is always the same: how many points or wins does a team deserve based on what happened on the field/ice/court? If they have fewer than expected, they're unlucky. If they have more, they're lucky.
How It Works Per Sport
Soccer (Premier League, La Liga, Ligue 1)
Every shot in football has a probability of being a goal based on its location, angle, body part, and game situation. This is called xG (Expected Goals). A penalty = ~0.76 xG. A 30-yard shot = ~0.03 xG.
For each match, both teams' xG is used to estimate win probabilities, which converts into xPTS (Expected Points). Sum it over a season and you know what the team deserves. The same model applies to all soccer leagues we cover.
Hockey (NHL)
We combine Pythagorean expectation (expected wins from goals scored/allowed) with MoneyPuck's expected goals model, which evaluates the quality of every shot attempt.
We normalize for the NHL's loser point system (OT losses = 1 pt) so league totals balance out.
Basketball (NBA)
The Morey exponent (13.91) is much higher than hockey (2) because basketball is the most skill-driven major sport. We layer in close-game records and home/road splits to capture luck in tight situations.
Baseball (MLB)
Baseball's Pythagorean expectation (exponent 1.83) estimates expected wins from runs scored and allowed. We enhance this with Statcast data from Baseball Savant, which uses exit velocity and launch angle to calculate what should have happened on every batted ball.
A team hitting line drives right at fielders all season has a high xwOBA but low actual wOBA - that's batting luck. Similarly, xERA measures pitching quality independent of defensive luck and sequencing.
Luck Tiers
After computing the raw luck score, we normalize it across all teams in the league using z-scores and scale to -100 to +100. Teams are then assigned to one of five tiers:
Historic bad luck. This team is being systematically robbed. Their record is significantly worse than their performance warrants. Strong regression expected - they're almost certainly better than their table position suggests. Think of a team that hits the post 15 times, loses 8 one-goal games, and has 3 goals disallowed by VAR. That's Cursed.
Meaningfully underperforming. Roughly 2-4 wins below true talent level. Things aren't going their way, but it's not catastrophic. A normal season's worth of bad breaks. Regression is likely but not guaranteed in the short term.
Results match performance. This team is where they deserve to be. Some noise in either direction, but nothing systematic. Their record is an honest reflection of their quality.
Overperforming. 2-4 wins above true talent. They're winning close games, opponents are missing chances, and bounces are going their way. Enjoy it - the data says this won't last.
Unsustainably fortunate. This level of overperformance almost never persists from one season to the next. The gap between results and process is so large that regression isn't just likely - it's almost certain. These teams are playing with house money.
Key Metrics Glossary
| Metric | Sport | What it means |
|---|---|---|
| Luck Index | All | The composite score from -100 to +100. Negative = unlucky, positive = lucky. Normalized across all teams in the league. |
| xPTS Δ | Soccer | Actual points minus expected points. A delta of -12 means the team has 12 fewer points than they deserve. This is the raw number, not normalized. |
| Pyth Δ | NHL/NBA/MLB | Actual points (NHL) or wins (NBA/MLB) minus Pythagorean expected value. Same idea as xPTS Δ but using goal/point/run differential instead of xG. |
| xG | Soccer | Expected Goals. The probability-weighted sum of all shots. 2.5 xG means the chances created were worth 2.5 goals on average. |
| xPTS | Soccer | Expected Points. Result of simulating each match thousands of times based on xG. More robust than xG alone because it captures game context. |
| Pythagorean | NHL/NBA/MLB | Expected win% from goals/points/runs scored and allowed. GF^n / (GF^n + GA^n). Exponent: 2 for NHL, 13.91 for NBA, 1.83 for MLB. |
| xwOBA | MLB | Expected weighted on-base average. Based on exit velocity and launch angle of every batted ball. Measures contact quality independent of outcomes. |
| xERA | MLB | Expected ERA based on batted ball quality. Strips out defense, sequencing, and BABIP luck to isolate true pitching performance. |
| Shot Quality | NBA | Expected eFG% from shot locations (restricted area, paint, mid-range, 3PT) vs actual eFG%. Separates shot selection from shooting luck. |
| Pos | All | Actual league standing by points or wins. Compare this to the Luck Index rank - big gaps indicate luck is at play. |
Can You Trust It?
Regression to the mean
The strongest validation: teams with extreme Luck Index values almost always regress the following season. A "Cursed" team typically improves by 5-10 points without changing anything. A "Blessed" team typically drops. This has been observed consistently across decades of data in every sport.
Non-persistence
A good luck metric should NOT persist year-over-year. If a team is "unlucky" every season, the metric is measuring skill, not luck. The Luck Index has near-zero autocorrelation (r < 0.15), meaning this season's luck tells you almost nothing about next season's.
Academic foundation
Built on established research: Bill James' Pythagorean expectation (1980, validated across 40+ years), StatsBomb's xG model (industry standard used by professional clubs), Dean Oliver's basketball analytics, and Michael Mauboussin's skill-luck decomposition framework.
The feel test
If a fan looks at the Luck Index and says "that doesn't feel right," we have a problem. The algorithm is designed so the anchor metric (xPTS or Pythagorean) captures the big picture, and supporting signals explain why. The result should match what fans intuitively sense when they watch the games.
Data Sources
| League | Source | Model | Update |
|---|---|---|---|
| ⚽ EPL / La Liga / Ligue 1 | API-Football | xG + xPTS (7 signals) | Daily |
| 🏒 NHL | NHL API + MoneyPuck | Pythagorean + xG + PDO (6 signals) | Daily |
| 🏀 NBA | ESPN API (standings + shot stats) | Pythagorean + shot quality + close games (5 signals) | Daily |
| ⚾ MLB | MLB Official API + Baseball Savant | Pythagorean + xwOBA + xERA (5 signals) | Daily |
| 🏈 NFL | nflverse | Pythagorean + EPA | Coming soon |
Soccer data via API-Football (paid). All other data from free, publicly available sources.