pydfs-lineup-optimizer
pydfs-lineup-optimizer copied to clipboard
Feature Request: Lineup Ownership
I am not so much concerned with individual player ownership as much as total lineup ownership.
For example, in PGA if I have six golfers projected at 25% ownership each, that means my lineup is projected to have a ownership of (0.25^6) * 100 = 0.02%. That means in a field of 400,000 you would share a lineup with roughly 100 people. I'm trying to prevent from doing this.
Is there currently a way to set a maximum lineup ownership, and if not could this be added? Thanks.
Currently optimizer has set_projected_ownership method and it calculates average ownership of players in lineup. So in your case you can set optimizer.set_projected_ownership(max_projected_ownership=0.25)
and lineup will include players with approximately 25% ownership, roughly it should generate close result to what you described. According to this feature it will hard to implement it because MIP problem doesn't support multiplying solver variables (player appearance in lineup is solver variable under the hood) and therefore I can't add it as constraint to MIP problem.
@DimaKudosh Would it be possible to use the set_projected_ownership method for X amount of players per lineup? For example, what if I wanted each lineup to contain 2 players under 5% projected ownership. The intuition is that you might be able to create more studs and scrubs lineups with a high medium projection but also a decent amount of variance.
@McCampy You can achieve this without using set_projected_ownership. You can create group with all players under 5% ownership and set min players from this group.
optimizer.add_players_group(PlayersGroup(
players=[player for player in optimizer.players if p.projected_ownership <= 0.05],
min_from_group=2,
))
@DimaKudosh This is perfect, thank you.
You can implement the constraint as a sum, not a product.
The user of the library would determine the appropriate max_lineup_ownership_sum. In the example above, if you have a field of 400,000 and you want an estimated chance of duplication less than 1%, set max_lineup_ownership_sum ~ .75.
The rule would be something like
prob += lpSum([player_var * projected_ownership for player_var, projected_ownership in player_vars, ownership_projections]) <= max_lineup_ownership_sum
I ran a quick simulation that can give you some guidelines on what the appropriate max_lineup_ownership_sum should be for your use case. For large fields, it looks like < 1 would be a reasonable choice.
import numpy as np
import pandas as pd
field_size = 400000
samples = []
for _ in range(500000):
owns = np.random.randint(1, 40, size=6) / 100
samples.append({'ownsum': np.sum(owns), 'stdev': np.std(owns), 'dups': np.product(owns) * field_size})
df = pd.DataFrame(samples)
(
df
.assign(ownsum=lambda x: x.ownsum.round(2))
.groupby('ownsum')
.agg(avg_dups=('dups', 'mean'))
.sort_values('ownsum')
)
@McCampy You can achieve this without using set_projected_ownership. You can create group with all players under 5% ownership and set min players from this group.
optimizer.add_players_group(PlayersGroup( players=[player for player in optimizer.players if p.projected_ownership <= 0.05], min_from_group=2, ))
@DimaKudosh This was working for a short time for me, now i get this error
NameError Traceback (most recent call last)
NameError: name 'p' is not defined