def fit_player_data(position,
                    season,
                    gameweek,
                    model=ConjugatePlayerModel(),
                    dbsession=session):
    """
    fit the data for a particular position (FWD, MID, DEF)
    """
    data = process_player_data(position, season, gameweek, dbsession)
    print("Fitting player model for", position, "...")
    model = fastcopy(model)
    fitted_model = model.fit(data)
    df = pd.DataFrame(fitted_model.get_probs())

    df["pos"] = position
    df = (df.rename(columns={
        "index": "player_id"
    }).sort_values("player_id").set_index("player_id"))
    return df
Exemple #2
0
def apply_strategy(strat,
                   tag,
                   baseline_dict=None,
                   num_iter=1,
                   update_func_and_args=None,
                   verbose=False):
    """
    apply a set of transfers over a number of gameweeks, and
    total up the score, taking into account points hits.
    strat is a tuple, with the first element being the
    dictionary {gw:ntransfers,...} and the second element being
    the total points hit.
    """
    sid = make_strategy_id(strat)
    starting_squad = get_starting_squad()
    if verbose:
        print("Trying strategy {}".format(strat))
    best_score = 0
    best_strategy_output = {}
    gameweeks = sorted(strat[0].keys())  # go through gameweeks in order
    if verbose:
        print(" --> doing strategy {}".format(sid))
    strategy_output = {
        "total_score": -1 * strat[1],  # points hit from this strategy
        "points_per_gw": {},
        "players_in": {},
        "players_out": {},
        "cards_played": {},
    }
    new_squad = fastcopy(starting_squad)
    ## If we use "free hit" card, we need to remember the team from the week before it
    squad_before_free_hit = None

    # determine if bench boost or triple captain used in this strategy
    bench_boost_gw = None
    triple_captain_gw = None
    for gw, n_transfers in strat[0].items():
        if n_transfers in ["B0", "B1"]:
            bench_boost_gw = gw
        elif n_transfers in ["T0", "T1"]:
            triple_captain_gw = gw

    for igw, gw in enumerate(gameweeks):
        ## how many gameweeks ahead should we look at for the purpose of estimating points?
        gw_range = gameweeks[igw:]  # range of gameweeks to end of window

        ## if we used a free hit in the previous gw, we will have stored the previous squad, so
        ## we go back to that one now.

        if squad_before_free_hit:
            new_squad = fastcopy(squad_before_free_hit)
            squad_before_free_hit = None

        ## process this gameweek
        if strat[0][gw] == 0:  # no transfers that gameweek
            rp, ap = [], []  ## lists of removed-players, added-players

        elif strat[0][gw] == 1:  # one transfer - choose optimum
            new_squad, rp, ap = make_optimum_transfer(
                new_squad,
                tag,
                gw_range,
                update_func_and_args=update_func_and_args,
                bench_boost_gw=bench_boost_gw,
                triple_captain_gw=triple_captain_gw,
            )
        elif strat[0][gw] == 2:
            ## two transfers - choose optimum
            new_squad, rp, ap = make_optimum_double_transfer(
                new_squad,
                tag,
                gw_range,
                update_func_and_args=update_func_and_args,
                bench_boost_gw=bench_boost_gw,
                triple_captain_gw=triple_captain_gw,
            )
        elif strat[0][gw] == "W":  ## wildcard - a whole new squad!
            rp = [p.player_id for p in new_squad.players]
            budget = get_team_value(new_squad)
            new_squad = make_new_squad(
                budget,
                num_iter,
                tag,
                gw_range,
                update_func_and_args=update_func_and_args,
                bench_boost_gw=bench_boost_gw,
                triple_captain_gw=triple_captain_gw,
            )

            ap = [p.player_id for p in new_squad.players]

        elif strat[0][gw] == "F":  ## free hit - a whole new squad!
            ## remember the starting team (so we can revert to it later)
            squad_before_free_hit = fastcopy(new_squad)
            ## now make a new squad for this gw, as is done for wildcard
            new_team = [p.player_id for p in new_squad.players]
            budget = get_team_value(new_team)
            new_squad = make_new_squad(
                budget,
                num_iter,
                tag,
                [gw],  # free hit should be optimised for this gameweek only
                update_func_and_args=update_func_and_args,
                bench_boost_gw=bench_boost_gw,
                triple_captain_gw=triple_captain_gw,
            )
            ap = [p.player_id for p in new_squad.players]

        elif strat[0][gw] in ["B0", "T0"
                              ]:  # bench boost/triple captain and no transfer
            rp, ap = [], []  ## lists of removed-players, added-players

        elif strat[0][gw] in [
                "B1",
                "T1",
        ]:  # bench boost/triple captain and one transfer
            new_squad, rp, ap = make_optimum_transfer(
                new_squad,
                tag,
                gw_range,
                update_func_and_args=update_func_and_args,
                bench_boost_gw=bench_boost_gw,
                triple_captain_gw=triple_captain_gw,
            )

        else:  # choose randomly
            new_squad, rp, ap = make_random_transfers(
                new_squad,
                tag,
                strat[0][gw],
                gw_range,
                num_iter=num_iter,
                update_func_and_args=update_func_and_args,
                bench_boost_gw=bench_boost_gw,
                triple_captain_gw=triple_captain_gw,
            )

        if gw == bench_boost_gw:
            score = new_squad.get_expected_points(gw, tag, bench_boost=True)
        elif gw == triple_captain_gw:
            score = new_squad.get_expected_points(gw, tag, triple_captain=True)
        else:
            score = new_squad.get_expected_points(gw, tag)

        ## if we're ever >5 points below the baseline, bail out!
        strategy_output["total_score"] += score
        if baseline_dict and baseline_dict[gw] - strategy_output[
                "total_score"] > 5:
            break
        strategy_output["points_per_gw"][gw] = score
        # record whether we're playing a chip this gameweek
        # only first character to remove number transfers in case of bench boost or
        # triple captain ("B" and "T", not "B0", "B1", "T0", "T1")
        strategy_output["cards_played"][gw] = (strat[0][gw][0] if isinstance(
            strat[0][gw], str) else None)
        strategy_output["players_in"][gw] = ap
        strategy_output["players_out"][gw] = rp
        ## end of loop over gameweeks
    if strategy_output["total_score"] > best_score:
        best_score = strategy_output["total_score"]
        best_strategy_output = strategy_output
    if verbose:
        print("Total score: {}".format(best_strategy_output["total_score"]))
    return best_strategy_output
