Advanced Guide#
Warning
These features have not been tested against real world data to check for their efficacy. You should test the parameters against your own data to ensure they suit your needs.
Additive Dynamics Factor#
If sigma
gets too small, eventually the rating change volatility will decrease. To prevent this you can pass the parameter tau
to rate
. tau
should preferably be a small decimal of two significant digits.
Here are some visuals of how ordinals change with different tau
values:

You can combine tau
with another parameter prevent_sigma_increase
to ensure the win probability always remains congruent with the actual win rate.
Here is how this looks:

Time Decay#
You can represent the decay of a player’s skill over time by increasing sigma
by a little per match not played (or every time interval). First collect data on by how much sigma goes up or down by resetting sigma to it’s default value per interval. The value by which sigma
should change must be an average of the change of sigma
over all matches when sigma
is reset per interval.
Here is an example of how to do this:
from openskill import Rating, rate, predict_win
x, y = Rating(), Rating()
mu_precision = 1 + 0.0001 / 365
sigma_precision = 1 + 1 / 365
# Let player X win 66% of the games.
for match in range(10000):
if match % 3:
[[x], [y]] = rate([[x], [y]])
else:
[[y], [x]] = rate([[y], [x]])
# Decay Rating - Assume 1 Match Per Day
x.mu /= mu_precision
y.mu /= mu_precision
x.sigma *= sigma_precision
y.sigma *= sigma_precision
print("Before Large Decay: ")
print(f"Player X: mu={x.mu}, sigma={x.sigma}")
print(f"Player Y: mu={y.mu}, sigma={y.sigma}\n")
print("Predict Winner Before Decay:")
x_percent, y_percent = predict_win([[x], [y]])
print(f"X has a {x_percent * 100: 0.2f}% chance of winning over Y\n")
# Decay Rating - Assume 365 Days Passed
for match in range(365):
# Only player X's rating has decayed.
if (x.mu < 25 + 3 * 25 / 3) or (x.mu > 25 - 3 * 25 / 3):
x.mu /= mu_precision
if x.sigma < 25 / 3:
x.sigma *= sigma_precision
print("Player X's Rating After Decay: ")
print(f"Player X: mu={x.mu}, sigma={x.sigma}\n")
# One Match b/w X and Y
[[x], [y]] = rate([[x], [y]])
x.mu /= mu_precision
y.mu /= mu_precision
x.sigma *= sigma_precision
y.sigma *= sigma_precision
print("After Large Decay (1 Year): ")
print(f"Player X: mu={x.mu}, sigma={x.sigma}")
print(f"Player Y: mu={y.mu}, sigma={y.sigma}\n")
print("Predict Winner After Decay:")
x_percent, y_percent = predict_win([[x], [y]])
print(f"X has a {x_percent * 100: 0.2f}% chance of winning over Y")
This will produce the following output:
Before Large Decay:
Player X: mu=26.986479759996925, sigma=1.879261533806081
Player Y: mu=22.87672143851661, sigma=1.879261533806081
Predict Winner Before Decay:
X has a 70.27% chance of winning over Y
Player X's Rating After Decay:
Player X: mu=26.983781247317594, sigma=5.101382249884723
After Large Decay (1 Year):
Player X: mu=28.199913286886318, sigma=4.958583411621401
Player Y: mu=22.711677880164803, sigma=1.881565104224607
Predict Winner After Decay:
X has a 58.51% chance of winning over Y