TonyCardillo / PyElo

PyElo is a simple Python library for creating Elo ranking systems within your programs. Use it for chess, basketball, football, or any other head-to-head sport you can think of!
MIT License
0 stars 0 forks source link

Incorrect math with large elo discrepencies #2

Closed csga5000 closed 1 month ago

csga5000 commented 1 year ago

The code is not using Ea and Eb when adjusting MMR, it's always using Eb. This causes it to act as if both players were very unlikely to win when one player is higher rated for example leading to changes like +18 and -2 when it should have been like +2/-2.

Here's adjusted code:

        # Calculate new Elo for A
        if homeAdvA == 1:
            # You are expected to do better if home, and thus the difference between you is less
            expectedScoreA = 1.0 / \
                (1.0 + math.pow(10.0, (teamB.elo-teamA.elo -
                 eloSystem.homeAdvAmt)/eloSystem.RPA))
        elif homeAdvA == -1:
            # Your opponent is expected to do better if you are away, and thus the difference between you is greater
            expectedScoreA = 1.0 / \
                (1.0 + math.pow(10.0, (teamB.elo-teamA.elo +
                 eloSystem.homeAdvAmt)/eloSystem.RPA))
        else:
            # Neutral site, no bonuses to anyone
            expectedScoreA = 1.0 / \
                (1.0 + math.pow(10.0, (teamB.elo-teamA.elo)/eloSystem.RPA))

        # Calculate new Elo for B
        if homeAdvB == 1:
            # You are expected to do better if home, and thus the difference between you is less
            expectedScoreB = 1.0 / \
                (1.0 + math.pow(10.0, (teamA.elo-teamB.elo -
                 eloSystem.homeAdvAmt)/eloSystem.RPA))
        elif homeAdvB == -1:
            # Your opponent is expected to do better if you are away, and thus the difference between you is greater
            expectedScoreB = 1.0 / \
                (1.0 + math.pow(10.0, (teamA.elo-teamB.elo +
                 eloSystem.homeAdvAmt)/eloSystem.RPA))
        else:
            # Neutral site, no bonuses to anyone
            expectedScoreB = 1.0 / \
                (1.0 + math.pow(10.0, (teamA.elo-teamB.elo)/eloSystem.RPA))

        # Positive if you win, negative if you lose.
        # More positive if you were less likely to win (an upset)
        # More positive if you had a higher margin of victory (scoreDif)
        if mov > 0:
            teamA.elo = teamA.elo + eloSystem.K * \
                (win - expectedScoreA)*math.log(abs(scoreDif)+1)
            teamB.elo = teamB.elo + eloSystem.K * \
                ((1-win) - expectedScoreB)*math.log(abs(scoreDif)+1)
        else:
            teamA.elo = teamA.elo + eloSystem.K*(win - expectedScoreA)
            teamB.elo = teamB.elo + eloSystem.K*((1-win) - expectedScoreB)
TonyCardillo commented 1 month ago

Thanks! This should now be fixed with the most recent refactor.