def get_expected(pairs): p1_name = pairs[0] p2_name = pairs[1] if p2_name == 'Charlie Hoffman': p2_name = 'Charley Hoffman' p1_row = fpr.loc[pr['name'] == p1_name] print(p1_row) p2_row = fpr.loc[pr['name'] == p2_name] print(p2_row) p1_elo = p1_row['ielo'].values[0] p2_elo = p2_row['ielo'].values[0] elo_expected = Elo.x(p1_elo, p2_elo) impact = Glicko.reduce_impact(p2_row['gvar']) mu = (p1_row['glicko'].values[0] - MU) / ratio opp_mu = (p2_row['glicko'].values[0] - MU) / ratio glicko_expected = Glicko.get_expected(mu, opp_mu, impact) p1_asg = p1_row['asg'].values[0] p1_var = p1_row['pvar'].values[0] p2_asg = p2_row['asg'].values[0] p2_var = p2_row['pvar'].values[0] sg_x = asg_pred(p1_asg, p1_var, p2_asg, p2_var) p1_ldate = p1_row['last_date'].values[0] p1_ldate = datetime.datetime.strptime(str(p1_ldate), '%b %d %Y').date() current_date = datetime.datetime.strptime(str('Jul 4 2019'), '%b %d %Y').date() p1_dsl = current_date - p1_ldate p1_days = p1_dsl.days p2_ldate = p2_row['last_date'].values[0] p2_ldate = datetime.datetime.strptime(str(p2_ldate), '%b %d %Y').date() p2_dsl = current_date - p2_ldate p2_days = p2_dsl.days p1_rnds_played = p1_row['rnds_played'].values[0] p2_rnds_played = p2_row['rnds_played'].values[0] # row = [elo_expected, sg_x, glicko_expected, 2, p1_days,p1_rnds_played,p2_days,p2_rnds_played] # return row return elo_expected
DG = avg_dist - p.dist_from_last except: DG = 0 asg_vs_sg.append([ ASG, SG, DG, round, p.days_since, p.dist_from_last, p.bearing_from_last, p.pr4, p.rnds_played ]) for combo in combos: p1 = combo[0] p2 = combo[1] p1_score = getattr(p1, round) p2_score = getattr(p2, round) margin = abs(p2_score - p1_score) if p1_score <= p2_score: expected_result = Elo.x(p1.elo, p2.elo) p1_change, p2_change = Elo.get_ielo_delta( expected_result, margin, p1, p2, num_opps, round) # used for error tracking x = expected_result if p1_score == p2_score: result = 0.5 else: result = 1 else: # order of arguments matters expected_result = Elo.x(p2.elo, p1.elo) p2_change, p1_change = Elo.get_ielo_delta( expected_result, margin, p2, p1, num_opps, round) # used for error tracking x = 1 - expected_result
p.esg, p.gsg, p.asg, SG, round, p.rnds_played, p.days_since ]) # print(index,round,p.name,ASG,SG,p.asg,len(p.prev_sgs)) change_dict[p.name] = 0 # rchange_dict[p.name]=0 for combo in combos: p1 = combo[0] p2 = combo[1] p1_score = getattr(p1, round) p2_score = getattr(p2, round) margin = abs(p2_score - p1_score) # make predictions using each system elo_x = Elo.x(p1.elo, p2.elo) # relo_x = Elo.x(p1.relo,p2.relo) glicko_x = Glicko.x(p1, p2) if CALC_SG: # sg_x = asg_pred(p1.esg,p1.pvar,p2.esg,p2.pvar) sg_x = 0.5 if CALC_LOG5: l5_x = get_l5_x(p1.wl, p2.wl) if p1_score <= p2_score: p1_change, p2_change = Elo.get_ielo_delta( elo_x, margin, p1, p2, num_opps) # used for error tracking if p1_score == p2_score: # p1_rchange = Elo.get_delta(relo_x, True) # p2_rchange = -1*p1_rchange
def test_systems(): # load season data sdf = pd.read_csv('./data/SeasonResults.csv') # separate data into individual seasons seasons = list(sdf.Season.unique()) # set how long before glicko updates g_resolve = glicko_set['resolve_time'] # track error per season sea_error = [] wkbywk_err = None first_season = seasons[0] for season in tqdm(seasons): sea_df = sdf.loc[sdf.Season == season] # sort in order sea_df = sea_df.sort_values(by='DayNum') sea_df = sea_df[[ 'Season', 'DayNum', 'WTeam', 'WScore', 'LTeam', 'LScore' ]] # get list of teams in season wteams = list(sea_df.WTeam.unique()) lteams = list(sea_df.LTeam.unique()) teams = list(set((wteams + lteams))) load_preseason = False # use for preseason rankings if season > first_season: load_preseason = True else: prev_team_dir = None # create team directory to track everything team_dir = init_td(teams, load_preseason, prev_team_dir) # init classes elo = Elo() glicko = Glicko() # track error per week week_err = [] wk_l5err = wk_eloerr = wk_ieloerr = wk_gerr = wk_tserr = 0 wk_gp = 0 wk_thres = 7 wk_cnt = 0 # iterate games for index, row in sea_df.iterrows(): t1 = row['WTeam'] t2 = row['LTeam'] team1 = team_dir[t1] team2 = team_dir[t2] # set max number of games for testing # if (team1.gp > 11): # continue # if (team2.gp > 11): # continue # tracking error by week, so check if it's a new week day_num = row['DayNum'] if day_num > wk_thres: # it's a new week # add end date of next week wk_thres += 7 # ignore weeks that don't have games if wk_gp > 0: wk_l5err /= wk_gp wk_eloerr /= wk_gp wk_ieloerr /= wk_gp wk_gerr /= wk_gp wk_tserr /= wk_gp week_err.append([ season, wk_cnt, wk_l5err, wk_eloerr, wk_ieloerr, wk_gerr, wk_tserr ]) wk_cnt += 1 wk_l5err = wk_eloerr = wk_ieloerr = wk_gerr = wk_serr = 0 wk_gp = 0 # track games played this week wk_gp += 1 margin = row['WScore'] - row['LScore'] # get expected outcome for each system log5_expect = l5_x(team1.wl, team2.wl) elo_expect = elo.x(team1.elo, team2.elo) ielo_expect = elo.x(team1.ielo, team2.ielo) ts_expect = ts_win_prob([team1.tskill], [team2.tskill]) # special steps for glicko expectation mu, phi = glicko.scale_down(team1.glicko, team1.g_phi) mu2, phi2 = glicko.scale_down(team2.glicko, team2.g_phi) impact = glicko.reduce_impact(phi2) glicko_expect = glicko.get_expected(mu, mu2, impact) # update error if log5_expect == 0: log5_expect += .001 expects = [ log5_expect, elo_expect, ielo_expect, glicko_expect, ts_expect ] t1_errors = calc_error(expects, 1) t2_errors = t1_errors team1.update_errors(t1_errors) team2.update_errors(t2_errors) # update week error wk_l5err += t1_errors[0] wk_eloerr += t1_errors[1] wk_ieloerr += t1_errors[2] wk_gerr += t1_errors[3] wk_tserr += t1_errors[4] ## update ratings ## # elo elo_delta = elo.get_delta(elo_expect) t1_ielo_delta, t2_ielo_delta = elo.get_ielo_delta( ielo_expect, margin, team1, team2) team1.update_rating("elo", elo_delta) team1.update_rating("ielo", t1_ielo_delta) team2.update_rating("elo", -elo_delta) team2.update_rating("ielo", t2_ielo_delta) team1.update_ts(team2.tskill, "won") team2.update_ts(team1.tskill, "lost") # log5 team1.add_win() team2.add_loss() # glicko (second arg is win or loss) team1.add_glicko_opp(team2, 1) team2.add_glicko_opp(team1, 0) # check if time to resolve if team1.gp % g_resolve == 0: team1 = glicko.update(team1) if team2.gp % g_resolve == 0: team2 = glicko.update(team2) team_dir[t1] = team1 team_dir[t2] = team2 # add week_err df to season trackers week_err = pd.DataFrame( week_err, columns=['Season', 'Week', 'Log5', 'Elo', 'IElo', 'Glicko', 'TS']) if wkbywk_err is None: wkbywk_err = week_err else: wkbywk_err = pd.concat([wkbywk_err, week_err]) # find total error in season sea_gp = 0 sea_l5err = 0 sea_eloerr = 0 sea_ieloerr = 0 sea_gerr = 0 sea_tserr = 0 for team in team_dir.values(): sea_gp += team.gp sea_l5err += team.l5err sea_eloerr += team.eloerr sea_ieloerr += team.ieloerr sea_gerr += team.glickoerr sea_tserr += team.tserr sea_l5err /= sea_gp sea_eloerr /= sea_gp sea_ieloerr /= sea_gp sea_gerr /= sea_gp sea_tserr /= sea_gp sea_error.append( [season, sea_l5err, sea_eloerr, sea_ieloerr, sea_gerr, sea_tserr]) # store rankings for preseason rankings next season prev_team_dir = team_dir final_table = pd.DataFrame( sea_error, columns=['Season', 'Log5', 'Elo', 'IElo', 'Glicko', 'TS']) print(final_table) print(final_table.mean()) wkbywk = pd.DataFrame( wkbywk_err, columns=['Season', 'Week', 'Log5', 'Elo', 'IElo', 'Glicko', 'TS']) wkbywk = wkbywk.drop(columns=['TS']) wk_avg = wkbywk.groupby('Week').mean() def plot_weeks(wk_avg): import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(15, 7)) plt.plot(wk_avg.index.values, wk_avg.Log5, '-k', label='Log5 Baseline') plt.plot(wk_avg.index.values, wk_avg.Elo, '-c', label='Elo') plt.plot(wk_avg.index.values, wk_avg.IElo, '-b', label='Improved Elo') plt.plot(wk_avg.index.values, wk_avg.Glicko, '-r', label='Glicko') plt.xlabel("Week of Season") plt.ylabel("Cross Entropy Error") xint = range(0, math.ceil(17) + 1) plt.xticks(xint) plt.legend(loc='upper left') plt.show() return plot_weeks(wk_avg) return