Calculating the Highest Value to Bid on Each Player in an Auction Draft: The Bid Up To Value
45In this post, I calculate the highest value you should bid on each player in an auction draft—what I refer to as the “bid up to” value. In a previous post, I showed how to determine the best starting lineup to draft using an optimizer tool. The “bid up to” value is calculated by finding the highest cost up to which a player is still on the best lineup, as determined by the optimizer.
How it Works
The optimizer tool finds the starting lineup that maximizes your team’s projected points, while staying within your risk tolerance. By placing the optimization function in a loop, we can calculate the optimal starting lineup for each player at each cost. For example, to find Tom Brady’s bid up to value, we can start his cost at $1 and run the optimization function. At this price, Tom Brady is on the best starting lineup, so we increase his cost by $1 while keeping all other players at their expected cost. At $2, Tom Brady is still on the best starting lineup, so we increase his cost again by $1. We repeat this until Tom Brady’s cost is too high for him to be on the best starting lineup. As of this writing and given my league settings, Tom Brady’s bid up to value is $16. That means that Tom Brady is a good value up to $16—if he’s above that price, I should draft someone else because he is no longer on the optimal starting lineup at this cost. After calculating Tom Brady’s bid up to value, we reset his cost to his expected cost and then we calculate the bid up to value for the next player. We repeat this for all players to calculate each player’s bid up to value.
The R Script
The R Script for looping the optimizer to find each player’s bid up to value is located here:
Here is the syntax for looping the optimizer to calculate each player’s bid up to value:
Conclusion
I demonstrated how to calculate a bid up to value for each player. Calculating a bid up to value for each player is a great way to calculate a player’s value in an auction draft because it helps you determine the highest bid you should make for each player. If a player goes for more than his bid up to value, you should draft someone else.
Great site. But how do you use the Bid up To Value script?
Hey Alfredo,
You can download the R script from GitHub (https://github.com/isaactpetersen/FantasyFootballAnalyticsR/blob/master/R%20Scripts/Calculations/Bid%20Up%20To.R). Run it with R to determine the optimal bidding value for every player.
-Isaac
iS there a downloadable version with this done for us for 2016? Love to have this as a chart for drafts
A downloadable version of which chart?
Hey Isaac,
Was interested in how to actually go about running this script – seems like it needs a bunch of other scripts/package(s) to work correctly. Do you know what I should download to be able to run it / is there something I’m missing?
Thanks
Hi Ricky,
Yes, the script depends on other scripts and packages. You might start here:
https://fantasyfootballanalytics.net/2014/10/download-run-r-scripts.html
We haven’t updated this particular script for this season, so it might require some re-working. But the proof-of-concept is what’s most crucial here. So you should be able to adapt it to meet your needs.
-Isaac
Any idea which other scripts I’m going to need? Should I just download all of your scripts from Github?
You will need the Functions.R and League Settings.R (https://fantasyfootballanalytics.net/2014/10/download-run-r-scripts.html). Here’s the order the scripts were run last season:
https://github.com/isaactpetersen/FantasyFootballAnalyticsR/blob/master/R%20Scripts/Prepare%20Data.R
Note, however, that many of these scripts have not been updated for this season.
Hey Isaac,
I just found your site recently and love it. Great job! I’m wondering if there’s a place to input the number of teams in my league and the number of RBs, WRs, etc that we start within the app?
Thanks!
Hi Jack,
We are currently working on updating the Auction tool so it’s ready for draft season. It will include inputs for number of teams in your league and roster positions.
-Isaac
Isaac,
Novice to Git, GitHub, R and RStudio here.
Will you be providing an on-site app (similar to the Roster Optimization and VOR) for the Bid-Up-to-Value? May help some of us less tech savvy full appreciate your brilliance here.
Rob
Hi Rob,
We are working on the Auction tool now. It will calculate players’ projected costs that reflect how much you should be willing to pay for a player if he is selected by our draft optimizer. For more info, see here:
https://fantasyfootballanalytics.net/2013/06/win-your-fantasy-football-auction-draft.html
Although I like the simulation approach to calculating a Bid-Up-To value, it’s not easily implemented in a web-app because it requires many runs (and time) to estimate. Hope to release the tool soon.
Hope that helps,
Isaac
Got it. Thanks Isaac!
Looking forward to the release of your 2015-16 auction tool soon.
Hi – nice site!
1) reading other comments on “cost” & “bid-up value”, I’m not sure how to apply this in actual drafts. how should I use the “cost” column?
2) does optimal strategy change based on actions of other teams in league? (which positions were already taken, how much they’ve already spent on each player at each position, etc.) if so, can you make it so we can add how much each player goes for (and maybe even to which team in the league)?
3) the present speed of the tool (for free thank you) would make it hard to use in a live auction, is there a paid version that is faster?
4) is this usable in a live draft? if yes, what’s best strategy for the tool?
much thanks!
Hi James,
1) The “Cost” column is described here:
https://fantasyfootballanalytics.net/2013/06/win-your-fantasy-football-auction-draft.html
2) Optimal strategy could change based on other teams. We haven’t gotten to adding that logic yet. Right now, you can modify players’ costs by selecting your AAV source and choosing the Low/Mid/High rank and multiplier.
3) We are working on an offline tool. We’ve had a number of users use the tool during Auction drafts without a problem. We’re trying to find ways to speed it up, but it’s faster than it takes most players to be picked in an Auction Draft, and it doesn’t have to re-optimize after every player is selected.
4) For strategy, see here:
https://fantasyfootballanalytics.net/2013/06/win-your-fantasy-football-auction-draft.html
Hope that helps,
Isaac
Isaac,
In reviewing the data set, I noticed the most recent data pull from GitHub was 2014 data. Will you have the 2015 “Bid-up-to-value” data available soon? Or am I doing something wrong?
Rob
Also, when I run the command, I am finding that some of the files are out of place and thus the command comes to a grinding halt.
Again, maybe it’s just me, but if you’d like I could show the errors via email.
Hi Rob,
We have plans to update the GitHub repo after we finish the draft tools. In the meantime, you can update the scripts to calculate a “Bid-Up-To” value for the 2015 season. However, note that there isn’t a “true value” cost of players because research has shown you should be willing to over-spend on key players: https://harvardsportsanalysis.files.wordpress.com/2012/04/fantasyfootballdraftanalysis1.pdf. In other words, there is no simple way of translating points to cost.
Hope that helps,
Isaac
Hi Isaac,
While not a “bid up to value” per se, I wanted to find out the highest price where I basically had to take a certain player (regardless of whether I like him or not).
I figured that an easy way to do this was to find the player with the highest VOR per $ ( using average auction value) and use that figure as a benchmark. In the data I just pulled from the projections that ends up being Andre Ellington at around 2.84 VOR/$.
From there I rearranged the formula so that a given players “Must buy at price”, x, was equal to their VOR/2.84.
This basically gives me the price at which any player is as efficient (on a VOR/$ basis) as the most efficient player in the league.
Does this make sense? Maybe you have a better method to calculate the price ceiling at which I HAVE to bid on a given player.
Hi Jake,
Interesting approach. Fascinating that Andre Ellington has the highest ROI given that he has the highest injury risk of all RBs (http://sportsinjurypredictor.com/injury-predictor/injury-predictor/search-by-position/rb/high-to-low). So you’re paying less for him likely, in part, because he is injury prone. We have plans to include an ROI variable in the future.
Thanks,
Isaac
Sounds cool. Great website btw, it’s tons of fun to play around with.
Jake
Hi,
How would you use the ‘bid up to value’ with the Optimizer? Any plans to integrate them?
Thanks,
Jim
Hi Jim,
The “Bid-Up-To” value discussed in the above article is a simulation that takes time to run and is specific to your league settings, so it wouldn’t be practical for a webapp. You could always run it offline, though. If you have ideas how to efficiently calculate a Bid-Up-To value, I’m all ears!
Thanks,
Isaac
Isaac,
These resources are absolutely fantastic, I appreciate the great work. Your projections provide a cornerstone of my draft preparation and strategy.
I implemented a different version of your Optimizer using Excel. It runs more quickly for me locally, and also provides me more control to tweak the Cost values on the fly based on how results come rolling in. (Solver only allows you to optimize over 200 variables, but since I ideally won’t dip past the top 200 for my starting roster, I find that this is enough.) I was able to ‘win’ my 8-team Yahoo draft and will refine the model for a 16-team ESPN keeper draft I have coming up.
One of the biggest benefits of the local implementation, however, is that I am able to integrate a Bid-Up-To tool. Your approach above is robust but, as you note, rather impractical. A first thought that struck me is that you might be better served to start at a player’s expected cost and DECREASE this by one until the player is included in the optimal set. This assumes that, on average, a player will become optimal at some value >50% of the projected cost, which I think is accurate for top-level players at least. To add a layer of refinement, you could investigate this question for a variety of players, try to find some proxy (such as perhaps VOR) that helps classify players by whether bid-up-to is > or = the points baseline from Step 1.
4) Change the objective from maximizing points to minimizing cost. (Steps 3 and 4 change your program from “maximize my points subject to cost constraints, along with position, risk, etc. constraints” to “minimize the cost subject to achieving at least as many points as before, along with position, risk, etc. constraints.” The program remains linear.) Run the optimizer.
5) Subtract the minimized roster cost from your remaining starter budget. This is the bid-up-to value for the player.
This does require a bit of back-and-forth between calculating your baseline and calculating the bid-up-to for any player. The baseline must be recalculated any time your roster changes or one of the players on your optimal roster is selected. I would also periodically update my cost estimates based on live results, which would also require a new baseline. And then whenever a potential starter is nominated, the bid-up-to program would be run against the current baseline.
I haven’t yet implemented a program for calculating bid-up-to for players on the optimal roster. Your method of incrementing is a good start (starting of course with the player’s cost, not at 0). However, it could also be done in two steps:
1) Remove the player from the pool and calculate a “second-best” point baseline (the points of your optimal roster if this player is not available).
2) Run the program described above using this “second-best” point baseline.
I’d be happy to discuss any of this further – feel free to reach out to me.
Thanks,
Jason
This comment was truncated for some reason. I have saved a copy of the original and would like to provide it if possible.
Hi Jason,
It’s actually much faster in R than in Excel. It’s slower online because we have to send lots of data across servers. Agreed that it’s easier to calculate a Bid-Up-To value locally that’s specific to your league settings. You could decrease from their expected projected cost (except for players already selected by the optimizer at that cost).
Thanks,
Isaac
My comment above was somehow cut in the middle, so it stops making sense at about the mention of using VOR as a proxy. 🙂
One can (and I did) use a single linear program to optimize for bid-up-to, once you have your optimal roster baseline. This program works for any player NOT on your optimal roster already. I’ll sketch it here:
1) Calculate the optimal roster baseline subject to the normal constraints and whatever positions are already satisfied on your roster. Consider the expected points for the lineup as the “points baseline.”
2) Taking the player that you want to calculate “bid-up-to” for, set the integer for this player to 1 and his cost to 0. This implies selecting the player at cost = 0.
2a) Note: This obviously doesn’t make sense if the player will violate your constraints, e.g. he is a second QB. In this case the optimizer of course won’t be able to find a value, but you could use some logic against the constraints before starting the optimizer just to save time.
3) Remove the cost constraint and add a constraint whereby points must be >= the points baseline from Step 1.
4) Change the objective from maximizing points to minimizing cost. (Steps 3 and 4 change your program from “maximize my points subject to cost constraints, along with position, risk, etc. constraints” to “minimize the cost subject to achieving at least as many points as before, along with position, risk, etc. constraints.” The program remains linear.) Run the optimizer.
5) Subtract the minimized roster cost from your remaining starter budget. This is the bid-up-to value for the player.
So, a single run of the simplex method gives you your answer – no search algorithm needed. For a player already on the roster, see the two steps at the end of my note above.
I have no doubt that R will run faster (and is much more powerful for running scripts, etc.) but I have just basic R literacy and am much more comfortable in Excel for now. Maybe next season that will have changed 🙂
Thanks,
Jason
Jason/Isaac,
I have been trying to replicate in excel a lot of what Isaac has been trying to do and have come to a few obstacles. First is that the solver function in excel is not 100% accurate when using the Simplex LP. Solver with that method is very close to accurate, but gave me 10 points less than what I found to be the optimal lineup using trial and error. (I caught this because I was using a bid up to macro and noticed that if a player increased in value the optimal lineup increased?!?!)
So I began to research why this is. If you use the GRG Nonlinear or Evolutionary solving methods they are more accurate, but can take hours, days, or with enough constaints, years to return their results.
Jason,
I would like to see your excel spreadsheet if you don’t mind sharing. I plan to start learning how to use R and hopefully can check the excel results for optimal lineups/bid up to amounts against it.
We use R (not Excel) for our optimization, which is fast, accurate, and reliable.
Hi Isaac and Jason
I recently started dabbling in auction drafts, and so I have implemented the optimizer and the bid up to value tool. I have a couple of thoughts regarding this issue.
1. I agree with Isaac that Excel seems like a pain to use here. It is very slow and generally ill suited for this purpose. I used MATLAB since that is what I’m most proficient at, but languages like R and Python are also great.
2. Starting at a players cost and going down is a bad idea. The assumption “on average, a player will become optimal at some value >50% of the projected cost” is indeed accurate for top level players. The problem is that in my tests the players with bid up to value greater than 0 become optimal at a value which is on average 1.5 times the projected cost. Thus you cannot assume that the projected cost is some upper limit.
3. The best strategy here I can think of is to use a binary search. Stepping down or up by 1 is inefficient. Instead, start at some reasonable estimate, e.g. projected cost. Then repeatedly double (setting the current value as the lower limit) or half (setting the current value as the upper limit) the estimate, depending on if it was too small or big respectively. Do this until you hit 0 or have an upper and lower limit on the value. From there try the middle, and half that interval until the size of the interval is 1, at which point you have the correct value.
In some quick tests with 300 players and the roster [QB, WR, WR, WR, RB, RB, TE, K, DST], binary search works around 3 times as fast as stepping up from 0 for top players (players with a bid up value significantly larger than 0). However for later players, the difference is basically nonexistent since they almost always have a bid up value of 0, in which case both methods use just 1 optimiser call anyway.
Eirik, this is helpful. I now agree that my discussion above doesn’t take enough factors into account – e.g., given the differences existing between different positions, what players have already been drafted, etc. would make it difficult to use some sort of proxy. Given this, your binary search makes more sense (although use of a single linear program, see my reply comment above, should be more optimal yet for players not on the optimal roster).
I do however wonder how you arrive at bid-up-to values “on average 1.5 times the projected cost.” It seems to me that this can only be the case for players on your optimal roster already – otherwise, if a player is optimal at 1.5x more than expected cost, he should also be optimal at his expected cost, and therefore on the optimal roster? And even for players on the optimal roster, I have not seen instances where the bid-up-to value is so high. What sort of projections and optimal rosters do you use when getting these results?
Yes now that I see your entire comment I fully agree your method is even better, since at most you need two runs. I actually have implemented your version now, and it seems to work very well with only a few very minor differences in the computed bid up to values, so thank you for the idea.
You are of course right regarding large bid up to values. I wrote this fairly early in the morning, so I suspect i managed to invert the ratio 😉
-Eirik
Hey Eirik and Jason,
Thanks for improving the efficiency of this calculation. The community would greatly appreciate it if you could share your improvements by creating a pull request to our GitHub repo. For more info how to do this, see here:
https://fantasyfootballanalytics.net/2014/10/download-run-r-scripts.html
Here’s the relevant file:
https://github.com/isaactpetersen/FantasyFootballAnalyticsR/blob/master/R%20Scripts/Calculations/Bid%20Up%20To.R
Many thanks!
-Isaac
Hi Isaac
I’ll try to do this when I get some spare time. However it’s been several years since I’ve used R, so it might take a little while.
-Eirik
I will have to see if I can find the time for it. I’m a bit of an R novice and unfamiliar with the packages and data setup used here; however, I’ll see if I can’t put together a couple hours to take a stab at it.
*become optimal at a value – > have a bid up to value
Here is an example to illustrate:
Suppose the (unknown) bid up to value is 61 and the projected cost is 45.
We run the optimizer with the cost at 45. Is he in the optimal lineup? Yes. Then 45 is the lower limit.
We double the cost and try with 90. Is he in the optimal lineup? No. Then 90 is the upper limit. We now have an interval [45 90] we know contains the bid up to value.
We run the optimizer with cost (45+90)/2 = 68 (we round to nearest integer). Is he in the optimal lineup? No. Then 68 is the new upper limit. Interval is now [45 68].
We run the optimizer with cost (45+68)/2 = 57 . Is he in the optimal lineup? Yes. Then 57 is the new lower limit. Interval is now [57 68].
New cost (57+68)/2 = 63. No. Interval is now [57 63].
New cost (57+63)/2 = 60. Yes. Interval is now [60 63].
New cost (60+63)/2 = 62. No. Interval is now [60 62].
New cost (60+62)/2 = 61. Yes. Interval is now [61 62]. Length is 1. Cost is lower limit, so 61.
This took 8 optimser runs, compared to 61 with stepping up. As mentioned stepping down doesn’t really work since you need some robust upper limit in that case.
*This took 8 optimiser runs, compared to 62 with stepping up.
I’m wondering generally what the correct bid-up-to value is in an auction draft, for those who have run these calculations locally. I understand that it is different based on different scenarios, but lets assume that I’m speaking of the top 20 players. Should we bid +10% their expected cost? +5%?
Hi Adam
I can’t define bid-up-to value better than Isaac does in the post above: “The “bid up to” value is calculated by finding the highest cost up to which a player is still on the best lineup, as determined by the optimizer.”
Unfortunately there is no simple general formula like +10% to projected cost to compute the bid-up-to value. It is not very hard to calculate it using a computer, but you probably need some proficiency with programming.
This also means every player not selected by the optimizer will have a bid-up-to value lower than projected cost, because if not, they would have been selected by the optimizer by definition of bid up to value. Thus even in the top 20, most players will have a bid up to value lower than their projected cost. For example, in my last auction draft 18 of the top 20 players had a bid-up-to value lower than expected cost.
Initially 18 of 20 I should add, because the bid-up-to values change as players gets picked. For example, if I didn’t get one of those players, some other player in the top 20 would probably replace him in the optimizer, which means his bid-up-to value changed to at least his projected cost.
Should I use this to decide what keepers I should pick?
Below are players I’m considering keeping. The first price is what it would cost me to keep. The second price is from the the cost column in the optimizer.
I can pick 2 keepers.
Ap 60, 50
Odb 54, 57
Charles 48, 34
Ingram 37, 29
Martin 16, 31
Jordy 5, 35
Based on the optimizer the best keepers are Jordy and Martin. Is this right or should it be Jordy and Odb since Odb is an elite player?
Does this work well in a league where keepers allow for players to be drafted at a much lower cost?
is this built into the draft optimizer in any way, once we enter in our custom settings? can this be added as column?
https://fantasyfootballanalytics.net/2013/08/calculating-bid-up-to-values.html#comment-214
Hi team! Revisiting this: Is this “bid up to value” incorporated anywhere in the projections? I see a few values that could be that (e.g., AAV, salary) but nothing that explicitly states “bid up to value.”