Exemple #3
0
def make_optimum_double_transfer(
    squad,
    tag,
    gameweek_range=None,
    season=CURRENT_SEASON,
    update_func_and_args=None,
    verbose=False,
    bench_boost_gw=None,
    triple_captain_gw=None,
):
    """
    If we want to just make two transfers, it's not unfeasible to try all
    possibilities in turn.
    We will order the list of potential subs via the sum of expected points
    over a specified range of gameweeks.
    """
    if not gameweek_range:
        gameweek_range = [NEXT_GAMEWEEK]

    transfer_gw = min(gameweek_range)  # the week we're making the transfer
    best_score = 0.0
    best_pid_out, best_pid_in = 0, 0
    ordered_player_lists = {}
    for pos in ["GK", "DEF", "MID", "FWD"]:
        ordered_player_lists[pos] = get_predicted_points(
            gameweek=gameweek_range, position=pos, tag=tag)

    for i in range(len(squad.players) - 1):
        positions_needed = []
        pout_1 = squad.players[i]

        new_squad_remove_1 = fastcopy(squad)
        new_squad_remove_1.remove_player(pout_1.player_id,
                                         season=season,
                                         gameweek=transfer_gw)
        for j in range(i + 1, len(squad.players)):
            if update_func_and_args:
                ## call function to update progress bar.
                ## this was passed as a tuple (func, increment, pid)
                update_func_and_args[0](update_func_and_args[1],
                                        update_func_and_args[2])

            pout_2 = squad.players[j]
            new_squad_remove_2 = fastcopy(new_squad_remove_1)
            new_squad_remove_2.remove_player(pout_2.player_id,
                                             season=season,
                                             gameweek=transfer_gw)
            if verbose:
                print("Removing players {} {}".format(i, j))
            ## what positions do we need to fill?
            positions_needed = [pout_1.position, pout_2.position]

            # now loop over lists of players and add players back in
            for pin_1 in ordered_player_lists[positions_needed[0]]:
                if (pin_1[0].player_id == pout_1.player_id
                        or pin_1[0].player_id == pout_2.player_id):
                    continue  ## no point in adding same player back in
                new_squad_add_1 = fastcopy(new_squad_remove_2)
                added_1_ok = new_squad_add_1.add_player(pin_1[0],
                                                        season=season,
                                                        gameweek=transfer_gw)
                if not added_1_ok:
                    continue
                for pin_2 in ordered_player_lists[positions_needed[1]]:
                    new_squad_add_2 = fastcopy(new_squad_add_1)
                    if (pin_2[0] == pin_1[0]
                            or pin_2[0].player_id == pout_1.player_id
                            or pin_2[0].player_id == pout_2.player_id):
                        continue  ## no point in adding same player back in
                    added_2_ok = new_squad_add_2.add_player(
                        pin_2[0], season=season, gameweek=transfer_gw)
                    if added_2_ok:
                        # calculate the score
                        total_points = 0.0
                        for gw in gameweek_range:
                            if gw == bench_boost_gw:
                                total_points += new_squad_add_2.get_expected_points(
                                    gw, tag, bench_boost=True)
                            elif gw == triple_captain_gw:
                                total_points += new_squad_add_2.get_expected_points(
                                    gw, tag, triple_captain=True)
                            else:
                                total_points += new_squad_add_2.get_expected_points(
                                    gw, tag)
                        if total_points > best_score:
                            best_score = total_points
                            best_pid_out = [pout_1.player_id, pout_2.player_id]
                            best_pid_in = [
                                pin_1[0].player_id, pin_2[0].player_id
                            ]
                            best_squad = new_squad_add_2
                        break

    return best_squad, best_pid_out, best_pid_in
