Elote
The scikit-learn of rating algorithms: compare rating models behind one largely uniform Python interface, then keep the one that fits your data.
Use Elote to turn pairwise wins, losses, and draws into expected scores and rankings. Start with Elo, switch to Glicko, TrueSkill, Bradley-Terry, or another included model without rewriting the surrounding workflow, and evaluate the alternatives on the same match history.
pip install elote
Compare and rank in 60 seconds
The same matchups can drive different rating systems:
from elote import EloCompetitor, GlickoCompetitor, LambdaArena
winner_loser_pairs = [
("Ada", "Grace"),
("Grace", "Linus"),
("Ada", "Linus"),
("Grace", "Linus"),
]
for model in (EloCompetitor, GlickoCompetitor):
arena = LambdaArena(lambda winner, loser: True, base_competitor=model)
for winner, loser in winner_loser_pairs:
arena.matchup(winner, loser)
ranking = [row["competitor"] for row in arena.leaderboard()]
print(f"{model.__name__}: {' > '.join(ranking)}")
EloCompetitor: Ada > Grace > Linus
GlickoCompetitor: Ada > Grace > Linus
LambdaArena owns the population, creates competitors as identifiers appear,
records each bout, and returns the leaderboard best-first. Change
base_competitor to compare another model with the same application code.
Choose your task
| I want to... | Start with |
|---|---|
| Rate two competitors directly | Create two matching competitor objects; call expected_score(), then beat(), lost_to(), or tied(). See Getting started. |
| Manage a changing population | Use LambdaArena with your identifiers and results, then read leaderboard() and history. See Arenas. |
| Compare models on held-out data | Build a DataSplit, then use evaluate_competitor() or benchmark_competitors() and the plotting helpers. See elote/benchmark.py. |
| Save and resume ratings | Call export_state() or to_json() and store the result yourself; restore with from_state(), from_json(), or LambdaArena(initial_state=...). See Serialization. |
Install the dataset adapters when you want the Lichess chess or college-football loaders:
pip install "elote[datasets]"
Install the plotting helpers when you want the visualization functions:
pip install "elote[viz]"
SyntheticDataset and the core rating systems are included in the base installation.
Rating models
Every row below is exported from elote and supports the shared competitor
workflow. Constructor parameters and algorithm-specific state still differ.
| Model | Class | Model shape |
|---|---|---|
| Elo | EloCompetitor |
Incremental rating |
| Glicko-1 | GlickoCompetitor |
Incremental rating and rating deviation |
| Glicko-2 | Glicko2Competitor |
Incremental rating, deviation, and volatility |
| TrueSkill | TrueSkillCompetitor |
Bayesian mean and uncertainty |
| ECF | ECFCompetitor |
English Chess Federation rating |
| DWZ | DWZCompetitor |
German chess rating |
| Colley Matrix | ColleyMatrixCompetitor |
Global fit over the matchup graph |
| Massey | MasseyCompetitor |
Global least-squares fit using score margins |
| Keener | KeenerCompetitor |
Global eigenvector fit using scores |
| Pythagorean | PythagoreanCompetitor |
Points-based win expectation from points scored and allowed |
| Bradley-Terry | BradleyTerryCompetitor |
Global paired-comparison fit |
| Whole-History Rating | WholeHistoryRatingCompetitor |
Time-aware Bradley-Terry rating curve |
| Blended ensemble | BlendedCompetitor |
Composition of multiple competitor models |
The common surface covers expected scores, results, ratings, reset, configuration, and state serialization. It does not erase meaningful differences in parameters, uncertainty, rating scale, or whether a model updates incrementally or refits a connected population.
Evaluation tools
Elote keeps pre-result predictions in History objects so you can inspect
accuracy, precision, recall, F1, draw-aware metrics, confusion counts, calibration
data, optimized decision thresholds, and accuracy by prior bouts. Dataset helpers
train on one split and evaluate on another without updating ratings on the held-out
rows. Benchmark results retain the trained arena and history for further analysis.
The package also includes plotting helpers for rating-system comparisons, optimized accuracy, calibration, and accuracy by prior bouts.
To see how the rating models compare on the same split, run make compare-systems
(or scripts/rating_system_comparison.py
directly) for accuracy, Brier score, and log loss — see
docs/source/rating_systems/comparison_benchmark.rst
for methodology and measured results.
Library boundaries
Elote is an in-process Python library. It does not provide a CLI, hosted API, server, user interface, accounts, authentication, or a database. Your application supplies identifiers and results, decides how a model is selected, and stores exported dictionaries or JSON in the persistence system it owns.
Trust and project status
- Python 3.10 or later
- Typed-package marker (
py.typed) - MIT licensed
- Behavioral and known-value tests across the model catalog, plus tests for serialization, datasets, benchmarking, histories, plots, and the shared interface
- Published with an Alpha development classifier
See the full documentation and the
examples/ directory for more workflows.
Blog Posts
Here are some blog posts about Elote:
- Elote: A Python Package for Rating Systems - Introduction to the library
- Using Cursor for Library Maintenance - How Cursor helps maintain Elote
- Year's End: Looking Back at 2017 - Reflections including Elote development
References
- Glicko Rating System
- Glicko-2 Rating System
- Massey Ratings
- Elo, Arpad (1978). The Rating of Chessplayers, Past and Present. Arco. ISBN 0-668-04721-6.
- ECF Grading System
- Deutsche Wertungszahl
- TrueSkill: A Bayesian Skill Rating System
Contributing
Contributions are welcome. Read CONTRIBUTING.md and the Code of Conduct, then open an issue or pull request.
git clone https://github.com/wdm0006/elote.git
cd elote
make install-dev
make test # or: make test-cov
make lint # or: make lint-fix, make format
make docs # or: make build
Elote is available under the MIT License.
Metadata
Release files for elote 1.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| elote-1.5.1.tar.gz | 274.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| elote-1.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 425.4 kB
Release files / elote-1.5.1.tar.gz
| Download URL | elote-1.5.1.tar.gz |
|---|---|
| Size | 274.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
57fcf804ba309b7120ff86798d40f810f43aa02278a0c90fad7bef91f030faee
|
|
BLAKE2b-256 checksum How to use checksums |
b4e53650a4f128eb82cc4d3ef06b2e9bae597e598c09f9d94c4ccb77de687227
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / elote-1.5.1-py3-none-any.whl
| Download URL | elote-1.5.1-py3-none-any.whl |
|---|---|
| Size | 151.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ee225e218b4087c7e71c5fe0ed07e0eaca2bc9fdceb3a579123c0304774671dd
|
|
BLAKE2b-256 checksum How to use checksums |
7afc34480ba78804c250e58d858aea07b7aa0838dfc085a5e82734d182f4287c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency log