예제 #1
0
 def _build_lineup(
     self,
     players: List[Player],
     context: OptimizationContext,
     unswappable_players: Optional[List[LineupPlayer]] = None,
 ) -> Lineup:
     lineup = []
     positions = self._settings.positions[:]
     if not positions:
         for player in sorted(players, key=lambda p: p.positions[0]):
             lineup.append(
                 LineupPlayer(
                     player,
                     player.positions[0],
                     used_fppg=context.players_used_fppg.get(player)))
         return Lineup(lineup, self._settings.lineup_printer)
     if unswappable_players:
         players = [
             player for player in players
             if player not in unswappable_players
         ]
         positions = get_remaining_positions(positions, unswappable_players)
         lineup.extend(unswappable_players)
     players_with_positions = link_players_with_positions(
         players, positions)
     for player, position in players_with_positions.items():
         lineup.append(
             LineupPlayer(player,
                          position.name,
                          used_fppg=context.players_used_fppg.get(player)))
     positions_order = [pos.name for pos in self._settings.positions]
     lineup.sort(key=lambda p: positions_order.index(p.lineup_position))
     return Lineup(lineup, self._settings.lineup_printer)
예제 #2
0
 def import_lineups(self, players):
     with open(self.filename, 'r') as csv_file:
         lines = csv.reader(csv_file)
         try:
             header = next(lines)
             start_column = 4  # First 4 columns has info about tournament
             end_column = header.index('Instructions') - 1
         except (IndexError, ValueError):
             raise LineupOptimizerIncorrectCSV
         position_names = header[start_column:end_column]
         players_dict = {player.id: player for player in players}
         lineups = []
         for line in lines:
             if not line[0]:
                 break
             lineup_players = []
             for index, position in zip(range(start_column, end_column),
                                        position_names):
                 try:
                     player_data = line[index]
                     player_data = player_data.replace(
                         '(LOCKED)',
                         '')  # Remove possible '(LOCKED)' substring
                     player_id = player_data.split('(')[1][:-1]
                 except IndexError:
                     raise LineupOptimizerIncorrectCSV
                 try:
                     player = players_dict[player_id]
                 except KeyError:
                     raise LineupOptimizerIncorrectCSV(
                         'Player not found in players pool')
                 lineup_players.append(LineupPlayer(player, position))
             lineups.append(Lineup(lineup_players))
         return lineups
예제 #3
0
 def setUp(self):
     self.future_game_info = GameInfo(
         home_team='H',
         away_team='A',
         game_started=False,
         starts_at=datetime.now(timezone('EST')) + timedelta(days=1))
     self.finished_game_info = GameInfo(
         home_team='H',
         away_team='A',
         game_started=False,
         starts_at=datetime.now(timezone('EST')) - timedelta(days=1))
     self.lineup_optimizer = get_optimizer(Site.DRAFTKINGS,
                                           Sport.BASKETBALL)
     positions = ['PG', 'SG', 'SF', 'PF', 'C', 'PG/SG', 'SF/PF', 'C']
     self.active_players = create_players(positions,
                                          game_info=self.future_game_info,
                                          salary=5000,
                                          fppg=20)
     self.inactive_players = create_players(
         positions, game_info=self.finished_game_info, salary=4500, fppg=10)
     self.lineup_optimizer.load_players(self.active_players +
                                        self.inactive_players)
     self.lineup = Lineup([
         LineupPlayer(self.active_players[0], 'PG'),
         LineupPlayer(self.inactive_players[1], 'SG'),
         LineupPlayer(self.active_players[2], 'SF'),
         LineupPlayer(self.inactive_players[3], 'PF'),
         LineupPlayer(self.active_players[4], 'C'),
         LineupPlayer(self.inactive_players[5], 'G'),
         LineupPlayer(self.active_players[6], 'F'),
         LineupPlayer(self.inactive_players[7], 'UTIL'),
     ])
예제 #4
0
 def import_lineups(self, players):
     with open(self.filename, 'r') as csv_file:
         lines = csv.reader(csv_file)
         try:
             header = next(lines)
             start_column = 4  # First 4 columns has info about tournament
             end_column = header.index('Instructions') - 1
         except (IndexError, ValueError):
             raise LineupOptimizerIncorrectCSV
         position_names = header[start_column:end_column]
         players_dict = {player.id: player for player in players}
         lineups = []
         for line in lines:
             if not line[0]:
                 break
             lineup_players = []
             for index, position in zip(range(start_column, end_column), position_names):
                 try:
                     match = re.search(self.LINEUP_PLAYER_ID_REGEX, line[index])
                 except IndexError:
                     raise LineupOptimizerIncorrectCSV
                 if not match:
                     raise LineupOptimizerIncorrectCSV
                 player_id = match.group('id')
                 try:
                     player = players_dict[player_id]
                 except KeyError:
                     raise LineupOptimizerIncorrectCSV('Player not found in players pool')
                 lineup_players.append(LineupPlayer(player, position))
             lineups.append(Lineup(lineup_players))
         return lineups
예제 #5
0
 def test_standard_strategy(self):
     player1 = Player('1', '1', '1', ['P'], 'test', 5000, 20)
     player2 = Player('2', '2', '2', ['P'], 'test', 8000, 30)
     strategy = StandardFantasyPointsStrategy()
     self.assertEqual(strategy.get_player_fantasy_points(player1), 20)
     self.assertEqual(strategy.get_player_fantasy_points(player2), 30)
     strategy.set_previous_lineup(Lineup([LineupPlayer(player1, 'P')]))
     self.assertEqual(strategy.get_player_fantasy_points(player1), 20)
     self.assertEqual(strategy.get_player_fantasy_points(player2), 30)