Exemple #4
0
def make_random_transfers(
    squad,
    tag,
    nsubs=1,
    gw_range=None,
    num_iter=1,
    update_func_and_args=None,
    season=CURRENT_SEASON,
    bench_boost_gw=None,
    triple_captain_gw=None,
):
    """
    choose nsubs random players to sub out, and then select players
    using a triangular PDF to preferentially select  the replacements with
    the best expected score to fill their place.
    Do this num_iter times and choose the best total score over gw_range gameweeks.
    """
    best_score = 0.0
    best_squad = None
    best_pid_out = []
    best_pid_in = []
    max_tries = 100
    for i in range(num_iter):
        if update_func_and_args:
            ## call function to update progress bar.
            ## this was passed as a tuple (func, increment, pid)
            update_func_and_args[0](update_func_and_args[1],
                                    update_func_and_args[2])

        new_squad = fastcopy(squad)

        if not gw_range:
            gw_range = [NEXT_GAMEWEEK]

        transfer_gw = min(gw_range)  # the week we're making the transfer
        players_to_remove = []  # this is the index within the squad
        removed_players = []  # this is the player_ids
        ## order the players in the squad by predicted_points - least-to-most
        player_list = []
        for p in squad.players:
            p.calc_predicted_points(tag)
            player_list.append(
                (p.player_id, p.predicted_points[tag][gw_range[0]]))
        player_list.sort(key=itemgetter(1), reverse=False)
        while len(players_to_remove) < nsubs:
            index = int(random.triangular(0, len(player_list), 0))
            if not index in players_to_remove:
                players_to_remove.append(index)

        positions_needed = []
        for p in players_to_remove:
            positions_needed.append(squad.players[p].position)
            removed_players.append(squad.players[p].player_id)
            new_squad.remove_player(removed_players[-1],
                                    season=season,
                                    gameweek=transfer_gw)
        budget = new_squad.budget
        predicted_points = {}
        for pos in set(positions_needed):
            predicted_points[pos] = get_predicted_points(position=pos,
                                                         gameweek=gw_range,
                                                         tag=tag)
        complete_squad = False
        added_players = []
        attempt = 0
        while not complete_squad:
            ## sample with a triangular PDF - preferentially select players near
            ## the start
            added_players = []
            for pos in positions_needed:
                index = int(random.triangular(0, len(predicted_points[pos]),
                                              0))
                pid_to_add = predicted_points[pos][index][0]
                added_ok = new_squad.add_player(pid_to_add,
                                                season=season,
                                                gameweek=transfer_gw)
                if added_ok:
                    added_players.append(pid_to_add)
            complete_squad = new_squad.is_complete()
            if not complete_squad:
                # try to avoid getting stuck in a loop
                attempt += 1
                if attempt > max_tries:
                    new_squad = fastcopy(squad)
                    break
                # take those players out again.
                for ap in added_players:
                    removed_ok = new_squad.remove_player(ap.player_id,
                                                         season=season,
                                                         gameweek=transfer_gw)
                    if not removed_ok:
                        print("Problem removing {}".format(ap.name))
                added_players = []

        ## calculate the score
        total_points = 0.0
        for gw in gw_range:
            if gw == bench_boost_gw:
                total_points += new_squad.get_expected_points(gw,
                                                              tag,
                                                              bench_boost=True)
            elif gw == triple_captain_gw:
                total_points += new_squad.get_expected_points(
                    gw, tag, triple_captain=True)
            else:
                total_points += new_squad.get_expected_points(gw, tag)
        if total_points > best_score:
            best_score = total_points
            best_pid_out = removed_players
            best_pid_in = [ap.player_id for ap in added_players]
            best_squad = new_squad
        ## end of loop over n_iter
    return best_squad, best_pid_out, best_pid_in
