Beispiel #1
0
def __apply_current_elo_ratings_for_fixture(fixture: pd.Series,
                                            data: pd.DataFrame,
                                            points: int) -> pd.Series:
    """
    Calculate and apply home and defence ratings for a Fixture
    """
    home_rows = data[data['homeTeam'] == fixture['homeTeam']]
    away_rows = data[data['awayTeam'] == fixture['awayTeam']]

    home = home_rows.iloc[-1, :]
    away = away_rows.iloc[-1, :]

    home_attack, _ = elo.calculate_attack_and_defence_ratings(
        points, home['homeAttackStrength'], home['awayDefenceStrength'],
        home['homeGoals'])

    _, home_defence = elo.calculate_attack_and_defence_ratings(
        points, home['awayAttackStrength'], home['homeDefenceStrength'],
        home['awayGoals'])

    away_attack, _ = elo.calculate_attack_and_defence_ratings(
        points, away['awayAttackStrength'], away['homeDefenceStrength'],
        away['awayGoals'])

    _, away_defence = elo.calculate_attack_and_defence_ratings(
        points, away['homeAttackStrength'], away['awayDefenceStrength'],
        away['homeGoals'])

    fixture['homeAttackStrength'] = home_attack
    fixture['homeDefenceStrength'] = home_defence
    fixture['awayAttackStrength'] = away_attack
    fixture['awayDefenceStrength'] = away_defence

    return fixture
Beispiel #2
0
def test_calculate_attack_and_defence_ratings_decreases_attack_and_increases_defence_ratings_when_goals_is_zero(
):
    [home, away] = elo.calculate_attack_and_defence_ratings(k_factor=10,
                                                            attack=1550.0,
                                                            defence=1410.25,
                                                            goals=0)

    assert home == 1543.09
    assert away == 1417.16
Beispiel #3
0
def test_calculate_attack_and_defence_ratings_accounts_for_unexpected_attack_goals_compared_to_strong_defence(
):
    [home, away] = elo.calculate_attack_and_defence_ratings(k_factor=10,
                                                            attack=1450.0,
                                                            defence=1610.25,
                                                            goals=3)

    assert home == 1471.47
    assert away == 1588.78
Beispiel #4
0
def test_calculate_attack_and_defence_ratings_increases_attack_and_decreases_defence_ratings_when_goals_is_greater_than_zero(
):
    [home, away] = elo.calculate_attack_and_defence_ratings(k_factor=10,
                                                            attack=1550.0,
                                                            defence=1410.25,
                                                            goals=2)

    assert home == 1556.18
    assert away == 1404.07
Beispiel #5
0
def __apply_historic_elo_ratings(df, historic_elos, soft_reset_factor,
                                 goal_points: int) -> pd.DataFrame:
    """
    Calculate rolling ELO ratings for teams based on results provided in data frame
    """
    # Initialise a dictionary with default elos for each team
    for team in df['homeTeam'].unique():
        if team not in historic_elos.keys():
            historic_elos[team] = 1500

    current_elos = historic_elos.copy()
    current_home_attack_elos = historic_elos.copy()
    current_home_defence_elos = historic_elos.copy()
    current_away_attack_elos = historic_elos.copy()
    current_away_defence_elos = historic_elos.copy()
    match_elos = {}
    match_home_strength = {}
    match_away_strength = {}

    last_season = 0

    # Loop over the rows in the DataFrame
    for index, row in df.iterrows():
        # Get the current year
        current_season = row['season']

        # If it is a new season, soft-reset elos
        if current_season != last_season:
            current_elos = __revert_elos_to_mean(current_elos,
                                                 soft_reset_factor)
            current_home_attack_elos = __revert_elos_to_mean(
                current_home_attack_elos, soft_reset_factor)
            current_home_defence_elos = __revert_elos_to_mean(
                current_home_defence_elos, soft_reset_factor)
            current_away_attack_elos = __revert_elos_to_mean(
                current_away_attack_elos, soft_reset_factor)
            current_away_defence_elos = __revert_elos_to_mean(
                current_away_defence_elos, soft_reset_factor)

        # Get the Game ID
        match_id = row['fixtureID']

        # Get the team and opposition
        home_team = row['homeTeam']
        away_team = row['awayTeam']

        # Get the team and opposition elo score
        home_team_elo = current_elos[home_team]
        away_team_elo = current_elos[away_team]
        home_attack_elo = current_home_attack_elos[home_team]
        home_defence_elo = current_home_defence_elos[home_team]
        away_attack_elo = current_away_attack_elos[away_team]
        away_defence_elo = current_away_defence_elos[away_team]

        # Add the elos and probabilities our elos dictionary and elo_probs dictionary based on the Match ID
        match_elos[match_id] = [home_team_elo, away_team_elo]
        match_home_strength[match_id] = [home_attack_elo, home_defence_elo]
        match_away_strength[match_id] = [away_attack_elo, away_defence_elo]

        # Calculate the new elos of each team
        new_home_team_elo, new_away_team_elo = elo.calculate_team_ratings(
            25, home_team_elo, away_team_elo, row['homeGoals'],
            row['awayGoals'])

        new_home_attack, new_away_defence = elo.calculate_attack_and_defence_ratings(
            goal_points, home_attack_elo, away_defence_elo, row['homeGoals'])

        new_away_attack, new_home_defence = elo.calculate_attack_and_defence_ratings(
            goal_points, away_attack_elo, home_defence_elo, row['awayGoals'])

        # Update elos in elo dictionary
        current_elos[home_team] = new_home_team_elo
        current_elos[away_team] = new_away_team_elo
        current_home_attack_elos[home_team] = new_home_attack
        current_away_attack_elos[away_team] = new_away_attack
        current_home_defence_elos[home_team] = new_home_defence
        current_away_defence_elos[away_team] = new_away_defence

        last_season = current_season

    updated = (df.assign(
        homeElo=lambda frame: frame.fixtureID.map(match_elos).str[0],
        awayElo=lambda frame: frame.fixtureID.map(match_elos).str[1],
        homeAttackStrength=lambda frame: frame.fixtureID.map(
            match_home_strength).str[0],
        homeDefenceStrength=lambda frame: frame.fixtureID.map(
            match_home_strength).str[1],
        awayAttackStrength=lambda frame: frame.fixtureID.map(
            match_away_strength).str[0],
        awayDefenceStrength=lambda frame: frame.fixtureID.map(
            match_away_strength).str[1],
    ))

    return updated