Competitors API Reference

This page provides detailed API documentation for all competitor classes in Elote.

Base Competitor

class elote.competitors.base.BaseCompetitor(**kwargs: Any)[source]

Bases: ABC

Base abstract class for all rating system competitors.

This class defines the interface that all rating system implementations must follow. Each competitor represents an entity with a rating that can be compared against other competitors of the same type.

All rating system implementations should inherit from this class and implement the abstract methods. This ensures a consistent API across all rating systems.

Class Attributes:
_minimum_rating (float): The minimum allowed rating value. Default: 100.

This prevents ratings from becoming negative or unreasonably low.

Initialize base competitor state.

abstractmethod __init__(**kwargs: Any) None[source]

Initialize base competitor state.

abstractmethod beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

This method updates the ratings of both this competitor and the opponent based on the match outcome where this competitor won.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two non-negative, finite scores in

caller order – (self_score, competitor_score). Rating systems that model margin of victory (such as MasseyCompetitor) consume it; the rest validate and ignore it. When omitted, every system falls back to its documented unit-score behaviour.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If scores is malformed, negative, non-finite, or does not describe

a win for this competitor.

configure(**kwargs: Any) None[source]

Configure instance-level parameters for this competitor.

This method allows setting instance-level parameters that affect only this competitor.

Args:

**kwargs: Keyword arguments for instance-level parameters.

Raises:

InvalidParameterException: If any parameter is invalid.

classmethod configure_class(**kwargs: Any) None[source]

Configure class-level parameters for this rating system.

This method allows setting class-level parameters that affect all instances of this rating system.

Args:

**kwargs: Keyword arguments for class-level parameters.

Raises:

InvalidParameterException: If any parameter is invalid.

abstractmethod expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score (probability of winning) against another competitor.

Args:

competitor (BaseCompetitor): The opponent competitor to compare against.

Returns:

float: The probability of winning (between 0 and 1).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

This method exports the competitor’s state in a standardized format that can be used to recreate the competitor with the same state. The format includes: - type: The class name of the competitor - version: The version of the serialization format - created_at: The timestamp when the state was exported - id: A unique identifier for this state export - parameters: The parameters used to initialize the competitor - state: The current state variables of the competitor

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_json(json_str: str) T[source]

Create a new competitor from a JSON string.

Args:

json_str (str): A JSON string representing a competitor’s state.

Returns:

BaseCompetitor: A new competitor with the state from the JSON string.

Raises:

InvalidStateException: If the JSON string is invalid or incompatible. InvalidParameterException: If any parameter in the state is invalid.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a state dictionary.

Args:

state: A dictionary containing the state of a competitor, including its type and parameters.

Returns:

A new competitor of the same type as the exported one.

Raises:

InvalidStateException: If the state format is invalid or missing required fields.

classmethod get_competitor_class(class_name: str) Type[BaseCompetitor][source]

Get a competitor class by name.

Args:

class_name (str): The name of the competitor class.

Returns:

Type[BaseCompetitor]: The competitor class.

Raises:

InvalidParameterException: If the class name is not registered.

import_state(state: Dict[str, Any]) None[source]

Import the competitor’s state from a dictionary.

This method updates the competitor’s state based on the provided dictionary, including parameters and current state variables.

Args:

state (dict): A dictionary containing the state of a competitor.

Raises:

InvalidStateException: If the state dictionary is invalid or incompatible. InvalidParameterException: If any parameter in the state is invalid.

classmethod list_competitor_types() List[str][source]

List all registered competitor types.

Returns:

List[str]: A list of registered competitor type names.

