DimaKudosh / pydfs-lineup-optimizer

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

Feature request: applying max exposure progressively #185

Open harvitronix opened 3 years ago

harvitronix commented 3 years ago

Max exposure currently works in a naive way. Here's the problem:

You maybe get something like this:

Position X Position Y Position Z
Player A Player B Player C
Player A Player B Player D
Player A Player B Player E
Player A Player B Player F
Player A Player B Player G
Player H Player I Player J
Player H Player I Player K
Player H Player I Player L
Player H Player I Player M
Player H Player I Player N

Notice that player A and B are in all the first half of lineups, then never again, and likewise H and I are in the second half, but don't appear anywhere before. This is almost certainly sub-optimal, as your two star value players (A and B) are either both in or both out in every lineup.

I understand the optimizer deals with max exposure one lineup at a time, so it doesn't have the full context of the resulting lineups. But could it do something like:

Any thoughts on how we can do this? I'm happy to contribute with a little guidance.

harvitronix commented 3 years ago

@DimaKudosh Oh, it seems this may have been handled already? Is that what this does? https://github.com/DimaKudosh/pydfs-lineup-optimizer/issues/159

harvitronix commented 3 years ago

In case future searches find this, see the linked issue #159, or here:

from pydfs_lineup_optimizer import AfterEachExposureStrategy
optimizer.optimize(10, exposure_strategy=AfterEachExposureStrategy)
harvitronix commented 3 years ago

Sorry to spam this issue, but I think there's a problem in the current implementation, @DimaKudosh. It is removing every player who hits the max_exposure at the current lineup, which means that in my scenario above, player A and B will still always be in the same lineups as each other. They're simply excluded for lineups 2 and 3 and then put back in for 4, 6, 8, etc. So you still don't get any diversification for the top value players, but only for players who are filling in the gap.

Let me know if that makes sense or if you would like further explanation (or if this is even useful, I understand if it's not a priority).

bigboyz commented 3 years ago

I really have nothing to add to harvtronix note above, but to confirm I am getting the exact same result as him. Really wish there was a way to get max_exposure and min_exposure to work more efficiently. I would happily give up processing speed in order to get Player A and B in the second half of my lineups.

I think the problem is the logic doesn't allow it to break a constraint. Ideally, it would have the flexibility to break a constraint and then try to balance it on next lineup generated. I would also be happy to contribute in anyway to find a way to solve this.

harvitronix commented 3 years ago

I think the problem is the logic doesn't allow it to break a constraint. Ideally, it would have the flexibility to break a constraint and then try to balance it on next lineup generated.

^ this.

sansbacon commented 3 years ago

I would split your lineup generation into chunks, so if you want 20 lineups, do 4 chunks of 5. In each chunk, you can block player(s) who have too much exposure.

n_lineups = 20
exclude_chunks = (('Player 1'), ('Player 2'), ('Player 1', 'Player 3'), ('Player 1', 'Player 2'))

lineups = []
for exclude in exclude_chunks:
    for item in exclude:
        player = optimizer.get_player_by_name(item)
        optimizer.remove_player(player)
    for lineup in optimizer.optimize(n_lineups / len(exclude_chunks)):
        lineups.append(lineup)
    for item in exclude:
        player = optimizer.get_player_by_name(item)
        optimizer.restore_player(player)

At some point, what you are really asking for is more of a genetic algorithm than a linear-programming model. I would generate a large number of optimal lineups and then do some random variations on them after-the-fact to reach the desired results.