The method
One open ratings model for every league. Here is how it turns past scores into a probability, the settings it uses, and the things it cannot see.
Six steps from a final score to a published number
The same six steps run for every game in every league. Nothing else goes in.
- 1
Every team has a rating
Each team starts at 1500. After every game the winner takes rating points from the loser. Beating a strong team, or winning by a lot, moves more points than edging a weak one.
- 2
Home teams get a head start
The home team is treated as a little stronger than its rating. How much depends on the league, and nothing is added at a neutral site.
- 3
Tired teams get a small penalty
A team on short rest against a rested one gives up a few rating points for that game. Baseball is left out, because teams play almost every day.
- 4
A new season pulls everyone toward average
Rosters change over the summer, so each rating moves part of the way back to 1500 before a new season starts.
- 5
The rating gap becomes a probability
A 100-point advantage is about a 64% chance to win. 200 points is about 76%. Two equal teams are 50/50.
- 6
The number is published before the game
Up to 48 hours before the start, once both teams have finished their previous game, the probability is stored with a time stamp. It is never edited afterward.
The settings in force
Four numbers per league. They were chosen by trying a fixed list of values and keeping the ones with the lowest log loss on past seasons, then checked on a season that was kept aside. A coin flip scores 0.6931, so lower than that is better than guessing.
| League | K (speed) | Home edge | Season reset | Short rest | Tuned on | Held-out season |
|---|---|---|---|---|---|---|
| NFL | 36 | 40 pts (55.7%) | 40% | 0 pts | 2022, 2023, 2024 log loss 0.6327 on 852 games | 2025 log loss 0.6351 on 284 games |
| NBA | 18 | 40 pts (55.7%) | 50% | 70 pts | 2022–23, 2023–24, 2024–25 log loss 0.6203 on 3,960 games | 2025–26 log loss 0.6009 on 1,322 games |
| MLB | 4 | 20 pts (52.9%) | 40% | not used | 2022, 2023, 2024 log loss 0.6786 on 7,413 games | 2025 log loss 0.6788 on 2,477 games |
| NHL | 8 | 20 pts (52.9%) | 20% | 60 pts | 2022–23, 2023–24, 2024–25 log loss 0.6617 on 4,198 games | 2025–26 log loss 0.6892 on 1,394 games |
Home edge and short rest are in rating points; the percentage is what the home edge alone gives two equal teams. “Season reset” is the share of each team’s distance from 1500 that is removed before a new season. Settings last tuned September 30, 2026 (the values shipped with EdgeBoard). The site owner can change them, and the published ledger stores the settings used for every row.
The math, for the curious
Five lines. The same five lines are written in JavaScript, which your browser runs, and in PHP, which the publishing job runs. A test requires both to agree on every stored game.
- Win probability
p(home) = 1 / (1 + 10^(−d / 400))whered = home rating − away rating + home edge + rest adjustment- After the game
change = K × margin multiplier × (result − p), added to the home team and taken from the away team. Result is 1 for a home win, 0 for a loss, 0.5 for a tie.- Margin multiplier
log2(1 + margin / scale) × 2.2 / (2.2 + 0.001 × winner’s advantage). Scale is a typical winning margin: 7 points in the NFL, 10 in the NBA, 3 runs in MLB, 2 goals in the NHL. The second part stops favorites gaining too much for big wins.- New season
rating = 1500 + (rating − 1500) × (1 − season reset)- Short rest
- NFL: 4 or fewer full days off. NBA and NHL: played the day before. The penalty applies only when one team is on short rest and the other is not. Not used for MLB.
How a prediction gets on the record
The published record is only worth something if nobody can tidy it up afterward. These are the rules the software follows.
When
A prediction is stored when the game is within 48 hours, has an announced start time and has not started.
Which rating
Only once both teams have finished their previous game, so the rating used is the one the game is played at.
Insert only
One row per game. No part of the software edits or deletes a published row.
Fingerprint
Each row is hashed with SHA-256 together with the fingerprint of the row before it. Change one row and every later fingerprint stops matching.
Decided or void
A prediction is decided when its game is final within 36 hours of the start it was published for. A game called off or moved further than that makes the row void: it stays visible and is never counted right or wrong.
Enough history first
Nothing is published for a league with fewer than 250 finished games stored. Ratings built on a handful of games stay off the record.

What the model does not know
A floodlight shows you the field, not the dressing room. The model sees scores, venue and rest. That is all.
Injuries and trades
A star who is out tonight, or a deadline trade yesterday, changes nothing in the model until the scores start to reflect it.
Who is starting
Starting pitchers and goalies matter a great deal in a single game. The model rates the team, not tonight’s lineup.
Weather and travel
Wind, cold, altitude and a cross-country flight are all invisible to it. Only a short turnaround between games is counted.
A team that changed over the summer
Early in a season the ratings lean on last year. A rebuilt roster takes a few weeks of results to show up.
Luck
A 70% chance still loses 3 times in 10. One result says almost nothing. The record over many games is the honest test.
Where the games come from
Schedules and final scores come from the leagues’ public feeds. Regular season and playoff games count. Preseason and all-star games do not. This site refreshes every hour.
- NFLESPN scoreboard API, with the ESPN CDN scoreboard as the fallback
- NBAESPN scoreboard API, with the ESPN CDN scoreboard as the fallback
- MLBMLB Stats API (statsapi.mlb.com), with ESPN’s scoreboard as the fallback
- NHLNHL API (api-web.nhle.com), with ESPN’s scoreboard as the fallback
See it on tonight’s games.
Every number on the board comes from the method on this page.