Elote 🏆
Elote is a powerful Python library for implementing and comparing rating systems. Whether you're ranking chess players, sports teams, or prioritizing features in your product backlog, Elote provides a simple, elegant API for all your competitive ranking needs.
Table of Contents
- Overview
- Features
- Installation
- Quick Start
- Usage Examples
- Development
- Contributing
- Blog Posts
- References
Overview
Rating systems allow you to rank competitors based on their performance in head-to-head matchups. The most famous example is the Elo rating system used in chess, but these systems have applications far beyond sports:
- Ranking products based on A/B comparisons
- Prioritizing features through pairwise voting
- Creating recommendation systems
- Matchmaking in games and competitions
- Collaborative filtering and ranking
Elote makes implementing these systems simple and intuitive, with a clean API that handles all the mathematical complexity for you.
Features
Currently implemented rating systems:
- Elo - The classic chess rating system
- Glicko-1 - An improvement on Elo that accounts for rating reliability
- Glicko-2 - A further improvement on Glicko that adds volatility tracking
- TrueSkill - Microsoft's Bayesian skill rating system for multiplayer games
- ECF - The English Chess Federation rating system
- DWZ - The Deutsche Wertungszahl (German evaluation number) system
- Colley Matrix - A least-squares method that ranks competitors by solving a linear system
- Bradley-Terry - A maximum-likelihood paired-comparison model on an Elo-compatible scale
You can also combine several systems into a single Ensemble (blended) competitor.
Installation
For Users
# Basic installation (core rating systems)
pip install elote
# With optional dataset support
pip install "elote[datasets]"
Optional Dependencies
Elote has optional dependencies for specific datasets:
-
Chess Dataset: Requires
python-chessandpyzstdpip install python-chess pyzstd
-
College Football Dataset: Requires
sportsdataversepip install "sportsdataverse[all]"
-
All Datasets: Install all optional dependencies
pip install "elote[datasets]"
For Developers
We use a modern Python packaging approach with pyproject.toml. Most things you need are in the Makefile:
# Using Make (recommended)
make install-dev
# Or using pip
pip install -e ".[dev]"
# Or using uv
uv pip install -e ".[dev]"
Requirements
- Python 3.10 or higher
Quick Start
from elote import EloCompetitor
# Create two competitors with different initial ratings
player1 = EloCompetitor(initial_rating=1500)
player2 = EloCompetitor(initial_rating=1600)
# Get win probability
print(f"Player 2 win probability: {player2.expected_score(player1):.2%}")
# Record a match result
player1.beat(player2) # Player 1 won!
# Ratings are automatically updated
print(f"Player 1 new rating: {player1.rating}")
print(f"Player 2 new rating: {player2.rating}")
Check Available Features
from elote import list_available_datasets, list_missing_datasets
# See which datasets are available
print("Available datasets:", list_available_datasets())
# See which datasets require additional dependencies
missing = list_missing_datasets()
for dataset in missing:
print(f"Missing: {dataset['name']}")
print(f"Install with: {dataset['error']}")
Usage Examples
Elote is built around two main concepts: Competitors and Arenas.
Competitors
Competitors represent the entities you're rating. Here's how to use them:
from elote import EloCompetitor
good = EloCompetitor(initial_rating=400)
better = EloCompetitor(initial_rating=500)
# Check win probabilities
print(f"Probability of better beating good: {better.expected_score(good):.2%}")
print(f"Probability of good beating better: {good.expected_score(better):.2%}")
Output:
Probability of better beating good: 64.01%
Probability of good beating better: 35.99%
If a match occurs, updating ratings is simple:
# If good wins (an upset!)
good.beat(better)
# OR
better.lost_to(good)
# Check updated probabilities
print(f"Probability of better beating good: {better.expected_score(good):.2%}")
print(f"Probability of good beating better: {good.expected_score(better):.2%}")
Output:
Probability of better beating good: 61.25%
Probability of good beating better: 38.75%
Arenas
Arenas handle large numbers of matchups automatically. The LambdaArena takes a comparison function and manages all competitors for you:
from elote import LambdaArena
import json
import random
# Define a comparison function (returns True if a beats b)
def comparison(a, b):
return a > b
# Generate 1000 random matchups between numbers 1-10
matchups = [(random.randint(1, 10), random.randint(1, 10)) for _ in range(1000)]
# Create arena and run tournament
arena = LambdaArena(comparison)
arena.tournament(matchups)
# Display final rankings
print("Arena results:")
print(json.dumps(arena.leaderboard(), indent=4))
This example effectively implements a sorting algorithm using a rating system - not efficient, but demonstrates how Elote works with any comparable objects!
Development
The project includes a Makefile that simplifies common development tasks:
# Run tests
make test
# Run tests with coverage
make test-cov
# Lint code
make lint
# Auto-fix linting issues
make lint-fix
# Format code
make format
# Build package
make build
# Build documentation
make docs
Contributing
Contributions are welcome! If you'd like to help improve Elote:
- Check the issues for open tasks
- Fork the repository
- Create a feature branch
- Add your changes
- Submit a pull request
For major changes, please open an issue first to discuss what you'd like to change.
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
Metadata
Release files for elote 1.3.0
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.3.0.tar.gz | 168.1 kB | Details |
Release files / elote-1.3.0.tar.gz
| Download URL | elote-1.3.0.tar.gz |
|---|---|
| Size | 168.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9ed30fccd5470fa4015a2a06ff7054a7722be2c0b0873c565a1ed633f13e896b
|
|
BLAKE2b-256 checksum How to use checksums |
65dcfe4fd35556ca4e652486144eedcf4cd3deeefb306c75676215a58cbb928e
|
| 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 Aug 22, 2026.
Transparency log