Glicko-2 Rating System¶
Summary¶
The Glicko rating system was invented by Mark Glickman in 1995 as an improvement on the Elo rating system. Its principal innovation is the introduction of a "rating deviation" (RD) — a measure of a player's rating accuracy. A player's RD is one standard deviation of their true strength estimate.
Glicko-2 further improves on Glicko by introducing a rating volatility (σ, sigma) that measures the degree of expected fluctuation in a player's rating based on how erratic their performances are. A consistent player has low volatility; an unpredictable player who has extreme results has high volatility.
The RD is central to the system's value: after a game, the rating change is smaller when the player's RD is already low (rating is accurate) and when the opponent's RD is high (opponent's true rating is uncertain, so less information is gained). RD also increases over time during inactivity.
Glicko-2 is used by Chess.com, Lichess, Dota 2, Counter-Strike 2, Guild Wars 2, and other competitive games. It is in the public domain.
Key Concepts¶
- Rating Deviation (RD): Measures accuracy of rating. RD = 50 means the player's true strength is expected to be within ±50 points (1 SD). After a game, RD decreases; during inactivity, it increases.
- Rating volatility (σ): Only in Glicko-2. Measures consistency of player performance. Low σ = consistent; high σ = erratic. The algorithm uses iterative steps to find σ.
- Rating period: A batch of games occurring in the same time period, treated simultaneously for updates
- Scale: Glicko uses a different scale from Elo. The conversion is: r = (R - 1500) / 173.7178, RD' = RD / 173.7178
- Uncertainty increase over time: RD increases based on time elapsed: RD_new = min(RD_max, sqrt(RD_old² + c² × t)) where t = rating periods since last game
Glicko Algorithm (Step by Step)¶
Step 1: Determine new RD after inactivity:
$$RD' = \min(RD_{max}, \sqrt{RD_{old}^2 + c^2 \times t})$$
Where c is a constant based on expected growth in uncertainty (typical c ≈ 30–50), and RD_max ≈ 350 for new/uncertain players.
Step 2: Update rating after games:
$$r' = r + Q \times \sum_{i=1}^{m} g(RD_i) \times (s_i - E)$$
Where Q = 1/ln(10)/400, g(RD_i) = 1/sqrt(1 + 3×Q²×RD_i²/π²), E = 1/(1 + 10^(-Q×(r-r_i)/400))
Step 3: Update RD after games:
$$RD' = \sqrt{\frac{1}{\frac{1}{RD^2} + \frac{1}{Q^2 \times \sum g(RD_i)^2 \times E \times (1-E)}}}$$
Glicko-2 Key Formulas (Rating Update)¶
The Glicko-2 system converts ratings to a glicko-2 scale (μ, φ, σ) where:
- μ = (r - 1500) / 173.7178
- φ = RD / 173.7178
After games, new μ is computed and converted back. The volatility σ is found via iterative algorithm (regula falsi / Illinois algorithm) to satisfy an equation involving the observed results and expected scores.
Python Implementation¶
import math
class Glicko2:
def __init__(self, rating=1500, rd=350, volatility=0.06, tau=0.5):
self.rating = rating
self.rd = rd
self.volatility = volatility
self.tau = tau # constraints on volatility
def scale(self):
mu = (self.rating - 1500) / 173.7178
phi = self.rd / 173.7178
return mu, phi
def expected_score(self, mu, mu_j):
return 1 / (1 + math.pow(10, -1 * (mu - mu_j) / math.sqrt(2 * math.pow(30, 2))))
def update(self, opponents_ratings, opponents_rds, scores):
"""Update after a rating period with m games."""
mu, phi = self.scale()
# Compute g(phi_j) and E for each opponent
v_sum = 0
delta_sum = 0
for r_j, rd_j, s in zip(opponents_ratings, opponents_rds, scores):
mu_j, phi_j = (r_j - 1500) / 173.7178, rd_j / 173.7178
g = 1 / math.sqrt(1 + 3 * math.pow(phi_j, 2) / (math.pow(30, 2) * math.pow(math.pi, 2)))
E = 1 / (1 + math.pow(10, -1 * (mu - mu_j) / (math.sqrt(2) * 30)))
v_sum += math.pow(g, 2) * E * (1 - E)
delta_sum += g * (s - E)
v = 1 / v_sum
delta = v * delta_sum
# Update phi and rating
phi_star = math.sqrt(math.pow(phi, 2) + math.pow(self.volatility, 2))
phi_new = 1 / math.sqrt(1 / math.pow(phi_star, 2) + 1 / v)
mu_new = mu + math.pow(phi_new, 2) * delta_sum
# Convert back
self.rating = 173.7178 * mu_new + 1500
self.rd = 173.7178 * phi_new
return self.rating, self.rd
Notes¶
- Glicko-2 is particularly well-suited for sports with infrequent matches (like international football), where player/rating uncertainty grows meaningfully between games
- The volatility parameter σ is the key differentiator from Elo — it allows the model to capture players whose ratings change erratically vs. consistently
- Implementation note: the iterative algorithm for finding σ is the most complex part; consider using established libraries (python-glicko2) for production use
- For sports betting, Glicko-2's RD can be used to weight predictions — give less weight to recent results from players with high RD (uncertain)