An open ranking engine your state association can adopt.
open-bethel computes strength ratings, strength of schedule, and per-game contributions for sports teams from a list of head-to-head results. The math is published and peer-reviewed. The implementation is short enough to read in an afternoon. The license is MIT.
What it produces
- Strength ratings
- Each team gets a single number reflecting how strong its results show it to be, accounting for opponent quality. Derived by maximum likelihood under the Bradley-Terry model with a Bayesian prior so low-data and disconnected graphs stay well-behaved.
- Classical RPI
- The traditional 25/50/25 blend of win percentage, opponents' win percentage, and opponents' opponents' win percentage. Reported alongside the strength rating for direct comparison with established formulas.
- Per-game contributions
- For any team, a leave-one-out decomposition of which games raised the rating and which lowered it, sorted by impact. Lets a coach, AD, or journalist answer which win mattered most? with arithmetic, not narrative.
- Pairwise diagnostics
- For any two teams, the level of indirection between them in the head-to-head graph. Surfaces when a comparison is well-grounded versus when it relies on long inferential chains — a transparency the formula owes to the people it ranks.
Who it's for
State athletic associations, conferences, and tournament directors who want a defensible, reproducible seeding mechanism instead of a proprietary number nobody can audit. Statisticians, athletic directors, coaches, and reporters who need to show their work. Anyone who has to explain a ranking to the people it affects.
Why it exists
Ranking decisions decide who makes the playoffs, who earns a seed, and who is left out. Those decisions deserve to be reproducible by the parties affected. Many of the systems state associations now defer to are proprietary: the formula is not published, the inputs are not released in full, and even administrators applying the numbers cannot always show their work.
open-bethel is the alternative: specified in the open, implemented in the open, free for anyone to run.
The method
The core method is the iterative Bradley-Terry-Ford strength rating with a Bayesian prior, derived in An Optimal Value for the Bradley-Terry Model for Estimating Strength-of-Schedule (Roy Bethel, MITRE Corporation, 2005). The test suite reproduces the paper's Table 2 — converged strengths for all 31 NFL teams after the 1999 regular season — to four decimal places given the same 248-game schedule, so the implementation is verifiable against a published ground truth, not just self-consistent.
The algorithm is dependency-free Python — standard library only. The full essay walking through the math, the failure modes, and the parameter decisions lives in docs/bethel-essence.md.
Examples
Two end-to-end runs. The first reproduces the published reference; the second is a current high-school season.
1999 NFL regular season
Bethel's 2005 paper publishes converged Bradley-Terry-Ford strengths for all 31 NFL teams after the 1999 regular season (Table 2). Running open-bethel on the same 248-game schedule recovers his table to four decimals — every team, every position. The test suite asserts this on every commit.
| Rank | Team | W-L | Strength | Bethel '05 | RPI |
|---|---|---|---|---|---|
| 1 | Indianapolis | 13-3 | 6.9927 | 6.9927 | .594 |
| 2 | Jacksonville | 14-2 | 5.0117 | 5.0117 | .553 |
| 3 | Buffalo | 11-5 | 3.8538 | 3.8538 | .581 |
| 4 | Tennessee | 13-3 | 3.7348 | 3.7348 | .557 |
| 5 | Miami | 9-7 | 2.5624 | 2.5624 | .557 |
| 6 | Tampa Bay | 11-5 | 2.2356 | 2.2356 | .535 |
| 7 | NY Jets | 8-8 | 2.1129 | 2.1129 | .552 |
| 8 | St. Louis | 13-3 | 2.0762 | 2.0762 | .519 |
| ⋮ | 23 teams omitted; full results in tests/test_bethel_nfl_1999.py | ||||
| 29 | San Francisco | 4-12 | 0.1591 | 0.1591 | .415 |
| 30 | New Orleans | 3-13 | 0.1062 | 0.1062 | .399 |
| 31 | Cleveland | 2-14 | 0.0830 | 0.0830 | .410 |
FHSAA Class 2A Region 1 District 3 — baseball, 2026
The five schools in northeast Florida's Class 2A District 3: Bishop Snyder, Bolles, Episcopal, Providence, and Trinity Christian. The run uses the full Florida high-school baseball graph for the 2026 season — 7,085 games across 951 teams — so strength-of-schedule chains extend through every opponent and every opponent's opponents statewide. The table below shows the five district members; the rightmost column is each team's rank against all 951 Florida programs.
| Rank | Team | W-L | Strength | RPI | State rk |
|---|---|---|---|---|---|
| 1 | Trinity Christian | 20-7 | 18.8315 | .659 | 19 |
| 2 | Bishop Snyder | 19-6 | 14.2762 | .621 | 30 |
| 3 | Bolles | 18-7 | 9.7697 | .611 | 54 |
| 4 | Episcopal | 17-10 | 5.0386 | .567 | 107 |
| 5 | Providence | 13-12 | 4.9520 | .578 | 113 |
prior_games=1); converged in 588 iterations. The district order tracks what happened on the field: Trinity Christian beat Bishop Snyder 11-10 in the district final on 2026-04-17, and the two are the closest pair in the table. See the essay for why a small Bayesian prior matters when graphs include thinly-connected teams.Use
Install:
pip install open-bethel
Library:
from open_bethel import bethel_strengths, classical_rpi, load_games
teams, games = load_games("games.csv")
strengths, iters, converged = bethel_strengths(teams, games)
Or from the command line:
open-bethel-rank games.csv team-a team-b
open-bethel-validate games.csv 2026-04-01
open-bethel-diagnose games.csv
The CSV expects one row per game with columns date, home_team, away_team, home_score, away_score. Team identifiers are free-form. Tied games are dropped — the model is undefined for ties.
Adopt
open-bethel is MIT licensed and dependency-free. There is nothing to license, nothing to procure, no per-school fee. A state association, conference, or tournament director can run it on its own infrastructure with no commercial relationship and no recurring cost. Source, issues, and discussion live at github.com/Londonberry/open-bethel.