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:
ABCBase 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.
- classmethod apply_rating_period(results: Sequence[Tuple[BaseCompetitor, BaseCompetitor, float, Sequence[float] | None]], *, period_end: Any | None = None) None[source]¶
Apply results that share one rating period.
The default implementation replays results in order through the pairwise methods. Rating systems whose published update is period-native can override this method to update the population simultaneously without changing the existing pairwise API.
- Args:
- results:
(competitor_a, competitor_b, outcome, scores)tuples. Outcomes use
1.0for an A win,0.0for a B win, and0.5for a draw; scores follow the same optional caller-order contract asbeat().
period_end: The shared activity time for time-aware competitors.
- results:
- Raises:
- ValueError: If an outcome is not
1.0,0.0, or0.5, or if a score payload is invalid or inconsistent with its outcome.
- ValueError: If an outcome is not
- 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 asMasseyCompetitor) 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
scoresis malformed, negative, non-finite, or does not describea 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’sbeat(), so the caller never reorders them.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If
scoresis malformed, negative, non-finite, or does not describea 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
scoresis 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:
ExceptionException 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:
ExceptionException 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:
ExceptionException 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:
ExceptionException 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))xisa’s score andyisb’s. The same ordering holds forlost_to,tiedandelote.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. Any real number is accepted – including NumPy scalars such as
np.int64andnp.float32– and normalized to a built-infloat.- outcome (float): The declared result from the first score’s perspective –
1.0(first competitor won),0.0(first competitor lost) or0.5(draw).
- scores (sequence of float, optional): The two scores in caller order, or
- Returns:
tuple of float, or None: The validated scores as floats, or
Nonewhen 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:
BaseCompetitorElo 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:
BaseCompetitorGlicko 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.
- lost_to(competitor: GlickoCompetitor, match_time: datetime | None = None, *, 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, forwarding the match time so a loser-side result still records elapsed-time RD inflation.- Args:
competitor (GlickoCompetitor): The opponent competitor that won. match_time (datetime, optional): The time when the match occurred. Default: current time. scores (sequence of float, optional): The two scores in caller order,
(self_score, competitor_score). They are reversed before being handed to the winner’sbeat(), so the caller never reorders them.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match.
- 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:
BaseCompetitorGlicko-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.
- lost_to(competitor: Glicko2Competitor, match_time: datetime | None = None, *, 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, forwarding the match time so a loser-side result still records elapsed-time RD inflation.- Args:
competitor (Glicko2Competitor): The opponent competitor that won. match_time (datetime, optional): The time when the match occurred. Default: current time. scores (sequence of float, optional): The two scores in caller order,
(self_score, competitor_score). They are reversed before being handed to the winner’sbeat(), so the caller never reorders them.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match.
- 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_timeso 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.
Glicko-Boost Competitor¶
- class elote.competitors.glicko_boost.GlickoBoostCompetitor(initial_rating: float = 1500, initial_rd: float = 250, initial_time: datetime | None = None)[source]¶
Bases:
BaseCompetitorGlicko-Boost rating system competitor.
Glicko-Boost is Mark Glickman’s extension of Glicko, described in Glicko-Boost. Unlike Elo or Glicko it is defined over a whole rating period rather than over one game: the population is updated twice from the same pre-period ratings, players whose performance was exceptional have their pre-period RD boosted, and the pair of updates is then repeated. This class therefore overrides
apply_rating_period()and is the first shipped system whose period update is not a replay of pairwise results.The six steps applied to one period are:
Glicko updating of every player from the pre-period ratings and RDs, with a white-advantage term inside
E().The same update from the pre-period ratings, but against the opponents’ step 1 ratings and RDs.
An RD boost for players whose performance z-score exceeds
k.Step 1 again, using the boosted RDs.
Step 2 again, using the step 4 results. These are the period’s final ratings.
An RD increase for the passage of time, applied when the competitor next takes part in a period (the way
GlickoCompetitorhandles inactivity), so a competitor that sits out periods catches up on its next appearance.
Colour is carried by argument order rather than by a new parameter: in a rating period row
(a, b, outcome, scores)– and ina.beat(b),a.lost_to(b)ora.tied(b)–ais white. Callers with no colour information leave_etaat its default of0.0, which removes the white-advantage term entirely.elote.LambdaArena.matchup()andelote.LambdaArena.rating_period()preserve that order – a loss is dispatched as the caller’slost_to– so a losing row streamed through the arena gives the same result as the same row handed toapply_rating_period().elote.train_arena_with_dataset()andelote.LambdaArena.process_history()still reverse a losing row themselves, which matters only when_etais non-zero.beat/lost_to/tiedapply the same algorithm to a one-game period, so a single result is never a different formula from a batch. Because of the two-pass structure a lone pairwise call is not identical to a Glicko update.- Class Attributes:
_q (float):
ln(10)/400, the Glicko scaling constant. _eta (float): Rating advantage for playing white. Default:0.0; Glickman’s is30.0. _b1 (float): RD boost multiplicative factor. Default: 0.20139. _b2 (float): RD boost additive factor. Default: 17.5. _k (float): The z-score above which an RD is boosted. Default: 1.96. _alpha0 .. _alpha4 (float): RD-increase-over-time coefficients, at Glickman’s values. _rd_unrated (float): The RD cap,RD_unrin the paper. Default: 250.0. _rating_period_days (float): Days in one rating period. Default: 30.0 (a month).
Initialize a Glicko-Boost competitor.
- Args:
- initial_rating (float, optional): The initial rating of this competitor. Default: 1500.
Glickman’s FIDE-specific default for an unrated player is 1946.25.
- initial_rd (float, optional): The initial rating deviation. Default: 250, the
paper’s
RD_unr.- 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 period, so 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 = 250, initial_time: datetime | None = None)[source]¶
Initialize a Glicko-Boost competitor.
- Args:
- initial_rating (float, optional): The initial rating of this competitor. Default: 1500.
Glickman’s FIDE-specific default for an unrated player is 1946.25.
- initial_rd (float, optional): The initial rating deviation. Default: 250, the
paper’s
RD_unr.- 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 period, so 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.
- classmethod apply_rating_period(results: Sequence[Tuple[BaseCompetitor, BaseCompetitor, float, Sequence[float] | None]], *, period_end: Any | None = None) None[source]¶
Apply results that share one rating period, using Glicko-Boost’s own period update.
This is where the whole algorithm lives: the pairwise methods route a single result through here as a one-game period, so every caller gets the same formulas.
- Args:
- results:
(white, black, outcome, scores)tuples. Outcomes use1.0for a white win,
0.0for a black win and0.5for a draw; scores follow the usual optional caller-order contract and are validated but not consumed.- period_end: The shared activity time for the period. Elapsed rating periods since
each participant’s last activity inflate its RD before the update.
- results:
- Raises:
ValueError: If an outcome or score payload is invalid. MissMatchedCompetitorTypesException: If a row contains another rating system.
- 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.
The result is applied as a one-game rating period in which this competitor had white.
- Args:
competitor (BaseCompetitor): The opponent competitor that lost. match_time (datetime, optional): The time of the match, used as the period’s end. scores (sequence of float, optional): The two scores in caller order. Validated only.
- 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.
This uses the paper’s own approximation, which combines the two rating deviations rather than using only the opponent’s. With
_etaat its default of0.0the result is exactly complementary:a.expected_score(b) + b.expected_score(a) == 1.- 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.
- lost_to(competitor: BaseCompetitor, match_time: datetime | None = None, *, scores: Sequence[float] | None = None) None[source]¶
Update ratings after this competitor has lost to the given competitor.
The result is applied as a one-game rating period in which this competitor had white, so the colour convention still follows the caller’s argument order.
- Args:
competitor (BaseCompetitor): The opponent competitor that won. match_time (datetime, optional): The time of the match, used as the period’s end. scores (sequence of float, optional): The two scores in caller order.
- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match.
- property rating: float¶
Get the current rating of this competitor.
- Returns:
float: The current rating.
- tied(competitor: BaseCompetitor, match_time: datetime | None = None, *, scores: Sequence[float] | None = None) None[source]¶
Update ratings after this competitor has drawn with the given competitor.
- Args:
competitor (BaseCompetitor): The opponent competitor that drew. match_time (datetime, optional): The time of the match, used as the period’s end. scores (sequence of float, optional): The two scores in caller order. Must be equal.
- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match.
TrueSkill Competitor¶
- class elote.competitors.trueskill.TrueSkillCompetitor(initial_mu: float = None, initial_sigma: float = None)[source]¶
Bases:
BaseCompetitorTrueSkill 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 mu is not finite or sigma is not finite and 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 mu is not finite or sigma is not finite and 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.
- import_state(state: Dict[str, Any]) None[source]¶
Import a modern state document without partially applying invalid values.
- 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:
BaseCompetitorDeutsche 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:
BaseCompetitorEnglish 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:
BaseCompetitorColley 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 the ratings of all related competitors are re-fit lazily, on the next rating read.
- 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’sbeat().- 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.
Reading the rating is where deferred matrix solves happen: if games have been recorded since the last read, the connected group is re-fit first.
- Returns:
float: The current rating.
- 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
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:
BaseCompetitorMassey 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/tiedaccept the common optionalscorespayload, 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 isself_score - competitor_score. When it is omitted the implementation falls back to unit margins: a win contributes+1to the winner’s cumulative margin and-1to the loser’s. A draw contributes0either 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
Rating scale. Because the rating difference carries the caller’s own units, every fit also records
_rating_scale, the spread of the connected group’s ratings.expected_score()divides by it, so the win probabilities do not change when the same schedule is expressed in different point units, and do not saturate to 0.0/1.0 when real point margins put the ratings on a points-per-game scale. It is1.0for a competitor that has never been fitted, and it survivesexport_state()/from_state().- 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): Dimensionless sharpness multiplier used by
expected_score(). The rating difference is divided by the fitted rating spread before it reaches the logistic, so this constant does not depend on the units the caller’s scores are in. Default: 2.0, chosen so that the widest plausible unit-margin gap maps to roughly the same probability as the widest gap under Colley’s1 / (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.
- _minimum_rating (float): The minimum allowed rating value. Default:
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 lazily, on the next rating read.
- 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 realself_score - competitor_score; when omitted the unit margin+1 / -1is 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_competitoris squashed through a logistic function to obtain a win probability. Because that margin is in whatever units the caller’s scores are in – unit margins whenscoresis omitted, points per game when it is supplied – the difference is first divided by the fitted rating spread (the root-mean-square rating difference within the connected group, see_update_rating_scale()). That makes the logistic argument dimensionless and leaves_expected_score_scalea pure sharpness knob. 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’sbeat().- 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.
Reading the rating is where deferred least-squares solves happen: if games have been recorded since the last read, the connected group is re-fit first.
- Returns:
float: The current rating.
- 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.
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.Skew transform.
a_ijis 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/2and1, and satisfiesh(x) + h(1 - x) = 1, so the matrix stays antisymmetric about1/2. Its square root damps the influence of very large margins, which is what stops the method rewarding running up the score without limit.Games-played normalization. Row
iis divided by the number of gamesiplayed plus a small prior, so a competitor cannot accumulate rating merely by playing more often, and cannot accumulate it by playing barely at all either. The prior matters on a ragged schedule: without it, a competitor’s single game concentrates its entire row on one opponent, which the eigenvector reads as strength.Stabilization. A small positive constant is added to every entry. Keener’s own
A + eps * Eperturbation 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:
BaseCompetitorKeener 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/tiedaccept the common optionalscorespayload, 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 credited1and the loser0, and a draw credits each side0.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.
- _games_prior (float): Pseudo-games added to the games-played denominator, shrinking a
competitor’s average preference toward zero in proportion to how little evidence backs it. Default: 2.0, matching the two pseudo-observations the Laplace-smoothed score share already assumes. Without it, a competitor with a single game puts all of its row weight on one opponent and the dominant eigenvector rewards that concentration, so a one-game team can outrate an undefeated one.
- _expected_score_scale (float): Logistic scale applied to the log rating ratio by
expected_score(). Default: 1.0, which is the plain Keener sharer_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 lazily, on the next rating read.
- 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 scores1and0are recorded.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If
scoresdoes 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’sbeat().- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If
scoresdoes 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.
Reading the rating is where deferred eigenvector fits happen: if games have been recorded since the last read, the connected group is re-fit first.
- Returns:
float: The current rating.
- 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 score0.5.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If
scoresdoes not describe a draw.
Pythagorean Competitor¶
Pythagorean expectation implementation for the Elote library.
Pythagorean expectation is the oldest points-based rating in the sports canon. Bill James introduced it for baseball in the early 1980s, observing that a team’s winning percentage is predicted remarkably well by the runs it scored and the runs it allowed:
The name comes from the resemblance to the Pythagorean theorem in the original k = 2
form. The exponent is the one free parameter, and it is fitted per sport: 2 for baseball
(James’ original), around 2.37 for American football, and around 14 for basketball, where
scores are much larger and a point is worth correspondingly less.
Two properties make it unusual in this library.
The rating is already a win expectation. Every other shipped system produces a strength score that has to be mapped through a logistic, a normal CDF or a share before it can be read as a probability. A Pythagorean rating is a number in
[0, 1]that reads directly as “the fraction of games this competitor should win against the field it has played”.It ignores the opponent graph entirely. A competitor’s rating depends only on its own accumulated points for and points against, never on who supplied them. That makes it the cheapest system here – a constant-time update with no graph, no matrix and no refit – and also its main limitation: it makes no strength-of-schedule adjustment at all.
Two competitors are compared through the standard log5 combination of their two win expectations,
which is Bill James’ formula for the probability that a beats b given the rate at
which each of them beats the field.
References:
- James, B. (1981). The Bill James Baseball Abstract. The original k = 2 formulation.
- Schatz, A. (2003). “Pythagoras on the Gridiron”, Football Outsiders. The k = 2.37 fit
for American football used as the default here.
Miller, S. J. (2007). “A Derivation of the Pythagorean Won-Loss Formula in Baseball”. Chance, 20(1), 40-48. Derives the formula from a Weibull model of scoring.
- class elote.competitors.pythagorean.PythagoreanCompetitor(exponent: float | None = None)[source]¶
Bases:
BaseCompetitorPythagorean expectation competitor.
Rates a competitor from the points it has scored and the points it has allowed. Unlike Colley, Massey, Keener and Bradley-Terry, nothing is fitted across a population: each result adds to two running totals, and the rating is read straight off them. Unlike Elo and the other incremental systems, the update does not depend on the opponent at all.
Scores.
beat/lost_to/tiedaccept the common optionalscorespayload, the two competitors’ scores in caller order. Points are what this system is built on, so supplying real ones is the intended use. When they are omitted the same unit-score fallback the rest of the library uses applies: the winner is credited1and the loser0, and a draw credits each side0.5. On unit scores the rating degenerates into a smoothed winning percentage, which is still a usable baseline.Degenerate inputs. A fresh competitor has
PF = PA = 0and an unbeaten one hasPA = 0; the first makes the rating0/0and the second makes it exactly1, which in turn makes log50/0. Both are handled by a small symmetric prior added to each accumulator rather than by clamping the output: the rating stays a continuous, strictly monotone function of the real totals, a fresh competitor is exactly0.5, and every rating is strictly inside(0, 1), so log5 is always defined.Key characteristics: - The rating is a win expectation in [0, 1], not a strength score - Constant-time update: no opponent graph, no refit, no order dependence - Reads real scores; falls back to unit scores when they are omitted - Makes no strength-of-schedule adjustment whatsoever
- Class Attributes:
- _minimum_rating (float): The minimum allowed rating value. Default: 0.0. The rating
is a probability, so the inherited Elo-style floor of 100 would saturate it.
- _default_initial_rating (float): The rating of a competitor that has not played.
Default: 0.5, which the symmetric prior produces exactly.
- _exponent (float): Pythagorean
k. Default: 2.37, the standard fit for American football (Football Outsiders). Use 2 for baseball, or a much larger value for a high-scoring sport such as basketball.
- _prior_points (float): The symmetric prior added to both accumulators, in points.
Default: 1.0 – comparable to the unit scores, negligible against real ones.
Initialize a Pythagorean competitor.
There is deliberately no
initial_ratingargument: the rating is derived from the points totals rather than stored, and a caller-supplied starting rating on a[0, 1]scale has no points totals that would produce it.- Args:
- exponent (float, optional): The Pythagorean exponent for this competitor. If
None, the class exponent is used. Default: None.
- Raises:
InvalidParameterException: If the exponent is not positive.
- __init__(exponent: float | None = None)[source]¶
Initialize a Pythagorean competitor.
There is deliberately no
initial_ratingargument: the rating is derived from the points totals rather than stored, and a caller-supplied starting rating on a[0, 1]scale has no points totals that would produce it.- Args:
- exponent (float, optional): The Pythagorean exponent for this competitor. If
None, the class exponent is used. Default: None.
- Raises:
InvalidParameterException: If the exponent 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). When omitted the unit scores1and0are recorded.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If
scoresdoes 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 Pythagorean-specific parameters.
- Raises:
InvalidParameterException: If any parameter is invalid.
- expected_score(competitor: BaseCompetitor) float[source]¶
Calculate the expected score against another competitor.
Both ratings are already win expectations, so they are combined with the standard log5 formula. The direction with the larger rating is the one actually computed and the other is taken as its complement, which makes the two argument orders sum to exactly 1.0 and makes two equal ratings give exactly 0.5.
- 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.
- 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.
The rating is the Pythagorean win expectation
PF^k / (PF^k + PA^k), computed on the prior-adjusted totals. It is evaluated in the equivalent ratio form1 / (1 + (PA/PF)^k), which cannot overflow for large totals and returns exactly 0.5 whenever the two totals are equal.- Returns:
float: The current rating, strictly inside (0, 1).
- 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 score0.5.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If
scoresdoes 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:
BaseCompetitorBradley-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, wherebetais the internal log-strength (re-centered so the mean log-strength of a component is zero). Choosingscale = 400 / ln(10)makesexpected_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’sbeat().- 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.
- 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.
Whole-History Rating Competitor¶
Whole-History Rating (WHR) for time-aware paired comparisons.
- class elote.competitors.whr.WholeHistoryRatingCompetitor(w2: float | None = None, initial_rating: float | None = None, max_iterations: int | None = None, precision: float | None = None)[source]¶
Bases:
BaseCompetitorA time-aware Bradley-Terry maximum-a-posteriori rating curve.
One latent rating is kept for every distinct playing day. Consecutive ratings are linked by a Wiener-process prior whose variance is
w2 * elapsed_daysin Elo points squared. Results use the Bradley-Terry likelihood, and a bounded sequence of per-competitor tridiagonal Newton updates fits the connected component lazily.Serialized state preserves the fitted per-day curve and day index, but cannot preserve object references in the game graph. On the first result after restore, the latest restored rating becomes the initial rating of a fresh history; restored lifetime games are therefore never silently combined with a reset graph.
- Args:
w2: Per-day Wiener-process variance in Elo points squared. initial_rating: Rating before any games, on the Elo scale. max_iterations: Maximum component-wide Newton sweeps per lazy fit. precision: Stop when the largest Elo-scale Newton step is below this value.
Reference: Coulom, R. (2008), Whole-History Rating: A Bayesian Rating System for Players of Time-Varying Strength.
Initialize base competitor state.
- __init__(w2: float | None = None, initial_rating: float | None = None, max_iterations: int | None = None, precision: float | None = None) None[source]¶
Initialize base competitor state.
- 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 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 asMasseyCompetitor) 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
scoresis malformed, negative, non-finite, or does not describea win for this competitor.
- 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.
- 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.
- lost_to(competitor: BaseCompetitor, match_time: datetime | None = None, *, 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’sbeat(), so the caller never reorders them.- Raises:
MissMatchedCompetitorTypesException: If the competitor types don’t match. ValueError: If
scoresis malformed, negative, non-finite, or does not describea loss for this competitor.
- property num_games: int¶
- property rating: float¶
Get the current rating value of this competitor.
- Returns:
float: The current rating value.
- rating_at(when: datetime | date) float[source]¶
Return the fitted rating on, or most recently before,
when.
- rating_history() List[Tuple[date, float]][source]¶
Return a chronological copy of the fitted
(day, rating)curve.
- 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.
- 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 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
scoresis malformed, negative, non-finite, or is not a draw.
Blended Competitor¶
- class elote.competitors.ensemble.BlendedCompetitor(competitors: List[Dict[str, Any]], blend_mode: str = 'mean')[source]¶
Bases:
BaseCompetitorEnsemble 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.
Team Competitor¶
- class elote.competitors.team.TeamCompetitor(members: Sequence[BaseCompetitor], aggregate: str = 'mean')[source]¶
Bases:
BaseCompetitorComposite competitor that rates a roster of members as a single side.
A
TeamCompetitorwraps a roster ofBaseCompetitorinstances and exposes the usual competitor interface for the team as a whole. Bouts between two teams delegate to the members positionally: memberiof one roster is paired against memberiof the other, and each pair updates through the member rating system’s ownbeat/tiedmath. The wrapper keeps no rating state of its own – the team rating is derived from the members on every read, so rating history follows the member objects.Because both endpoints of such a bout are
TeamCompetitorinstances, team-vs-team play works in existing arenas (e.g.LambdaArena) with no arena changes: seed the arena with the teams – for example throughinitial_statewith exported team state documents – and runmatchupas usual.Aggregation modes¶
The
aggregateflag selects how member ratings combine into the single number theratingproperty exposes – the team’s entry on any leaderboard:"mean"Arithmetic mean of the member ratings. The team’s rating lives on the same scale as the members’ own rating system, so team entries and individual competitors can share one leaderboard and be compared directly. Adding or swapping a member moves the aggregate toward that member’s rating; a weak member dilutes a strong roster.
"sum"Sum of the member ratings – the roster’s total rating mass. The value grows with roster size, so it is only meaningful between rosters of the same size: on a shared leaderboard a larger roster outranks a smaller one regardless of per-member strength. Choose
sumwhen the combined mass is the quantity of interest, and compare sum-mode teams only against rosters of the same size.
In both modes
expected_score()pairs members positionally and returns the mean of the members’ own model probabilities, so predictions are valid probabilities either way; the flag governs the exposed rating aggregate only.A note on members: aggregation consumes the
.ratingscalar each member exposes. For Bayesian systems (TrueSkill, Whole-History Rating) that scalar is a derived ordinal, so an aggregate of ordinals is a convenience figure, not a fusion of the underlying belief distributions. Member-level team updates – a single result distributed across a roster natively inside the rating model – arrive with the OpenSkill N-way bout support.Serialization is nested: the exported parameters carry the roster as
(type, init parameters)specifications, and the exported state carries each member’s full exported state document. Membership identity is preserved by roster position and concrete type, so a restored team has the same members, in the same roles, with their rating histories intact.reset()delegates to the members, restoring each to its own initial state.Initialize a TeamCompetitor from a roster of member competitors.
- Args:
- members (sequence of BaseCompetitor): The roster. Order defines the pairing
used for bouts and the membership identity preserved by serialization; copy the roster rather than aliasing the caller’s list.
- aggregate (str, optional): The aggregation mode for the exposed team rating.
"mean"or"sum". Default:"mean".
- Raises:
- InvalidParameterException: If
aggregateis not a supported mode, the roster is empty, or any roster entry is not a
BaseCompetitor.
- InvalidParameterException: If
- __init__(members: Sequence[BaseCompetitor], aggregate: str = 'mean') None[source]¶
Initialize a TeamCompetitor from a roster of member competitors.
- Args:
- members (sequence of BaseCompetitor): The roster. Order defines the pairing
used for bouts and the membership identity preserved by serialization; copy the roster rather than aliasing the caller’s list.
- aggregate (str, optional): The aggregation mode for the exposed team rating.
"mean"or"sum". Default:"mean".
- Raises:
- InvalidParameterException: If
aggregateis not a supported mode, the roster is empty, or any roster entry is not a
BaseCompetitor.
- InvalidParameterException: If
- beat(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]¶
Update ratings after this team has won against the given team.
Members are paired positionally: member
iof this team beats memberiof the opposing team through the members’ own rating math.- Args:
competitor (BaseCompetitor): The opponent team that lost. scores (sequence of float, optional): The two scores in caller order,
(self_score, competitor_score). Forwarded unchanged to every member pair.- Raises:
MissMatchedCompetitorTypesException: If the roster compositions don’t match.
- expected_score(competitor: BaseCompetitor) float[source]¶
Calculate the expected score (probability of winning) against another team.
Members are paired positionally and the result is the mean of the members’ own model probabilities. This is independent of the
aggregatemode: predictions are probabilities in both modes; the flag governs the exposed rating only.- Args:
competitor (BaseCompetitor): The opponent team to compare against.
- Returns:
float: The probability of winning (between 0 and 1).
- Raises:
MissMatchedCompetitorTypesException: If the roster compositions don’t match.
- property rating: float¶
Get the aggregate rating of the team.
The value is derived from the members on every read according to the
aggregatemode: the mean of the member ratings, or their sum. See the class docstring for the semantics of each mode and its leaderboard implications.- Returns:
float: The aggregate team rating.
- reset() None[source]¶
Reset this team to its initial state.
Delegates to each member, restoring every member to its own initial rating. The roster composition itself never changes.
- tied(competitor: BaseCompetitor, *, scores: Sequence[float] | None = None) None[source]¶
Update ratings after this team has tied with the given team.
Members are paired positionally: member
iof this team ties memberiof the opposing team through the members’ own rating math.- Args:
competitor (BaseCompetitor): The opponent team that tied. scores (sequence of float, optional): The two scores in caller order,
(self_score, competitor_score). Must be equal. Forwarded unchanged to every member pair.- Raises:
MissMatchedCompetitorTypesException: If the roster compositions don’t match.
- verify_competitor_types(competitor: BaseCompetitor) None[source]¶
Verify that both competitors are teams with matching roster composition.
Two teams can only bout when both are
TeamCompetitorinstances and their rosters have the same composition: the same member types in the same roster order, which also implies the same roster size. Member states may differ (that is what a bout updates); the composition may not.- Args:
competitor (BaseCompetitor): The competitor to verify.
- Raises:
- MissMatchedCompetitorTypesException: If the competitor is not a
TeamCompetitor, or its roster composition differs.