UPDATE on 10/5/2015: Explained how to model a requirement of baseball leagues (Requirement 4).
UPDATE on 10/8/2015: Explained how to model a different objective function (Requirement 5).
Yesterday, I wrote a post describing an optimization model for picking a set of players for a fantasy football team that maximizes the teams’ point projection, while respecting a given budget and team composition constraints. In this post I’ll assume you’re familiar with that model. (If you are not, please spend a few minutes reading this first.)
Fellow O.R. blogger and Analytics expert Matthew Galati pointed out that my model did not include all of the team-building constraints that appear on popular fantasy football web sites. Therefore, I’m writing this follow-up post to address this issue. (Thanks, Matthew!) My MBA student Kevin Bustillo was kind enough to compile a list of rules from three sites for me. (Thanks, Kevin!) After looking at them, it seems my previous model fails to deal with three kinds of requirements:
- Rosters must include players from at least different NFL teams ( for Draft Kings and for both Fan Duel and Yahoo!).
- Rosters cannot have more than players from the same team ( for Fan Duel and for Yahoo! Draft Kings does not seem to have this requirement).
- Players in the roster must represent at least different football games (Only Draft Kings seems to have this requirement, with ).
Let’s see what the math would look like for each of the three requirements above. (Converting this math into Excel formulas shouldn’t be a problem if you follow the methodology I used in my previous post.) I’ll be using the same variables I had before (recall that binary variable indicates whether or not player is on the team).
Last time I checked, the NFL had 32 teams, so let’s index them with the letter and create 32 new binary variables called , each of which is equal to 1 when at least one player from team is on our team, and equal to zero otherwise. The requirement that our team must include players from at least teams can be written as this constraint:
The above constraint alone, however, won’t do anything unless the variables are connected with the variables via additional constraints. The behavior that we want to enforce is that a given can only be allowed to equal 1, if at least one of the players from team has its corresponding variable equal to 1. To make this happen, we add the constraint below for each team :
For example, if the Miami Dolphins are team number 1 and their players are numbered from 1 to 20, this constraint would look like this:
Repeat the following constraint for every team :
Assuming again that the first 2o players represent all the players from the Miami Dolphins, this constraint on Fan Duel would look like this:
My understanding of this requirement is that it applies to short-term leagues that get decided after a given collection of games takes place (it could even be a single-day league). This could be implemented in a way that’s very similar to what I did for requirement 1. Create one binary variable for each game . It will be equal to 1 if your team includes at least one player who’s participating in game , and equal to zero otherwise. Then, you need this constraint
as well as the constraint below repeated for each game :
Additional Requirements Submitted by Readers
I earlier claimed that this model can be adapted to fit fantasy leagues other than football. So here’s a question I received from one of my readers:
For fantasy baseball, some players can play multiple positions. E.g. Miguel Cabrera can play 1B or 3B. I currently use OpenSolver for DFS and haven’t found a good way to incorporate this into my model. Any ideas?
Let’s call this…
Requirement 4: What if some players can be added to the team at one of several positions?
Here’s how to take care of this. Given a player , let the index represent the different positions he/she can play. Instead of having a binary variable representing whether or not is on the team, we have binary variables (as many as there are possible values for ) representing whether or not player is on the team at position . Because a player can either not be picked or picked to play one position, we need the following constraint for each of these multi-position players:
Because we have replaced with a collection of ‘s, we need to replace all occurrences of in our model with .
In the Miguel Cabrera example above, let’s say Cabrera’s player ID (the index ) is 3, and that represents the first-base position, and represents the third-base position. The constraint above would become
And we would replace all occurrences of in our model with .
Reader rs181602 asked me the following question:
I was wondering, is there a way to add an additional constraint that maximizes the minimum rating of the chosen players, if each player has some rating score. I tried to think that out, but can’t seem to get it to be linear.
Let’s call this…
Requirement 5: What if I want to maximize the point projection of the worst player on the team? (In other words, how do I make my worst player as good as possible?)
It’s possible to write a linear model to accomplish this. Technically speaking, we would be changing the objective function from maximizing the total point projection of all players on the team to maximizing the point projection of the worst player on the team. (There’s a way to do both together (sort of). I’ll say a few words about that later on.)
Here we go. Because we don’t know what the projection of the worst player is, let’s create a variable to represent it and call it . The objective then becomes:
You might have imagined, however, that this isn’t enough. We defined in words what we want to be, but we still need formulas to make behave the way we want. Let be the largest point projection among all players that could potentially be on our team. It should be clear to you that the constraint is a valid ceiling on the value of . In fact, the value of will be limited above by 9 values/ceilings: the 9 point projections of the players on the team. We want the lowest of these ceilings to be as high as possible.
When a player is not on the team (), his point projection should not interfere with the value of . When player is on the team (), we would like to become a ceiling for , by enforcing . The way to make this happen is to write a constraint that changes its behavior depending on the value of , as follows:
We need one of these for each player. To see why the constraint above works, consider the two possibilities for . When (player not on the team), the constraint reduces to (the obvious ceiling), and when (player on the team), the constraint reduces to (the ceiling we want to push up).
BONUS: What if I want, among all possible teams that have the maximum total point projection, the one team whose worst player is as good as possible? To do this, you solve two optimization problems. First solve the original model maximizing the total point projection. Then switch to this model and include a constraint saying that the total point projection of your team (the objective formula of the first model) should equal the total maximum value you found earlier.
And that does it, folks!
Does your league have other requirements I have not addressed here? If so, let me know in the comments. I’m sure most (if not all) of them can be incorporated.