예제 #6
0
 def test_progressive_strategy(self):
     player1 = Player('1', '1', '1', ['P'], 'test', 5000, 20)
     player2 = Player('2',
                      '2',
                      '2', ['P'],
                      'test',
                      8000,
                      30,
                      progressive_scale=0.2)
     strategy = ProgressiveFantasyPointsStrategy(scale=0.1)
     self.assertEqual(strategy.get_player_fantasy_points(player1), 20)
     self.assertEqual(strategy.get_player_fantasy_points(player2), 30)
     strategy.set_previous_lineup(Lineup([LineupPlayer(player1, 'P')]))
     self.assertEqual(strategy.get_player_fantasy_points(player1), 20)
     self.assertEqual(strategy.get_player_fantasy_points(player2), 36)
     strategy.set_previous_lineup(Lineup([LineupPlayer(player1, 'P')]))
     self.assertEqual(strategy.get_player_fantasy_points(player1), 20)
     self.assertEqual(strategy.get_player_fantasy_points(player2), 42)
     strategy.set_previous_lineup(Lineup([LineupPlayer(player2, 'P')]))
     self.assertEqual(strategy.get_player_fantasy_points(player1), 22)
     self.assertEqual(strategy.get_player_fantasy_points(player2), 30)
예제 #7
0
 def _build_lineup(self, players, unswappable_players=None):
     # type: (List[Player], Optional[List[LineupPlayer]]) -> Lineup
     lineup = []
     positions = self._settings.positions[:]
     if unswappable_players:
         players = [
             player for player in players
             if player not in unswappable_players
         ]
         positions = get_remaining_positions(positions, unswappable_players)
         lineup.extend(unswappable_players)
     players_with_positions = link_players_with_positions(
         players, positions)
     for player, position in players_with_positions.items():
         lineup.append(LineupPlayer(player, position.name))
     positions_order = [pos.name for pos in self._settings.positions]
     lineup.sort(key=lambda p: positions_order.index(p.lineup_position))
     return Lineup(lineup, self._settings.lineup_printer)
예제 #8
0
 def test_random_strategy(self):
     player1 = Player('1',
                      '1',
                      '1', ['P'],
                      'test',
                      5000,
                      20,
                      min_deviation=0.1,
                      max_deviation=0.2)
     player2 = Player('2', '2', '2', ['P'], 'test', 8000, 40)
     strategy = RandomFantasyPointsStrategy(0.05, 0.1)
     player1_fppg = strategy.get_player_fantasy_points(player1)
     if player1_fppg < 16 or 18 < player1_fppg < 22 or player1_fppg > 24:
         self.fail('Incorrect generated points')
     player2_fppg = strategy.get_player_fantasy_points(player2)
     if player2_fppg < 36 or 38 < player2_fppg < 42 or player2_fppg > 44:
         self.fail('Incorrect generated points')
     strategy.set_previous_lineup(Lineup([LineupPlayer(player1, 'P')]))
     player1_fppg = strategy.get_player_fantasy_points(player1)
     if player1_fppg < 16 or 18 < player1_fppg < 22 or player1_fppg > 24:
         self.fail('Incorrect generated points')
     player2_fppg = strategy.get_player_fantasy_points(player2)
     if player2_fppg < 36 or 38 < player2_fppg < 42 or player2_fppg > 44:
         self.fail('Incorrect generated points')
예제 #9
0
    def optimize(self, n=1):
        '''
        Select optimal lineup from players list.
        This method uses Mixed Integer Linear Programming method for evaluating best starting lineup.
        It's return generator. If you don't specify n it will return generator with all possible lineups started
        from highest fppg to lowest fppg.
        :type n: int
        :rtype: List[Lineup]
        '''
        positions = {}
        current_max_points = 100000

        # not sure why this is at the top - something to do with iterators??
        lineup_points = sum(player.fppg for player in self._lineup)
        if len(self._lineup) == self._settings.total_players:
            lineup = Lineup(self._lineup)
            yield lineup
            raise StopIteration()

        counter = 0
        while n > counter:
            players = self._players
            prob = LpProblem("Daily Fantasy Sports", LpMaximize)
            x = LpVariable.dicts('players',
                                 players,
                                 lowBound=0,
                                 upBound=1,
                                 cat=LpInteger)

            # objective function - maximize fppg
            prob += sum([player.fppg * x[player] for player in players])

            # constraints
            ## < current_max_points: needed for multiple lineups - set max points slightly below last lineup
            ## < budget: have to obey salary cap
            ## = total_players: need correct number of players
            ## == 1: no duplicate player IDs
            ## num + addition: obey position minimums (1,1,1,1,1,3,3)
            prob += sum([player.fppg * x[player]
                         for player in players]) <= current_max_points
            prob += sum([player.salary * x[player]
                         for player in players]) <= self._budget
            prob += sum([x[player]
                         for player in players]) == self._total_players
            for pid in set([p.id for p in players]):
                prob += sum(
                    [x[player] for player in players if player.id == pid]) == 1
            for position, num in self._positions.items():
                prob += sum([x[player] for player in players if
                             any([player_position in position for player_position in player.positions])]) \
                             >= num
            GUROBI(OutputFlag=0).solve(prob)
            if prob.status == 1:
                lineup_players = self._lineup[:]
                for player in players:
                    if x[player].value() == 1.0:
                        lineup_players.append(player)
                lineup = Lineup(lineup_players)
                current_max_points = lineup.fantasy_points_projection - lineup_points - 0.1
                yield lineup
                counter += 1
            else:
                raise LineupOptimizerException("Can't generate lineups")
        raise StopIteration()