Module rating.rating.glicko
Classes
class Glicko (default_change: float = 400, C: float = 50, max_exp_value=10, iterations=1, **kwargs)
-
Implementation of the Glicko rating system.
The Glicko rating system is a method for calculating the ratings of players in games such as chess. It takes into account the ratings of opponents and the outcomes of games to update a player's rating.
Attributes
- default_change (float): The default rating change value.
- C (float): The constant value used in the rating update formula.
- max_exp_value (int): The maximum value for the exponent in the expected score formula. Prevents overflow errors.
Args
- default_change (float, optional): The default change value. Defaults to 400.
- C (float, optional): The C value. Defaults to 50.
- max_exp_value (int, optional): The maximum value for the exponent in the expected score formula. Prevents overflow errors. Defaults to 10.
Expand source code
class Glicko(RatingSystem): def __init__(self, default_change : float = 400, C : float = 50, max_exp_value=10, iterations=1, **kwargs) -> 'Glicko': """ Implementation of the Glicko rating system. The Glicko rating system is a method for calculating the ratings of players in games such as chess. It takes into account the ratings of opponents and the outcomes of games to update a player's rating. Attributes: - default_change (float): The default rating change value. - C (float): The constant value used in the rating update formula. - max_exp_value (int): The maximum value for the exponent in the expected score formula. Prevents overflow errors. Args: - default_change (float, optional): The default change value. Defaults to 400. - C (float, optional): The C value. Defaults to 50. - max_exp_value (int, optional): The maximum value for the exponent in the expected score formula. Prevents overflow errors. Defaults to 10. """ super().__init__(default_change=default_change, C=C, max_exp_value=max_exp_value, iterations=iterations, **kwargs) def period_update(self, player_database : PlayerDatabase, game_database : GameDatabase, period_dates : List[datetime], **kwargs): period_dates = period_dates[:] period_dates.insert(0, None) for iteration in range(self.iterations): updated_ratings = [] player_scores_and_opponents = dict() for game in game_database.get_games_between_dates(period_dates[-1], period_dates[-2]): for _ in range(game.weight): # TODO: this can be done more efficiently for weight > 1 player_scores_and_opponents[game.home] = player_scores_and_opponents.get(game.home, []) + [(game.get_result(), game.out)] player_scores_and_opponents[game.out] = player_scores_and_opponents.get(game.out, []) + [(1 - game.get_result(), game.home)] for player in player_database: scores_and_opponents = player_scores_and_opponents.get(player.id, []) opponents = [player_database[opponent] for score, opponent in scores_and_opponents] scores = [score for score, opponent in scores_and_opponents] if len(opponents) == 0 and player.get_rating().deviation >= player.get_rating().default_rating.deviation: continue new_rating = self.update_player(player, opponents, scores) updated_ratings.append((player, new_rating)) for player, new_rating in updated_ratings: player.get_rating().update(new_rating[0], new_rating[1], new_rating[2]) def update_player(self, player : Player, opponents : List[Player], scores : List[float]) -> tuple: """ Updates the rating of a player based on the opponents and scores. Args: - player (Player): The player to update the rating for. - opponents (list): The list of opponents. - scores (list): The list of scores of the player against the opponents. Returns: - tuple: A tuple containing the updated rating, deviation, and volatility of the player. """ new_deviation = min(np.sqrt(player.get_rating().deviation ** 2 + self.C ** 2), player.get_rating().default_rating.deviation) rating_update = 0 player_rating = player.get_rating() for opponent, score in zip(opponents, scores): opponent_rating = opponent.get_rating() E = self.E(player_rating.rating, opponent_rating.rating, opponent_rating.deviation) g = self.g(opponent_rating.deviation) rating_update += g * (score - E) if len(opponents) > 0: d_2 = 1 / self.d_squared(player.get_rating().rating, opponents) else: d_2 = 0 denom = (1 / new_deviation ** 2 + d_2) update = self.q / denom * rating_update new_rating = player.get_rating().rating + update new_deviation = np.sqrt(1 / denom) return (new_rating, new_deviation, player.get_rating().default_rating.volatility) @property def q(self) -> float: return np.log(10) / self.default_change def d_squared(self, rating : float, opponents : List[Player]) -> float: """ Computes the squared denominator value used in the rating update formula. Args: - rating (float): The rating of the player. - opponents (list): The list of opponents. Returns: - float: The squared denominator value. """ expected_d = 0 for opponent in opponents: opponent_rating = opponent.get_rating() E = self.E(rating, opponent_rating.rating, opponent_rating.deviation) g = self.g(opponent_rating.deviation) expected_d += g ** 2 * E * (1 - E) denominator = (self.q) ** 2 * expected_d return 1 / denominator def g(self, deviation : float) -> float: """ Computes the g value used in the rating update formula. Args: - deviation (float): The deviation value. Returns: - float: The g value. """ return 1 / np.sqrt(1 + 3 * ((self.q) ** 2 * deviation ** 2) / (np.pi ** 2)) def E(self, rating : float, opponent_rating : float, opponent_deviation : float) -> float: """ Computes the expected score of a player against an opponent. Args: - rating (float): The rating of the player. - opponent_rating (float): The rating of the opponent. - opponent_deviation (float): The deviation of the opponent. Returns: - float: The expected score of the player against the opponent. """ exponent = -self.g(opponent_deviation) * (rating - opponent_rating) / self.default_change exponent = np.clip(exponent, -self.max_exp_value, self.max_exp_value) return 1 / (1 + 10 ** (exponent)) def convert_rating(self, rating : float, deviation : float, volatility : float, default_rating : DefaultRating) -> tuple: """ Converts a rating to the appropriate format. Args: - rating (float): The rating to be converted. - deviation (float): The deviation to be converted. - volatility (float): The volatility to be converted. - default_rating (DefaultRating): The default rating value. Returns: - tuple: A tuple containing the converted rating, deviation, and volatility. """ return (rating, deviation, volatility) def compute_expected_score(self, player : Player, games : List[Game], player_database : PlayerDatabase, date : datetime, next : bool = False) -> float: opponents = [game.home if game.home != player.id else game.out for game in games] opponents = [player_database[opponent] for opponent in opponents] ratings = [opponent.get_rating_at_date(date, next=next) for opponent in opponents] player_rating = player.get_rating_at_date(date, next=next) ratings = [self.convert_rating(rating.rating, rating.deviation, rating.volatility, rating.default_rating) for rating in ratings] converted_rating = self.convert_rating(player_rating.rating, player_rating.deviation, player_rating.volatility, player_rating.default_rating) expected_score = sum([game.weight * self.E(converted_rating[0], rating[0], rating[1]) for game, rating in zip(games, ratings)]) return expected_score def compute_expected_score_rating(self, player_rating: Rating, opponent_rating: Rating, is_home: bool) -> float: player_rating = self.convert_rating(player_rating.rating, player_rating.deviation, player_rating.volatility, player_rating.default_rating) opponent_rating = self.convert_rating(opponent_rating.rating, opponent_rating.deviation, opponent_rating.volatility, opponent_rating.default_rating) return self.E(player_rating[0], opponent_rating[0], opponent_rating[1])
Ancestors
Subclasses
Instance variables
prop q : float
-
Expand source code
@property def q(self) -> float: return np.log(10) / self.default_change
Methods
def E(self, rating: float, opponent_rating: float, opponent_deviation: float) ‑> float
-
Computes the expected score of a player against an opponent.
Args
- rating (float): The rating of the player.
- opponent_rating (float): The rating of the opponent.
- opponent_deviation (float): The deviation of the opponent.
Returns
- float: The expected score of the player against the opponent.
def convert_rating(self, rating: float, deviation: float, volatility: float, default_rating: DefaultRating) ‑> tuple
-
Converts a rating to the appropriate format.
Args
- rating (float): The rating to be converted.
- deviation (float): The deviation to be converted.
- volatility (float): The volatility to be converted.
- default_rating (DefaultRating): The default rating value.
Returns
- tuple: A tuple containing the converted rating, deviation, and volatility.
def d_squared(self, rating: float, opponents: List[Player]) ‑> float
-
Computes the squared denominator value used in the rating update formula.
Args
- rating (float): The rating of the player.
- opponents (list): The list of opponents.
Returns
- float: The squared denominator value.
def g(self, deviation: float) ‑> float
-
Computes the g value used in the rating update formula.
Args
- deviation (float): The deviation value.
Returns
- float: The g value.
def update_player(self, player: Player, opponents: List[Player], scores: List[float]) ‑> tuple
-
Updates the rating of a player based on the opponents and scores.
Args
- player (Player): The player to update the rating for.
- opponents (list): The list of opponents.
- scores (list): The list of scores of the player against the opponents.
Returns
- tuple: A tuple containing the updated rating, deviation, and volatility of the player.
Inherited members