Exemple #5
0
def make_optimum_transfer(
    squad,
    tag,
    gameweek_range=None,
    season=CURRENT_SEASON,
    update_func_and_args=None,
    bench_boost_gw=None,
    triple_captain_gw=None,
):
    """
    If we want to just make one transfer, it's not unfeasible to try all
    possibilities in turn.


    We will order the list of potential transfers via the sum of
    expected points over a specified range of gameweeks.
    """
    if not gameweek_range:
        gameweek_range = [NEXT_GAMEWEEK]

    transfer_gw = min(gameweek_range)  # the week we're making the transfer
    best_score = 0.0
    best_pid_out, best_pid_in = 0, 0
    ordered_player_lists = {}
    for pos in ["GK", "DEF", "MID", "FWD"]:
        ordered_player_lists[pos] = get_predicted_points(
            gameweek=gameweek_range, position=pos, tag=tag)
    for p_out in squad.players:
        if update_func_and_args:
            ## call function to update progress bar.
            ## this was passed as a tuple (func, increment, pid)
            update_func_and_args[0](update_func_and_args[1],
                                    update_func_and_args[2])

        new_squad = fastcopy(squad)
        position = p_out.position
        new_squad.remove_player(p_out.player_id,
                                season=season,
                                gameweek=transfer_gw)
        for p_in in ordered_player_lists[position]:
            if p_in[0].player_id == p_out.player_id:
                continue  # no point in adding the same player back in
            added_ok = new_squad.add_player(p_in[0],
                                            season=season,
                                            gameweek=transfer_gw)
            if added_ok:
                break
        total_points = 0.0
        for gw in gameweek_range:
            if gw == bench_boost_gw:
                total_points += new_squad.get_expected_points(gw,
                                                              tag,
                                                              bench_boost=True)
            elif gw == triple_captain_gw:
                total_points += new_squad.get_expected_points(
                    gw, tag, triple_captain=True)
            else:
                total_points += new_squad.get_expected_points(gw, tag)
        if total_points > best_score:
            best_score = total_points
            best_pid_out = p_out.player_id
            best_pid_in = p_in[0].player_id
            best_squad = new_squad
    return best_squad, [best_pid_out], [best_pid_in]