lost_to(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has lost to the given competitor.

This is a convenience method that calls beat() on the winning competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that won. scores (sequence of float, optional): The two scores in caller order –

(self_score, competitor_score). They are reversed before being handed to the winner’s beat(), so the caller never reorders them.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If scores is malformed, negative, non-finite, or does not describe

a loss for this competitor.

abstract property rating: float

Get the current rating value of this competitor.

Returns:

float: The current rating value.

abstractmethod reset() None[source]

Reset the competitor’s state to its initial configuration.

This method should revert any changes made through updates (beat, lost_to, tied) and re-import the initial parameters and state. Note: Actual implementation might be needed depending on how initial state is stored.

abstractmethod tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

This method updates the ratings of both this competitor and the opponent based on a drawn match outcome.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order –

(self_score, competitor_score). They must be equal, since the result is declared a draw.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If scores is malformed, negative, non-finite, or is not a draw.

to_json() str[source]

Convert this competitor’s state to a JSON string.

Returns:

str: A JSON string representing this competitor’s state.

verify_competitor_types(competitor: BaseCompetitor) None[source]

Verify that the competitor types match.

Args:

competitor (BaseCompetitor): The competitor to verify.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

exception elote.competitors.base.InvalidParameterException[source]

Bases: Exception

Exception raised when an invalid parameter is provided.

This exception is raised when a parameter value is outside the acceptable range or of an incorrect type for a particular rating system.

exception elote.competitors.base.InvalidRatingValueException[source]

Bases: Exception

Exception raised when an invalid rating value is provided.

This exception is raised when a rating value is outside the acceptable range for a particular rating system.

exception elote.competitors.base.InvalidStateException[source]

Bases: Exception

Exception raised when an invalid state is provided for deserialization.

This exception is raised when a state dictionary is missing required fields or contains invalid values.

exception elote.competitors.base.MissMatchedCompetitorTypesException[source]

Bases: Exception

Exception raised when attempting to compare or update competitors of different types.

This exception is raised when operations are attempted between competitors that use different rating systems, which would lead to invalid results.

elote.competitors.base.validate_scores(scores: Sequence[float] | None, outcome: float) Tuple[float, float] | None[source]

Validate an optional score payload against the outcome it is supposed to describe.

The score payload is always the two competitors’ scores in caller order: for a.beat(b, scores=(x, y)) x is a’s score and y is b’s. The same ordering holds for lost_to, tied and elote.LambdaArena.matchup(), so a caller never has to reorder a score pair to match the method it is calling.

Args:

scores (sequence of float, optional): The two scores in caller order, or None. outcome (float): The declared result from the first score’s perspective –

1.0 (first competitor won), 0.0 (first competitor lost) or 0.5 (draw).

Returns:

tuple of float, or None: The validated scores as floats, or None when no score payload was supplied.

Raises:
ValueError: If the payload is malformed, contains a negative or non-finite value, or

disagrees with the declared outcome.

Elo Competitor

class elote.competitors.elo.EloCompetitor(initial_rating: float = 400, k_factor: float | None = None)[source]

Bases: BaseCompetitor

Elo rating system competitor.

The Elo rating system is a method for calculating the relative skill levels of players in zero-sum games such as chess. It is named after its creator Arpad Elo, a Hungarian-American physics professor and chess master.

In the Elo system, each player’s rating changes based on the outcome of games and the rating of their opponents. The difference in ratings between two players determines the expected outcome of a match, and the actual outcome is used to update the ratings.

Class Attributes:

_base_rating (float): Base rating divisor used in the transformed rating calculation. Default: 400. _k_factor (float): Factor that determines how much ratings change after each match. Default: 32.

Initialize an Elo competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 400. k_factor (float, optional): The K-factor to use for this competitor. If None,

the class K-factor will be used. Default: None.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating. InvalidParameterException: If the k_factor is negative.

__init__(initial_rating: float = 400, k_factor: float | None = None)[source]

Initialize an Elo competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 400. k_factor (float, optional): The K-factor to use for this competitor. If None,

the class K-factor will be used. Default: None.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating. InvalidParameterException: If the k_factor is negative.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

This method updates the ratings of both this competitor and the opponent based on the match outcome where this competitor won.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score against another competitor.

Args:

competitor (BaseCompetitor): The competitor to compare against.

Returns:

float: The expected score (probability of winning).

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

EloCompetitor: A new competitor with the same state as the exported one.

Raises:

InvalidParameterException: If any parameter in the state is invalid.

property rating: float

Get the current rating of this competitor.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

This method resets the competitor’s rating to the initial rating.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

This method updates the ratings of both this competitor and the opponent based on a drawn match outcome.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

property transformed_rating: float

Get the transformed rating for this competitor.

Returns:

float: The transformed rating.

Glicko Competitor

class elote.competitors.glicko.GlickoCompetitor(initial_rating: float = 1500, initial_rd: float = 350, initial_time: datetime | None = None)[source]

Bases: BaseCompetitor

Glicko rating system competitor.

The Glicko rating system is an improvement on the Elo rating system that takes into account the reliability of a rating. It was developed by Mark Glickman as an improvement to the Elo system.

In addition to a rating, each competitor has a rating deviation (RD) that measures the reliability of the rating. A higher RD indicates a less reliable rating.

Class Attributes:
_c (float): Rating volatility constant that determines how quickly the RD increases over time.

Default: 34.6, which is calibrated so that it takes about 100 rating periods for a player’s RD to grow from 50 to 350 (maximum uncertainty).

_q (float): Scaling factor used in the rating calculation. Default: 0.0057565. _rating_period_days (float): Number of days that constitute one rating period.

Default: 1.0 (one day per rating period).

Initialize a Glicko competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 1500. initial_rd (float, optional): The initial rating deviation of this competitor. Default: 350. initial_time (datetime, optional): The initial timestamp for this competitor. When omitted the

competitor has no recorded activity and adopts the time of its first match, so a stream of historical results can be replayed through it.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating. InvalidParameterException: If the initial RD is not positive.

__init__(initial_rating: float = 1500, initial_rd: float = 350, initial_time: datetime | None = None)[source]

Initialize a Glicko competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 1500. initial_rd (float, optional): The initial rating deviation of this competitor. Default: 350. initial_time (datetime, optional): The initial timestamp for this competitor. When omitted the

competitor has no recorded activity and adopts the time of its first match, so a stream of historical results can be replayed through it.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating. InvalidParameterException: If the initial RD is not positive.

beat(competitor: GlickoCompetitor, match_time: datetime | None = None, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

This method updates the ratings of both this competitor and the opponent based on the match outcome where this competitor won.

Args:

competitor (GlickoCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

match_time (datetime, optional): The time when the match occurred. Default: current time.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score (probability of winning) against another competitor.

Args:

competitor (BaseCompetitor): The opponent competitor to compare against.

Returns:

float: The probability of winning (between 0 and 1).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

GlickoCompetitor: A new competitor with the same state as the exported one.

Raises:

InvalidParameterException: If any parameter in the state is invalid.

property rating: float

Get the current rating of this competitor.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

This method resets the competitor’s rating and RD to their initial values.

tied(competitor: GlickoCompetitor, match_time: datetime | None = None, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

This method updates the ratings of both this competitor and the opponent based on a drawn match outcome.

Args:

competitor (GlickoCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

match_time (datetime, optional): The time when the match occurred. Default: current time.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

property tranformed_rd: float

Get the transformed rating deviation of this competitor.

The transformed RD is used in the rating calculation and is capped at 350.

Returns:

float: The transformed rating deviation.

update_competitor_rating(competitor: GlickoCompetitor, s: float) Tuple[float, float][source]

Update the rating and RD of this competitor based on a match result.

Args:

competitor (GlickoCompetitor): The opponent competitor. s (float): The score of this competitor (1 for win, 0.5 for draw, 0 for loss).

Returns:

tuple: A tuple containing the new rating and RD.

update_rd_for_inactivity(current_time: datetime | None = None) None[source]

Update the rating deviation based on time elapsed since last activity.

This implements Glickman’s formula for increasing uncertainty in ratings over time when a player is inactive. The RD increase is controlled by the _c parameter and the number of rating periods that have passed.

Args:
current_time (datetime, optional): The current time to calculate inactivity against.

If None, uses the current system time.

Glicko-2 Competitor

class elote.competitors.glicko2.Glicko2Competitor(initial_rating: float = 1500, initial_rd: float = 350, initial_volatility: float | None = None, initial_time: datetime | None = None)[source]

Bases: BaseCompetitor

Glicko-2 rating system competitor.

The Glicko-2 rating system is an improvement on the original Glicko system, developed by Mark Glickman. It introduces a volatility parameter that measures the degree of expected fluctuation in a player’s rating.

In Glicko-2, ratings are internally represented in a different scale than displayed to users. The internal scale uses a mean of 0 and a standard deviation of 1, while the displayed scale uses a mean of 1500 and a standard deviation of 173.7.

Class Attributes:
_tau (float): System constant that constrains the volatility over time. Default: 0.5.

Smaller values (e.g., 0.3 to 0.2) make volatility change more slowly. Larger values (e.g., 0.6 to 1.0) allow volatility to change more quickly.

_epsilon (float): Convergence tolerance for the volatility iteration. Default: 0.000001. _default_volatility (float): Default volatility for new competitors. Default: 0.06. _scale_factor (float): Scale factor for converting between Glicko-2 and original scales. Default: 173.7178. _rating_period_days (float): Number of days that constitute one rating period. Default: 1.0.

Initialize a Glicko-2 competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 1500. initial_rd (float, optional): The initial rating deviation of this competitor. Default: 350. initial_volatility (float, optional): The initial volatility of this competitor. Default: _default_volatility. initial_time (datetime, optional): The initial timestamp for this competitor. When omitted the

competitor has no recorded activity and adopts the time of its first match, so a stream of historical results can be replayed through it.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating. InvalidParameterException: If the initial RD is not positive or if the initial volatility is not positive.

__init__(initial_rating: float = 1500, initial_rd: float = 350, initial_volatility: float | None = None, initial_time: datetime | None = None)[source]

Initialize a Glicko-2 competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 1500. initial_rd (float, optional): The initial rating deviation of this competitor. Default: 350. initial_volatility (float, optional): The initial volatility of this competitor. Default: _default_volatility. initial_time (datetime, optional): The initial timestamp for this competitor. When omitted the

competitor has no recorded activity and adopts the time of its first match, so a stream of historical results can be replayed through it.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating. InvalidParameterException: If the initial RD is not positive or if the initial volatility is not positive.

beat(competitor: BaseCompetitor, match_time: datetime | None = None, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

This method records the match result for later processing during the rating period update. The actual rating update happens when update_ratings() is called.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

match_time (datetime, optional): The time when the match occurred. Default: current time.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. InvalidParameterException: If the match time is before either competitor’s last activity.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score (probability of winning) against another competitor.

Args:

competitor (BaseCompetitor): The opponent competitor to compare against.

Returns:

float: The probability of winning (between 0 and 1).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

Glicko2Competitor: A new competitor with the same state as the exported one.

Raises:

InvalidParameterException: If any parameter in the state is invalid.

property rating: float

Get the current rating of this competitor.

Returns:

float: The current rating.

property rd: float

Get the current rating deviation of this competitor.

Returns:

float: The current rating deviation.

reset() None[source]

Reset this competitor to its initial state.

This method resets the competitor’s rating, RD, and volatility to their initial values.

tied(competitor: BaseCompetitor, match_time: datetime | None = None, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

This method records the match result for later processing during the rating period update. The actual rating update happens when update_ratings() is called.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

match_time (datetime, optional): The time when the match occurred. Default: current time.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. InvalidParameterException: If the match time is before either competitor’s last activity.

update_ratings() None[source]

Update ratings based on recorded match results.

This method implements the Glicko-2 rating system update algorithm. It processes all recorded match results and updates the rating, RD, and volatility. If no matches were played, it updates the RD based on inactivity. After updating, the match results are cleared.

update_rd_for_inactivity(current_time: datetime | None = None) None[source]

Update the rating deviation based on time elapsed since last activity.

This implements Glickman’s formula for increasing uncertainty in ratings over time when a player is inactive. In Glicko-2, the phi (internal RD) increases based on the current volatility (sigma) parameter and the number of rating periods that have passed.

The last-activity timestamp is advanced to current_time so that the inflation is applied exactly once per elapsed period: calling this method repeatedly with the same timestamp is a no-op after the first call.

Args:
current_time (datetime, optional): The current time to calculate inactivity against.

If None, uses the current system time.

property volatility: float

Get the current volatility of this competitor.

Returns:

float: The current volatility.

TrueSkill Competitor

class elote.competitors.trueskill.TrueSkillCompetitor(initial_mu: float = None, initial_sigma: float = None)[source]

Bases: BaseCompetitor

TrueSkill rating system competitor.

TrueSkill is a Bayesian skill rating system developed by Microsoft Research. It generalizes the Elo and Glicko rating systems to handle team-based games and multiplayer scenarios. TrueSkill models each player’s skill as a Gaussian distribution with a mean (mu) and standard deviation (sigma).

The mean represents the player’s estimated skill, while the standard deviation represents the system’s uncertainty about that estimate. As more games are played, the uncertainty typically decreases.

Class Attributes:
_beta (float): The skill factor that controls how much the game outcome depends

on skill vs. chance. Default: 4.166.

_tau (float): The additive dynamics factor that increases uncertainty over time.

Default: 0.083.

_draw_probability (float): The probability of a draw. Default: 0.10 (10%). _default_mu (float): The default mean skill value for new players. Default: 25.0. _default_sigma (float): The default standard deviation for new players. Default: 8.333.

Initialize a TrueSkill competitor.

Args:

initial_mu (float, optional): The initial mean skill value. Default: _default_mu. initial_sigma (float, optional): The initial standard deviation. Default: _default_sigma.

Raises:

InvalidParameterException: If the initial sigma is not positive.

__init__(initial_mu: float = None, initial_sigma: float = None)[source]

Initialize a TrueSkill competitor.

Args:

initial_mu (float, optional): The initial mean skill value. Default: _default_mu. initial_sigma (float, optional): The initial standard deviation. Default: _default_sigma.

Raises:

InvalidParameterException: If the initial sigma is not positive.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

classmethod create_team(players: List[TrueSkillCompetitor]) Tuple[float, float][source]

Create a virtual team competitor from a list of players.

This method combines the skills of multiple players into a single team skill. The team’s mu is the sum of the players’ mus, and the team’s sigma is the square root of the sum of the players’ sigma squared.

Args:

players (List[TrueSkillCompetitor]): The list of players in the team.

Returns:

Tuple[float, float]: The team’s mu and sigma.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score (probability of winning) against another competitor.

Args:

competitor (BaseCompetitor): The opponent competitor to compare against.

Returns:

float: The probability of winning (between 0 and 1).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

TrueSkillCompetitor: A new competitor with the same state as the exported one.

Raises:

InvalidParameterException: If any parameter in the state is invalid.

classmethod match_quality(player1: TrueSkillCompetitor, player2: TrueSkillCompetitor) float[source]

Calculate the match quality between two players.

Match quality is a value between 0 and 1 that represents how evenly matched two players are. A value of 1 indicates a perfectly even match, while a value of 0 indicates a completely one-sided match.

Args:

player1 (TrueSkillCompetitor): The first player. player2 (TrueSkillCompetitor): The second player.

Returns:

float: The match quality (between 0 and 1).

property mu: float

Get the current mean skill value of this competitor.

Returns:

float: The current mean skill value.

property rating: float

Get the current conservative rating of this competitor.

TrueSkill uses a conservative rating estimate (mu - 3*sigma) to ensure that a player’s displayed rating has a 99% chance of being below their actual skill level. This encourages players to keep playing to reduce uncertainty and increase their displayed rating.

Returns:

float: The current conservative rating.

reset() None[source]

Reset this competitor to its initial state.

This method resets the competitor’s mu and sigma to their initial values.

property sigma: float

Get the current standard deviation of this competitor.

Returns:

float: The current standard deviation.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

classmethod update_team(team_players: List[TrueSkillCompetitor], team_mu_diff: float, team_sigma_squared: float, v: float, result_func: callable) None[source]

Update the ratings of players in a team.

Args:

team_players (List[TrueSkillCompetitor]): The list of players in the team. team_mu_diff (float): The difference in team mu. team_sigma_squared (float): The team’s sigma squared. v (float): The skill variance factor. result_func (callable): The function to calculate the performance update.

DWZ Competitor

class elote.competitors.dwz.DWZCompetitor(initial_rating: float = 400)[source]

Bases: BaseCompetitor

Deutsche Wertungszahl (DWZ) rating system competitor.

The DWZ is the German chess rating system, similar to Elo but with some differences in how ratings are updated after matches, including factors based on player age and performance.

Class Attributes:

_J (int): Development coefficient. Default: 10.

Initialize a DWZ competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 400.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating.

__init__(initial_rating: float = 400)[source]

Initialize a DWZ competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 400.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating.

beat(competitor: BaseCompetitor, age: int | None = None, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor wins against another.

Args:

competitor (BaseCompetitor): The opponent competitor. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

age (Optional[int]): The age of this competitor at the time of the match.

Used for DWZ calculation. Defaults to 26 (adult).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score (probability of winning) against another competitor.

Args:

competitor (BaseCompetitor): The opponent competitor to compare against.

Returns:

float: The probability of winning (between 0 and 1).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

DWZCompetitor: A new competitor with the same state as the exported one.

Raises:

InvalidParameterException: If any parameter in the state is invalid.

property rating: float

Get the current rating of this competitor.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

This method resets the competitor’s rating and count to their initial values.

tied(competitor: BaseCompetitor, age: int | None = None, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor ties with another.

Args:

competitor (BaseCompetitor): The opponent competitor. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

age (Optional[int]): The age of this competitor at the time of the match.

Used for DWZ calculation. Defaults to 26 (adult).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

ECF Competitor

class elote.competitors.ecf.ECFCompetitor(initial_rating: float = 100)[source]

Bases: BaseCompetitor

English Chess Federation (ECF) rating system competitor.

The ECF rating system is used by the English Chess Federation to rate chess players. It uses a moving average of performance ratings over a number of periods.

Class Attributes:

_delta (float): Maximum rating difference considered for updates. Default: 50. _n_periods (int): Number of periods to consider for the moving average. Default: 30.

Initialize an ECF competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 100.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating.

__init__(initial_rating: float = 100)[source]

Initialize an ECF competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 100.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

This method updates the ratings of both this competitor and the opponent based on the match outcome where this competitor won.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

property elo_conversion: float

Convert the ECF rating to an approximate Elo rating.

Returns:

float: The approximate Elo rating.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score (probability of winning) against another competitor.

Args:

competitor (BaseCompetitor): The opponent competitor to compare against.

Returns:

float: The probability of winning (between 0 and 1).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

ECFCompetitor: A new competitor with the same state as the exported one.

Raises:

InvalidParameterException: If any parameter in the state is invalid.

property rating: float

Get the current rating of this competitor.

The rating is the average of all scores in the deque.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

This method resets the competitor’s scores deque to contain only the initial rating.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

This method updates the ratings of both this competitor and the opponent based on a drawn match outcome.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

property transformed_elo_rating: float

Get the transformed Elo rating of this competitor.

The transformed rating is used in the expected score calculation.

Returns:

float: The transformed Elo rating.

Colley Matrix Competitor

Colley Matrix Method implementation for the Elote library.

The Colley Matrix Method is a least-squares rating system developed by Dr. Wesley Colley that solves a system of linear equations to obtain rankings. It’s widely used in sports rankings, particularly college football.

References: - Colley, W. N. (2002). Colley’s Bias Free College Football Ranking Method: The Colley Matrix Explained.

class elote.competitors.colley.ColleyMatrixCompetitor(initial_rating: float | None = None)[source]

Bases: BaseCompetitor

Colley Matrix Method competitor.

The Colley Matrix Method is a least-squares rating system that solves a system of linear equations to obtain rankings. Unlike Elo which updates ratings incrementally after each match, Colley Matrix recalculates all ratings using the entire match history.

Key characteristics: - Bias-free (doesn’t depend on schedule order) - Considers only wins and losses (not margin of victory) - Initial rating of 0.5 for all competitors - Final ratings are between 0 and 1 - Sum of all ratings equals n/2 (where n is number of competitors)

Class Attributes:

_minimum_rating (float): The minimum allowed rating value. Default: 0.0 _default_initial_rating (float): Default initial rating for all competitors. Default: 0.5

Initialize a new Colley Matrix competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 0.5.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating.

__init__(initial_rating: float | None = None)[source]

Initialize a new Colley Matrix competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 0.5.

Raises:

InvalidRatingValueException: If the initial rating is below the minimum rating.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

In Colley Matrix Method, we store the match result and recalculate ratings for all related competitors.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score against another competitor.

Args:

competitor (BaseCompetitor): The competitor to compare against.

Returns:

float: The expected score (probability of winning).

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

This method exports the competitor’s state in a standardized format that can be used to recreate the competitor with the same state.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

ColleyMatrixCompetitor: A new competitor with the same state as the exported one.

Raises:

KeyError: If the state dictionary is missing required keys.

lost_to(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has lost to the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that won. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Reversed before being passed to the winner’s beat().

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

property num_games: int

Get the total number of games played by this competitor.

Returns:

int: The total number of games played.

property rating: float

Get the current rating of this competitor.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

Massey Competitor

Massey Ratings implementation for the Elote library.

The Massey method is the least-squares counterpart to ColleyMatrixCompetitor. Where Colley solves a ridge-regularized win-percentage model whose ratings are bounded to [0, 1], Massey solves an unregularized least-squares system whose ratings live on a signed margin scale: the fitted rating difference r_i - r_j is the model’s predicted margin when i plays j.

The system is

\[M r = p\]

where M = D - A (D_ii is the number of games played by i and A_ij the number of games between i and j) and p_i is i’s cumulative margin. M is a graph Laplacian, so its rows sum to zero and it is singular by construction. The standard fix is applied: the last row is replaced with all ones and the last entry of p with zero, which pins the ratings to zero mean and makes the solution unique on a connected schedule.

References: - Massey, K. (1997). Statistical Models Applied to the Rating of Sports Teams.

Bluefield College undergraduate honors thesis.

  • Langville, A. N., & Meyer, C. D. (2012). Who’s #1? The Science of Rating and Ranking. Princeton University Press, chapter 2.

class elote.competitors.massey.MasseyCompetitor(initial_rating: float | None = None)[source]

Bases: BaseCompetitor

Massey Ratings competitor.

Massey’s method assigns every competitor a rating such that the difference between two ratings is a least-squares estimate of the margin by which one would beat the other. Like Colley and Bradley-Terry – and unlike Elo – ratings are not nudged after each result; the whole connected group is re-fit from the complete match history, which makes the method order independent.

Margins. beat / lost_to / tied accept the common optional scores payload, the two competitors’ scores in caller order. When it is supplied this is genuine margin-of-victory Massey – the form used in college football rankings – and the margin contributed by a game is self_score - competitor_score. When it is omitted the implementation falls back to unit margins: a win contributes +1 to the winner’s cumulative margin and -1 to the loser’s. A draw contributes 0 either way, while still counting as a game played for both.

Key characteristics: - Global least-squares fit (does not depend on the order of results) - Ratings are zero mean within a connected group, so roughly half of them are negative - The rating difference is directly interpretable as a predicted margin

Class Attributes:
_minimum_rating (float): The minimum allowed rating value. Default: -inf. Massey

ratings are zero mean and routinely negative, so no floor is imposed.

_default_initial_rating (float): Default initial rating. Default: 0.0. _expected_score_scale (float): Logistic scale used by expected_score() to turn a

rating difference into a win probability. Default: 2.0, chosen so that the widest plausible unit-margin gap maps to roughly the same probability as the widest gap under Colley’s 1 / (1 + exp(-4 * diff)).

_round_decimals (int): Number of decimal places fitted ratings are canonicalized to, so

that solver noise cannot make mathematically identical records differ. Default: 13.

Initialize a new Massey competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 0.0.

__init__(initial_rating: float | None = None)[source]

Initialize a new Massey competitor.

Args:

initial_rating (float, optional): The initial rating of this competitor. Default: 0.0.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

The result is recorded in the match graph and the whole connected group is re-fit.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). When supplied, the margin contributed to the Massey system is the real self_score - competitor_score; when omitted the unit margin +1 / -1 is used.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

classmethod configure_class(**kwargs: Any) None[source]

Configure class-level parameters for this rating system.

Overrides the base implementation to validate the expected-score scale.

Raises:

InvalidParameterException: If any parameter is invalid.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score against another competitor.

Massey ratings are on a margin scale rather than a probability scale, so the predicted margin r_self - r_competitor is squashed through a logistic function to obtain a win probability. Two competitors with equal ratings give exactly 0.5, and the two argument orders are exactly complementary.

Args:

competitor (BaseCompetitor): The competitor to compare against.

Returns:

float: The expected score (probability of winning).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

lost_to(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has lost to the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that won. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Reversed before being passed to the winner’s beat().

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

property num_games: int

Get the total number of games played by this competitor.

Returns:

int: The total number of games played.

property rating: float

Get the current rating of this competitor.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

A draw contributes nothing to either cumulative margin, but counts as a game played for both competitors.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). They must be equal, so a drawn game contributes a zero margin whether or not scores are supplied.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

Keener Competitor

Keener Ratings implementation for the Elote library.

Keener’s method is the score-based member of the classical global-fit family. Where ColleyMatrixCompetitor and MasseyCompetitor solve a linear system, Keener builds a square preference matrix from the points competitors have scored on one another and reads the ratings off that matrix’s dominant eigenvector.

The construction has four steps. Let S_ij be the total number of points i has scored against j across all their meetings.

  1. Smoothed preference. Raw score shares are unstable for lopsided or barely-played pairs, so Keener applies Laplace smoothing:

    \[a_{ij} = \frac{S_{ij} + 1}{S_{ij} + S_{ji} + 2}\]

    A pair that has never met gives a_ij = 1/2 – no evidence either way.

  2. Skew transform. a_ij is pushed away from the middle by Keener’s skew function

    \[h(x) = \frac{1}{2} + \frac{1}{2}\,\mathrm{sgn}\!\left(x - \frac{1}{2}\right) \sqrt{\left|2x - 1\right|}\]

    which is monotone, fixes 0, 1/2 and 1, and satisfies h(x) + h(1 - x) = 1, so the matrix stays antisymmetric about 1/2. Its square root damps the influence of very large margins, which is what stops the method rewarding running up the score without limit.

  3. Games-played normalization. Row i is divided by the number of games i played, so a competitor cannot accumulate rating merely by playing more often.

  4. Stabilization. A small positive constant is added to every entry. Keener’s own A + eps * E perturbation makes the matrix strictly positive, so Perron-Frobenius applies: the dominant eigenvalue is real and simple and its eigenvector is strictly positive and unique up to scale. Without it a schedule whose graph is bipartite or otherwise imprimitive has no single dominant eigenvector to read.

The ratings of a connected group are then that dominant eigenvector, scaled so they average exactly 1.0.

References: - Keener, J. P. (1993). The Perron-Frobenius Theorem and the Ranking of Football Teams.

SIAM Review, 35(1), 80-93.

  • Langville, A. N., & Meyer, C. D. (2012). Who’s #1? The Science of Rating and Ranking. Princeton University Press, chapter 4.

class elote.competitors.keener.KeenerCompetitor(initial_rating: float | None = None)[source]

Bases: BaseCompetitor

Keener Ratings competitor.

Keener rates a connected population from the dominant eigenvector of a pairwise preference matrix built from points scored. Like Colley, Massey and Bradley-Terry – and unlike Elo – ratings are not nudged after each result; the whole connected group is re-fit from the complete match history, which makes the method order independent.

Scores. beat / lost_to / tied accept the common optional scores payload, the two competitors’ scores in caller order. Keener is a score-based method, so supplying real scores is what it is built for. When they are omitted the implementation falls back to the same unit scores the rest of the library uses: the winner is credited 1 and the loser 0, and a draw credits each side 0.5. Unit-score Keener still produces a sensible ranking, but it only sees who beat whom.

Key characteristics: - Global eigenvector fit (does not depend on the order of results) - Ratings are strictly positive and average exactly 1.0 within a connected group - Large margins have a damped, not linear, influence thanks to the skew transform

Class Attributes:
_minimum_rating (float): The minimum allowed rating value. Default: 0.0. Keener

ratings are strictly positive, so no Elo-style floor applies.

_default_initial_rating (float): Default initial rating. Default: 1.0, which is the

mean the fitted ratings are normalized to, so an unplayed competitor sits exactly at the population average.

_perturbation (float): Keener’s eps, added to every matrix entry so the matrix is

strictly positive and Perron-Frobenius applies. Default: 1e-4.

_expected_score_scale (float): Logistic scale applied to the log rating ratio by

expected_score(). Default: 1.0, which is the plain Keener share r_a / (r_a + r_b).

_round_decimals (int): Number of decimal places fitted ratings are canonicalized to,

so that solver noise cannot make mathematically identical records differ. Default: 10, chosen because the eigen-solve’s row-order noise is around 5e-15 – five orders of magnitude below the rounding grid.

Initialize a new Keener competitor.

Args:
initial_rating (float, optional): The initial rating of this competitor.

Default: 1.0.

Raises:

InvalidRatingValueException: If the initial rating is not positive.

__init__(initial_rating: float | None = None)[source]

Initialize a new Keener competitor.

Args:
initial_rating (float, optional): The initial rating of this competitor.

Default: 1.0.

Raises:

InvalidRatingValueException: If the initial rating is not positive.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

The scores are recorded in the match graph and the whole connected group is re-fit.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). When omitted the unit scores 1 and 0 are recorded.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If scores does not describe a win for this competitor.

classmethod configure_class(**kwargs: Any) None[source]

Configure class-level parameters for this rating system.

Overrides the base implementation to validate the Keener-specific parameters.

Raises:

InvalidParameterException: If any parameter is invalid.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score against another competitor.

Keener ratings are positive strengths rather than probabilities, so the natural mapping is the share r_self / (r_self + r_competitor). That share is computed here as a logistic of the log rating ratio, which is the same quantity written in a form that is exactly complementary in floating point: two equal ratings give exactly 0.5, and the two argument orders sum to exactly 1.0.

Args:

competitor (BaseCompetitor): The competitor to compare against.

Returns:

float: The expected score (probability of winning).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

lost_to(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has lost to the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that won. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Reversed before being passed to the winner’s beat().

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If scores does not describe a loss for this competitor.

property num_games: int

Get the total number of games played by this competitor.

Returns:

int: The total number of games played.

property rating: float

Get the current rating of this competitor.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). They must be equal. When omitted each side is credited the unit draw score 0.5.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If scores does not describe a draw.

Bradley-Terry Competitor

Bradley-Terry model implementation for the Elote library.

The Bradley-Terry model is a probabilistic model for paired comparisons. Each competitor is assigned a latent strength, and the probability that competitor i beats competitor j is p_i / (p_i + p_j). Working in the log domain with p_i = exp(beta_i) this is the logistic function sigmoid(beta_i - beta_j) – the same functional form as the Elo expected score.

Unlike Elo, which nudges ratings incrementally after every game, the Bradley-Terry strengths are obtained by maximum likelihood estimation over the full set of observed comparisons. This implementation follows the same approach as ColleyMatrixCompetitor: each competitor accumulates its match history and, after every result, the strengths of the whole connected component are re-fit. The fit uses the minorization-maximization (MM) update of Hunter (2004) with geometric-mean normalization and a small amount of regularization so that a unique, finite solution exists even when a competitor is undefeated or winless within its component.

References: - Bradley, R. A., & Terry, M. E. (1952). Rank Analysis of Incomplete Block Designs: I. The

Method of Paired Comparisons. Biometrika, 39(3/4), 324-345.

  • Hunter, D. R. (2004). MM algorithms for generalized Bradley-Terry models. The Annals of Statistics, 32(1), 384-406.

class elote.competitors.bradley_terry.BradleyTerryCompetitor(initial_rating: float | None = None)[source]

Bases: BaseCompetitor

Bradley-Terry model competitor.

The Bradley-Terry model assigns each competitor a latent strength and models the probability that one competitor beats another as a function of the difference of their log-strengths. Unlike Elo, which updates ratings incrementally, Bradley-Terry re-fits the strengths of every connected competitor via maximum likelihood after each result.

Ratings are reported on an Elo-like scale via rating = anchor + scale * beta, where beta is the internal log-strength (re-centered so the mean log-strength of a component is zero). Choosing scale = 400 / ln(10) makes expected_score() numerically identical to the Elo expected score, so ratings are directly comparable to Elo ratings.

Key characteristics: - Global maximum-likelihood fit (does not depend on the order of results) - Considers only wins and losses (ties are counted as half a win for each side) - Regularized so a unique, finite fit exists even for undefeated/winless competitors

Class Attributes:

_minimum_rating (float): The minimum allowed rating value. Default: 0.0. _anchor_rating (float): Rating assigned to the mean log-strength. Default: 1500.0. _scale (float): Points per unit of log-strength. Default: 400 / ln(10). _reg (float): Regularization strength (virtual wins/losses against an average

phantom opponent). Default: 0.1.

_max_iter (int): Maximum MM iterations per fit. Default: 10000. _tol (float): Convergence tolerance on the max change in log-strength. Default: 1e-8.

Initialize a new Bradley-Terry competitor.

Args:
initial_rating (float, optional): The initial rating of this competitor, on the

Elo-like reporting scale. Default: the anchor rating (1500).

Raises:

InvalidParameterException: If the regularization or iteration parameters are invalid.

__init__(initial_rating: float | None = None)[source]

Initialize a new Bradley-Terry competitor.

Args:
initial_rating (float, optional): The initial rating of this competitor, on the

Elo-like reporting scale. Default: the anchor rating (1500).

Raises:

InvalidParameterException: If the regularization or iteration parameters are invalid.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

The result is recorded on both competitors and the strengths of the entire connected component are re-fit by maximum likelihood.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

classmethod configure_class(**kwargs: Any) None[source]

Configure class-level parameters for this rating system.

Overrides the base implementation to validate the regularization and iteration parameters.

Raises:

InvalidParameterException: If any parameter is invalid.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score against another competitor.

Args:

competitor (BaseCompetitor): The competitor to compare against.

Returns:

float: The expected score (probability of winning).

lost_to(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has lost to the given competitor.

Args:

competitor (BaseCompetitor): The opponent competitor that won. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Reversed before being passed to the winner’s beat().

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

property num_games: int

Get the total number of games played by this competitor.

Returns:

int: The total number of games played.

property rating: float

Get the current rating of this competitor on the Elo-like reporting scale.

Returns:

float: The current rating.

reset() None[source]

Reset this competitor to its initial state.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

A tie is counted as half a win for each side.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Validated but not otherwise used by this rating system.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

Blended Competitor

class elote.competitors.ensemble.BlendedCompetitor(competitors: List[Dict[str, Any]], blend_mode: str = 'mean')[source]

Bases: BaseCompetitor

Ensemble rating system that combines multiple rating algorithms.

The BlendedCompetitor allows combining multiple rating systems to leverage their individual strengths while mitigating their weaknesses. By aggregating predictions from different rating algorithms, it can potentially provide more robust and accurate predictions than any single rating system alone.

Supported blend modes:
  • “mean”: Average the expected scores from all sub-competitors.

Initialize a BlendedCompetitor with multiple rating systems.

Args:
competitors (List[Dict[str, Any]]): List of dictionaries specifying the

sub-competitors to use. Each dictionary should have a “type” key with the name of the competitor class and a “competitor_kwargs” key with the arguments to pass to the constructor.

blend_mode (str, optional): The method to use for blending the ratings.

Currently only “mean” is supported. Default: “mean”.

Raises:
InvalidParameterException: If the blend_mode is not supported or if any

competitor specification is invalid.

__init__(competitors: List[Dict[str, Any]], blend_mode: str = 'mean')[source]

Initialize a BlendedCompetitor with multiple rating systems.

Args:
competitors (List[Dict[str, Any]]): List of dictionaries specifying the

sub-competitors to use. Each dictionary should have a “type” key with the name of the competitor class and a “competitor_kwargs” key with the arguments to pass to the constructor.

blend_mode (str, optional): The method to use for blending the ratings.

Currently only “mean” is supported. Default: “mean”.

Raises:
InvalidParameterException: If the blend_mode is not supported or if any

competitor specification is invalid.

beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has won against the given competitor.

This method updates the ratings of all sub-competitors based on the match outcome.

Args:

competitor (BaseCompetitor): The opponent competitor that lost. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Forwarded unchanged to every sub-competitor.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

expected_score(competitor: BaseCompetitor) float[source]

Calculate the expected score (probability of winning) against another competitor.

For a BlendedCompetitor, the expected score is calculated by blending the expected scores from all sub-competitors according to the blend_mode.

Args:

competitor (BaseCompetitor): The opponent competitor to compare against.

Returns:

float: The probability of winning (between 0 and 1).

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match. NotImplementedError: If the blend_mode is not supported.

export_state() Dict[str, Any][source]

Export the current state of this competitor for serialization.

Returns:
dict: A dictionary containing all necessary information to recreate

this competitor’s current state.

classmethod from_state(state: Dict[str, Any]) T[source]

Create a new competitor from a previously exported state.

Args:
state (dict): A dictionary containing the state of a competitor,

as returned by export_state().

Returns:

BlendedCompetitor: A new competitor with the same state as the exported one.

Raises:

InvalidStateException: If the state dictionary is invalid or incompatible. InvalidParameterException: If any competitor specification is invalid.

property rating: float

Get the combined rating of this competitor.

For a BlendedCompetitor, the rating is the sum of all sub-competitor ratings. This is a simple way to represent the overall strength, but the expected_score method provides a more accurate way to compare competitors.

Returns:

float: The combined rating.

reset() None[source]

Reset this competitor to its initial state.

This method resets all sub-competitors to their initial states.

tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]

Update ratings after this competitor has tied with the given competitor.

This method updates the ratings of all sub-competitors based on the drawn match outcome.

Args:

competitor (BaseCompetitor): The opponent competitor that tied. scores (sequence of float, optional): The two scores in caller order,

(self_score, competitor_score). Must be equal. Forwarded unchanged to every sub-competitor.

Raises:

MissMatchedCompetitorTypesException: If the competitor types don’t match.

verify_competitor_types(competitor: BaseCompetitor) None[source]

Verify that both ensembles have matching sub-competitor types.