def combine_player_info(player_id, dbsession=DBSESSION): """ Get player's name, club, recent scores, upcoming fixtures, and upcoming predictions if available """ info_dict = {"player_id": player_id} p = get_player(player_id, dbsession=dbsession) info_dict["player_name"] = p.name team = p.team(CURRENT_SEASON, NEXT_GAMEWEEK) info_dict["team"] = team # get recent scores for the player rs = get_recent_scores_for_player(p, dbsession=dbsession) recent_scores = [{"gameweek": k, "score": v} for k, v in rs.items()] info_dict["recent_scores"] = recent_scores # get upcoming fixtures fixtures = get_fixtures_for_player(p, dbsession=dbsession)[:3] info_dict["fixtures"] = [] for f in fixtures: home_or_away = "home" if f.home_team == team else "away" opponent = f.away_team if home_or_away == "home" else f.home_team info_dict["fixtures"].append({ "gameweek": f.gameweek, "opponent": opponent, "home_or_away": home_or_away }) try: tag = get_latest_prediction_tag(dbsession=dbsession) predicted_points = get_predicted_points_for_player(p, tag, dbsession=dbsession) info_dict["predictions"] = predicted_points except (RuntimeError): pass return info_dict
def best_transfer_suggestions(n_transfer, session_id, dbsession=DBSESSION): """ Use our predicted playerscores to suggest the best transfers. """ n_transfer = int(n_transfer) if not n_transfer in range(1,3): raise RuntimeError("Need to choose 1 or 2 transfers") if not validate_session_squad(session_id, dbsession): raise RuntimeError("Cannot suggest transfer without complete squad") budget = get_session_budget(session_id, dbsession) players = [p["id"] for p in get_session_players(session_id, dbsession)] t = Team(budget) for p in players: added_ok = t.add_player(p) if not added_ok: raise RuntimeError("Cannot add player {}".format(p)) pred_tag = get_latest_prediction_tag() gw=get_next_gameweek(CURRENT_SEASON, dbsession) if n_transfer == 1: new_team, pid_out, pid_in = make_optimum_transfer(t, pred_tag) elif n_transfer == 2: new_team, pid_out, pid_in = make_optimum_double_transfer(t, pred_tag) return { "transfers_out": pid_out, "transfers_in": pid_in }
def get_session_predictions(session_id, dbsession=DBSESSION): """ Query the fixture and predictedscore tables for all players in our session squad """ pids = [p["id"] for p in get_session_players(session_id, dbsession)] pred_tag = get_latest_prediction_tag() gw = NEXT_GAMEWEEK return { pid: get_session_prediction(pid, session_id, gw, pred_tag, dbsession) for pid in pids }
def get_session_predictions(session_id, dbsession=DBSESSION): """ Query the fixture and predictedscore tables for all players in our session squad """ pids = [p["id"] for p in get_session_players(session_id, dbsession)] pred_tag = get_latest_prediction_tag() gw = get_next_gameweek(CURRENT_SEASON, dbsession) pred_scores = {} for pid in players: pred_scores[pid] = get_session_prediction(pid, session_id, gw, pred_tag, dbsession) return pred_scores
def print_team_for_next_gw(strat): """ Display the team (inc. subs and captain) for the next gameweek """ t = get_starting_squad() gameweeks_as_str = strat["points_per_gw"].keys() gameweeks_as_int = sorted([int(gw) for gw in gameweeks_as_str]) next_gw = gameweeks_as_int[0] for pidout in strat["players_out"][str(next_gw)]: t.remove_player(pidout, gameweek=next_gw) for pidin in strat["players_in"][str(next_gw)]: t.add_player(pidin, gameweek=next_gw) tag = get_latest_prediction_tag() expected_points = t.get_expected_points(next_gw, tag) print(t)
def get_session_prediction(player_id, session_id, gw=None, pred_tag=None, dbsession=DBSESSION): """ Query the fixture and predictedscore tables for a specified player """ if not gw: gw = get_next_gameweek(CURRENT_SEASON, dbsession) if not pred_tag: pred_tag = get_latest_prediction_tag() return_dict = { "predicted_score": get_predicted_points_for_player(pid, pred_tag, CURRENT_SEASON, dbsession)[gw], "fixture": get_next_fixture_for_player(pid,CURRENT_SEASON,dbsession) } return return_dict
def set_lineup(fpl_team_id=None): """ Retrieve the latest lineup and apply the latest prediction to it. Note that this assumes that the prediction has been ran recently. """ print("fpl_team_id is {}".format(fpl_team_id)) fetcher = FPLDataFetcher(fpl_team_id) print("Got fetcher {}".format(fetcher.FPL_TEAM_ID)) picks = get_lineup(fetcher) print("Got picks {}".format(picks)) squad = get_lineup_from_payload(picks) print("got squad: {}".format(squad)) squad.optimize_lineup(NEXT_GAMEWEEK, get_latest_prediction_tag()) if check_proceed(squad): payload = build_lineup_payload(squad) post_lineup(payload, fetcher)
def run_optimize_squad(num_thread, weeks_ahead, fpl_team_id, dbsession, chips_played): """ Build the initial squad """ gw_range = list(range(NEXT_GAMEWEEK, NEXT_GAMEWEEK + weeks_ahead)) season = CURRENT_SEASON tag = get_latest_prediction_tag(season, tag_prefix="", dbsession=dbsession) with warnings.catch_warnings(): warnings.simplefilter("ignore", TqdmWarning) run_optimization( gameweeks=gw_range, tag=tag, season=season, fpl_team_id=fpl_team_id, num_thread=num_thread, chip_gameweeks=chips_played, ) return True
def run_make_squad(weeks_ahead, fpl_team_id, dbsession): """ Build the initial squad """ gw_range = list(range(NEXT_GAMEWEEK, NEXT_GAMEWEEK + weeks_ahead)) season = CURRENT_SEASON tag = get_latest_prediction_tag(season, tag_prefix="", dbsession=dbsession) best_squad = make_new_squad_pygmo( gw_range, tag, ) best_squad.get_expected_points(NEXT_GAMEWEEK, tag) print(best_squad) fill_initial_suggestion_table(best_squad, fpl_team_id, tag, season, NEXT_GAMEWEEK, dbsession=dbsession) return True
def main(): parser = argparse.ArgumentParser(description="Make a squad from scratch") # General parameters parser.add_argument( "--budget", help="budget, in 0.1 millions", type=int, default=1000 ) parser.add_argument("--season", help="season, in format e.g. 1819") parser.add_argument("--gw_start", help="gameweek to start from", type=int) parser.add_argument( "--num_gw", help="how many gameweeks to consider", type=int, default=3 ) parser.add_argument( "--algorithm", help="Which optimization algorithm to use - 'normal' or 'genetic'", type=str, default="normal", ) # parameters for "normal" optimization parser.add_argument( "--num_iterations", help="number of iterations (normal algorithm only)", type=int, default=10, ) # parameters for "pygmo" optimization parser.add_argument( "--num_generations", help="number of generations (genetic only)", type=int, default=100, ) parser.add_argument( "--population_size", help="number of candidate solutions per generation (genetic only)", type=int, default=100, ) parser.add_argument( "--no_subs", help="Don't include points contribution from substitutes (genetic only)", action="store_true", ) parser.add_argument( "--include_zero", help="Include players with zero predicted points (genetic only)", action="store_true", ) parser.add_argument( "--gw_weight_type", help="'constant' to treat all gameweeks equally, or 'linear' to reduce weight of gameweeks with time (genetic only)", type=str, default="linear", ) args = parser.parse_args() if args.season: season = args.season else: season = get_current_season() budget = args.budget if args.gw_start: gw_start = args.gw_start else: gw_start = NEXT_GAMEWEEK gw_range = list(range(gw_start, min(38, gw_start + args.num_gw))) tag = get_latest_prediction_tag(season) if args.algorithm == "normal": from airsenal.framework.optimization_utils import make_new_squad num_iterations = args.num_iterations best_squad = make_new_squad(args.budget, num_iterations, tag, gw_range, season) elif args.algorithm == "genetic": from airsenal.framework.optimization_pygmo import make_new_squad num_generations = args.num_generations population_size = args.population_size remove_zero = not args.include_zero gw_weight_type = args.gw_weight_type uda = pg.sga(gen=num_generations) if args.no_subs: sub_weights = {"GK": 0, "Outfield": (0, 0, 0)} else: sub_weights = {"GK": 0.01, "Outfield": (0.4, 0.1, 0.02)} best_squad = make_new_squad( gw_range, tag, budget=budget, season=season, remove_zero=remove_zero, sub_weights=sub_weights, uda=uda, population_size=population_size, gw_weight_type=gw_weight_type, ) else: raise ValueError("'algorithm' must be 'normal' or 'genetic'") points = best_squad.get_expected_points(gw_start, tag) print("---------------------") print("Best expected points for gameweek {}: {}".format(gw_start, points)) print("---------------------") print(best_squad)
def main(): """ The main function, to be used as entrypoint. """ parser = argparse.ArgumentParser( description="Try some different transfer strategies") parser.add_argument("--weeks_ahead", help="how many weeks ahead", type=int) parser.add_argument("--gw_start", help="first gameweek to consider", type=int) parser.add_argument("--gw_end", help="last gameweek to consider", type=int) parser.add_argument("--tag", help="specify a string identifying prediction set") parser.add_argument( "--wildcard_week", help="play wildcard in the specified week. Choose 0 for 'any week'.", type=int, default=-1, ) parser.add_argument( "--free_hit_week", help="play free hit in the specified week. Choose 0 for 'any week'.", type=int, default=-1, ) parser.add_argument( "--triple_captain_week", help= "play triple captain in the specified week. Choose 0 for 'any week'.", type=int, default=-1, ) parser.add_argument( "--bench_boost_week", help="play bench_boost in the specified week. Choose 0 for 'any week'.", type=int, default=-1, ) parser.add_argument("--num_free_transfers", help="how many free transfers do we have", type=int) parser.add_argument( "--max_hit", help="maximum number of points to spend on additional transfers", type=int, default=8, ) parser.add_argument( "--allow_unused", help="if set, include strategies that waste free transfers", action="store_true", ) parser.add_argument( "--num_iterations", help="how many iterations to use for Wildcard/Free Hit optimization", type=int, default=100, ) parser.add_argument("--num_thread", help="how many threads to use", type=int, default=4) parser.add_argument( "--season", help="what season, in format e.g. '2021'", type=str, default=CURRENT_SEASON, ) parser.add_argument( "--profile", help="For developers: Profile strategy execution time", action="store_true", ) parser.add_argument( "--fpl_team_id", help="specify fpl team id", type=int, required=False, ) args = parser.parse_args() fpl_team_id = args.fpl_team_id or None sanity_check_args(args) season = args.season # default weeks ahead is not specified (or gw_end is not specified) is three if args.weeks_ahead: gameweeks = get_gameweeks_array(args.weeks_ahead) elif args.gw_start: if args.gw_end: gameweeks = list(range(args.gw_start, args.gw_end)) else: gameweeks = list(range(args.gw_start, args.gw_start + 3)) else: gameweeks = list(range(get_next_gameweek(), get_next_gameweek() + 3)) num_iterations = args.num_iterations if args.num_free_transfers: num_free_transfers = args.num_free_transfers else: num_free_transfers = None # will work it out in run_optimization tag = args.tag or get_latest_prediction_tag(season=season) max_total_hit = args.max_hit allow_unused_transfers = args.allow_unused num_thread = args.num_thread profile = args.profile or False chip_gameweeks = { "wildcard": args.wildcard_week, "free_hit": args.free_hit_week, "triple_captain": args.triple_captain_week, "bench_boost": args.bench_boost_week, } if not check_tag_valid(tag, gameweeks, season=season): print( "ERROR: Database does not contain predictions", "for all the specified optimsation gameweeks.\n", "Please run 'airsenal_run_prediction' first with the", "same input gameweeks and season you specified here.", ) sys.exit(1) set_multiprocessing_start_method(num_thread) with warnings.catch_warnings(): warnings.simplefilter("ignore", TqdmWarning) run_optimization( gameweeks, tag, season, fpl_team_id, chip_gameweeks, num_free_transfers, max_total_hit, allow_unused_transfers, 2, num_iterations, num_thread, profile, )
from airsenal.framework.squad import TOTAL_PER_POSITION from airsenal.framework.utils import ( NEXT_GAMEWEEK, CURRENT_SEASON, get_latest_prediction_tag, ) # ------------------------- # INPUTS # ------------------------- # Gameweek range and budget gw_start = NEXT_GAMEWEEK num_gw = 3 season = CURRENT_SEASON tag = get_latest_prediction_tag() budget = 1000 # Gameweek weightings - either 'constant' to treat all gameweeks equally, or 'linear' # to reduce weight by 1/15 for each subsequent gameweek. gw_weight_type = "linear" # Weighting given to substitutes (GK, and 1st, 2nd, 3rd outfield sub). # 1 means points scored by subs treated as important as points scored by the first XI # 0 means points scored by subs not considered in optimisation sub_weights = {"GK": 0.01, "Outfield": (0.4, 0.1, 0.02)} # Can choose not to optimize full squad by changing the number of players per position. # In that case, to create valid squads during the optimization, the empty slots are # filled with dummy players. Each dummy player has a cost of 'dummy_sub_cost'. players_per_position = TOTAL_PER_POSITION
def main(): parser = argparse.ArgumentParser( description="Try some different transfer strategies") parser.add_argument("--weeks_ahead", help="how many weeks ahead", type=int, default=3) parser.add_argument("--tag", help="specify a string identifying prediction set") parser.add_argument("--num_iterations", help="how many trials to run", type=int, default=100) parser.add_argument( "--allow_wildcard", help="include possibility of wildcarding in one of the weeks", action="store_true", ) parser.add_argument( "--allow_free_hit", help="include possibility of playing free hit in one of the weeks", action="store_true", ) parser.add_argument( "--allow_bench_boost", help="include possibility of playing bench boost in one of the weeks", action="store_true", ) parser.add_argument( "--allow_triple_captain", help= "include possibility of playing triple captain in one of the weeks", action="store_true", ) parser.add_argument( "--no_unused_transfers", help="don't consider strategies that waste free transfers", action="store_true", ) parser.add_argument( "--max_points_hit", help="how many points are we prepared to lose on transfers", type=int, default=4, ) parser.add_argument( "--num_free_transfers", help="how many free transfers do we have", type=int, default=1, ) parser.add_argument( "--bank", help="how much money do we have in the bank (multiplied by 10)?", type=int, default=0, ) parser.add_argument("--num_thread", help="how many threads to use", type=int, default=4) parser.add_argument( "--season", help="what season, in format e.g. '1819'", type=int, default=CURRENT_SEASON, ) parser.add_argument( "--profile", help="For developers: Profile strategy execution time", action="store_true", ) if NEXT_GAMEWEEK == 1: print(("This function suggests transfers to make from " "an existing squad and can't be used before " "the season has started.\n" "Use 'airsenal_make_squad' to generate a " "starting squad instead.")) return args = parser.parse_args() season = args.season num_weeks_ahead = args.weeks_ahead num_iterations = args.num_iterations allow_wildcard = args.allow_wildcard allow_free_hit = args.allow_free_hit allow_bench_boost = args.allow_bench_boost allow_triple_captain = args.allow_triple_captain allow_unused_transfers = not args.no_unused_transfers num_free_transfers = args.num_free_transfers budget = args.bank max_points_hit = args.max_points_hit if args.tag: tag = args.tag else: # get most recent set of predictions from DB table tag = get_latest_prediction_tag() # create the output directory for temporary json files # giving the points prediction for each strategy os.makedirs(OUTPUT_DIR, exist_ok=True) if len(os.listdir(OUTPUT_DIR)) > 0: os.system("rm " + OUTPUT_DIR + "/*") # first get a baseline prediction baseline_score, baseline_dict = get_baseline_prediction( num_weeks_ahead, tag) # create a queue that we will add strategies to, and some processes to take # things off it squeue = Queue() procs = [] # create one progress bar for each thread progress_bars = [] for i in range(args.num_thread): progress_bars.append(tqdm(total=100)) # generate the list of transfer strategies strategies = generate_transfer_strategies( num_weeks_ahead, free_transfers=num_free_transfers, max_total_hit=max_points_hit, allow_wildcard=allow_wildcard, allow_free_hit=allow_free_hit, allow_bench_boost=allow_bench_boost, allow_triple_captain=allow_triple_captain, allow_unused_transfers=allow_unused_transfers, ) # define overall progress bar total_progress = tqdm(total=len(strategies), desc="Total progress") # functions to be passed to subprocess to update or reset progress bars def reset_progress(index, strategy_string): if strategy_string == "DONE": progress_bars[index].close() else: progress_bars[index].n = 0 progress_bars[index].desc = "strategy: " + strategy_string progress_bars[index].refresh() def update_progress(increment=1, index=None): if index is None: # outer progress bar nfiles = len(os.listdir(OUTPUT_DIR)) total_progress.n = nfiles total_progress.refresh() if nfiles == len(strategies): total_progress.close() for pb in progress_bars: pb.close() else: progress_bars[index].update(increment) progress_bars[index].refresh() for i in range(args.num_thread): processor = Process( target=process_strat, args=( squeue, i, num_iterations, tag, baseline_dict, update_progress, reset_progress, budget, args.profile, ), ) processor.daemon = True processor.start() procs.append(processor) # add the strategies to the queue for strat in strategies: squeue.put(strat) for i in range(args.num_thread): squeue.put("DONE") # now rejoin the main thread for i, p in enumerate(procs): progress_bars[i].close() progress_bars[i] = None p.join() # find the best from all the strategies tried best_strategy = find_best_strat_from_json(tag) fill_suggestion_table(baseline_score, best_strategy, season) for i in range(len(procs)): print("\n") print("\n====================================\n") print("Baseline score: {}".format(baseline_score)) print("Best score: {}".format(best_strategy["total_score"])) print_strat(best_strategy) print_team_for_next_gw(best_strategy)
def main(): parser = argparse.ArgumentParser(description="Make a squad from scratch") # General parameters parser.add_argument( "--budget", help="budget, in 0.1 millions", type=int, default=1000 ) parser.add_argument("--season", help="season, in format e.g. 1819") parser.add_argument("--gw_start", help="gameweek to start from", type=int) parser.add_argument( "--num_gw", help="how many gameweeks to consider", type=int, default=3 ) parser.add_argument( "--algorithm", help="Which optimization algorithm to use - 'normal' or 'genetic'", type=str, default="genetic", ) # parameters for "normal" optimization parser.add_argument( "--num_iterations", help="number of iterations (normal algorithm only)", type=int, default=10, ) # parameters for "pygmo" optimization parser.add_argument( "--num_generations", help="number of generations (genetic only)", type=int, default=100, ) parser.add_argument( "--population_size", help="number of candidate solutions per generation (genetic only)", type=int, default=100, ) parser.add_argument( "--no_subs", help="Don't include points contribution from substitutes (genetic only)", action="store_true", ) parser.add_argument( "--include_zero", help="Include players with zero predicted points (genetic only)", action="store_true", ) parser.add_argument( "--verbose", help="Print details on optimsation progress", action="store_true", ) parser.add_argument( "--fpl_team_id", help="ID for your FPL team", type=int, ) args = parser.parse_args() season = args.season or get_current_season() budget = args.budget gw_start = args.gw_start or NEXT_GAMEWEEK gw_range = list(range(gw_start, min(38, gw_start + args.num_gw))) tag = get_latest_prediction_tag(season) if not check_tag_valid(tag, gw_range, season=season): print( "ERROR: Database does not contain predictions", "for all the specified optimsation gameweeks.\n", "Please run 'airsenal_run_prediction' first with the", "same input gameweeks and season you specified here.", ) sys.exit(1) algorithm = args.algorithm num_iterations = args.num_iterations num_generations = args.num_generations population_size = args.population_size remove_zero = not args.include_zero verbose = args.verbose if args.no_subs: sub_weights = {"GK": 0, "Outfield": (0, 0, 0)} else: sub_weights = {"GK": 0.01, "Outfield": (0.4, 0.1, 0.02)} if algorithm == "genetic": try: import pygmo as pg uda = pg.sga(gen=num_generations) except ModuleNotFoundError as e: print(e) print("Defaulting to algorithm=normal instead") algorithm = "normal" uda = None else: uda = None best_squad = make_new_squad( gw_range, tag, budget=budget, season=season, algorithm=algorithm, remove_zero=remove_zero, sub_weights=sub_weights, uda=uda, population_size=population_size, num_iterations=num_iterations, verbose=verbose, ) if best_squad is None: raise RuntimeError( "best_squad is None: make_new_squad failed to generate a valid team or " "something went wrong with the squad expected points calculation." ) points = best_squad.get_expected_points(gw_start, tag) print("---------------------") print("Best expected points for gameweek {}: {}".format(gw_start, points)) print("---------------------") print(best_squad) fpl_team_id = args.fpl_team_id or fetcher.FPL_TEAM_ID fill_initial_suggestion_table( best_squad, fpl_team_id, tag, season=season, gameweek=gw_start, )
def main(): """ The main function, to be used as entrypoint. """ parser = argparse.ArgumentParser( description="Try some different transfer strategies") parser.add_argument("--weeks_ahead", help="how many weeks ahead", type=int) parser.add_argument("--gw_start", help="first gameweek to consider", type=int) parser.add_argument("--gw_end", help="last gameweek to consider", type=int) parser.add_argument("--tag", help="specify a string identifying prediction set") parser.add_argument( "--allow_wildcard", help="include possibility of wildcarding in one of the weeks", action="store_true", ) parser.add_argument( "--allow_free_hit", help="include possibility of playing free hit in one of the weeks", action="store_true", ) parser.add_argument( "--allow_triple_captain", help= "include possibility of playing triple captain in one of the weeks", action="store_true", ) parser.add_argument( "--allow_bench_boost", help="include possibility of playing bench boost in one of the weeks", action="store_true", ) parser.add_argument("--num_free_transfers", help="how many free transfers do we have", type=int) parser.add_argument( "--num_iterations", help="how many iterations to use for Wildcard/Free Hit optimization", type=int, default=100, ) parser.add_argument("--num_thread", help="how many threads to use", type=int, default=4) parser.add_argument( "--season", help="what season, in format e.g. '2021'", type=str, default=CURRENT_SEASON, ) parser.add_argument( "--profile", help="For developers: Profile strategy execution time", action="store_true", ) args = parser.parse_args() args_ok = sanity_check_args(args) season = args.season if args.weeks_ahead: gameweeks = list( range(get_next_gameweek(), get_next_gameweek() + args.weeks_ahead)) else: gameweeks = list(range(args.gw_start, args.gw_end)) num_iterations = args.num_iterations if args.allow_wildcard: wildcard = True else: wildcard = False if args.allow_free_hit: free_hit = True else: free_hit = False if args.allow_triple_captain: triple_captain = True else: triple_captain = False if args.allow_bench_boost: bench_boost = True else: bench_boost = False if args.num_free_transfers: num_free_transfers = args.num_free_transfers else: num_free_transfers = None # will work it out in run_optimization if args.tag: tag = args.tag else: ## get most recent set of predictions from DB table tag = get_latest_prediction_tag() num_thread = args.num_thread profile = args.profile if args.profile else False run_optimization( gameweeks, tag, season, wildcard, free_hit, triple_captain, bench_boost, num_free_transfers, num_iterations, num_thread, )