DimaKudosh / pydfs-lineup-optimizer

Daily Fantasy Sports lineup optimzer for all popular daily fantasy sports sites
MIT License
420 stars 157 forks source link

feature request: DK showdown captain slates #31

Closed sansbacon closed 5 years ago

sansbacon commented 5 years ago

DraftKings now has one-game "showdown captain mode" games that have the same salary cap but a few differences from the ordinary DraftKings game:

(1) There are only six lineup spots.

(2) There are no fixed positions (everything is FLEX) and you can play kickers as well as the ordinary positions on DraftKings.

(3) There is a captain slot in the lineup. The captain costs 1.5X the published salary and gets 1.5X the points earned.

So the settings would be:

@SitesRegistry.register_settings class DraftKingsCaptainFootballSettings(DraftKingsSettings): sport = Sport.FOOTBALL positions = [ LineupPosition('CAPTAIN', ('QB','WR','RB','TE','DST','K')), LineupPosition('FLEX1', ('QB','WR','RB','TE','DST','K')), LineupPosition('FLEX2', ('QB','WR','RB','TE','DST','K')), LineupPosition('FLEX3', ('QB','WR','RB','TE','DST','K')), LineupPosition('FLEX4', ('QB','WR','RB','TE','DST','K')), LineupPosition('FLEX5', ('QB','WR','RB','TE','DST','K')) ]

It is unclear to me how to modify the existing optimize function to account for the "captain," which increases a player's salary and fantasy points per game when used in that slot.

Thanks! Eric

sansbacon commented 5 years ago

You can use a player pool that has every player listed twice, once with projections and salaries for the FLEX position and a second time with the 1.5X projections and salaries for the CPT position. This is how the csv file provided by DraftKings is structured (I've attached a copy of what it looks like).

Since the same player is listed twice in the pool, there has to be a "DuplicatePlayerRule" that a player cannot be used more than once. The catch is that DraftKings uses a different playerID for the same player (a player ID for captain and a different player ID for flex). So the constraint either has to be based on the player's name or a player ID assigned by the user that identifies the same player, whether the position is captain or flex.

@SitesRegistry.register_settings class DraftKingsCaptainFootballSettings(DraftKingsSettings): sport = Sport.FOOTBALL positions = [ LineupPosition('CPT', ('CPT')), LineupPosition('FLEX1', ('FLEX')), LineupPosition('FLEX2', ('FLEX')), LineupPosition('FLEX3', ('FLEX')), LineupPosition('FLEX4', ('FLEX')), LineupPosition('FLEX5', ('FLEX')) ]

class DuplicatePlayerRule(OptimizerRule): def apply(self, solver, players_dict): . . . . . solver.add_constraint(. . . , coefficients, SolverSign.LTE, 1)

ShowdownDKSalaries.zip

sansbacon commented 5 years ago

I think the "duplicate player" constraint is expressed as follows (as noted above, the player as captain and the player as flex should be given the same ID):

`

iterate over the unique player ids

add constraint that sum of times that player

is used in the solution <= 1

for player_id in set([p.id for p in players]): self.prob += lpSum([x[player] for player in players if player.id == player_id]) <= 1 `