Skip to main content

Elote 🏆

PyPI version Python Versions License: MIT

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

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-chess and pyzstd

    pip install python-chess pyzstd
    
  • College Football Dataset: Requires sportsdataverse

    pip 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:

  1. Check the issues for open tasks
  2. Fork the repository
  3. Create a feature branch
  4. Add your changes
  5. 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:

References

  1. Glicko Rating System
  2. Glicko-2 Rating System
  3. Massey Ratings
  4. Elo, Arpad (1978). The Rating of Chessplayers, Past and Present. Arco. ISBN 0-668-04721-6.
  5. ECF Grading System
  6. Deutsche Wertungszahl
  7. TrueSkill: A Bayesian Skill Rating System

Metadata

Release files for elote 1.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for elote 1.3.1
File Size Uploaded
elote-1.3.1.tar.gz 171.3 kB Details

Release files / elote-1.3.1.tar.gz

Download URL elote-1.3.1.tar.gz
Size 171.3 kB
Tags Source
SHA-256 checksum
How to use checksums
98d6016e580e60f16f01413c69482ca118a1362bdf5b7da48352611c4c366d2f
BLAKE2b-256 checksum
How to use checksums
f2dd66df0b4242fcb7ba1fc555c3e1767c8d8525b7515f869921e32a8fc4f7a7
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

Release history Release notifications | RSS feed

1.5.1

2 release files

1.5.0

2 release files

1.3.2

1 release file

This release

1.3.1 This release

1 release file

1.3.0

1 release file

1.2.1

1 release file

1.2.0

1 release file

1.1.0

1 release file

1.0.0

1 release file

0.1.0

2 release files

0.0.5

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page