Here at Projectile, we can generate values for countless fantasy league configurations. Even so, I know that some people love the thrill of going through the process themselves, spreadsheet in hand, so that they can verify every step.
If that's you, here's a tutorial that can give you fantasy values for any league you are in.
There are just three steps to creating your own draft values or cheat sheet, no matter what the sport or scoring system.
- Convert stats to a single value.
- Adjust for position.
- Match values to salaries (if using a salary cap format)
I’ve written this guide to help you understand how values are calculated on this site. For the ambitious folks out there, you ought to be able to follow this process to calculate your own values in a spreadsheet.
Step 1: Convert stats to a single value
Good news: If your league format is based on predetermined points (like for fantasy football and for many fantasy baseball leagues), then you can skip this step. Your league’s points are already creating a common currency for the different categories.
For those of us in category leagues, we will need to find a way to put each category to the same scale. In fantasy baseball, we recognize that 30 SB aren’t the same as 30 HR. Steals are much harder to come by, so each SB is more valuable than each HR. We just need to quantify the value of each.
There are several ways to do this that you may have heard about:
- Standings Gain Points (SGP) - a method I first heard about from Art McGee's book
- Point Shares - a “cousin” of SGP developed by Rudy Gamble
- Percent Value Method (PVM) - popularized by Todd Zola
These are some clever ideas, and they all give fairly similar results. However, one downside of some of these methods is that you need to have data from previous years (either from your own league or one that is similar). This can be a big obstacle if your league is new (so there are no past results) or if it changes scoring (so that past results are no longer relevant).
The method I prefer uses z-scores, which is a common way in statistics to compare values on different scales. With z-scores, we have a tried-and-true methodology that avoids all of those problems. All that is needed is a projected pool of players. I first read about it from Tom Tango in 2007 and soon after began developing tools that could perform the calculations automatically.
To compute the z-scores for each stat, we want to subtract the stats of the average player and divide by the standard deviation for the pool of drafted players. That might sound complicated, but it is easy to do if you have a spreadsheet (and even easier here on Projectile, where the calculations are completely automated).
As an example, let’s generate values for a shallow, mixed league that uses the default Yahoo settings. In this league, there are 12 teams that each draft 10 hitters, meaning that a total of 120 hitters will be drafted for starting lineups.
Using a set of projections, let’s suppose that the average stats for those 120 players will be:
Some Extra Work for Rate Stats
However, we need to do some extra work to find the standard scores for AVG. If a player has 2 AB all year and gets 1 hit, they’ll have .500 AVG. A player who has 600 AB and manages 200 hits will have a lower batting average (.333), but this player makes a greater positive contribution to a fantasy team’s AVG than the first.
What we need to do is convert AVG from a rate stat to a counting stat. To do that, we ask, “How many more hits would this player get than the average player, given the same number of AB?” We know that the average player in this league will bat .284, so the formula for “hits above average” is:
xH = H – (AB * .284)
Consider the player above with 1 hit and 2 AB. The average player, given 2 AB will get 0.568 hits (2 * .284). Our sample player got 1 hit, or 0.432 hits above average (1 – 0.568). The formula explains how this works out:
xH = 1 – (2 * .284) = 0.432 hits above average
For the other player, the formula yields:
xH = 200 – (600 * .284) = 29.6 hits above average
That fits with what we expect–a player who bats .333 throughout the season is much more valuable than a player who hits .500 in a very small sample.
(Now, the average player by definition will get 0 hits above average. So, when it comes time to subtract out the average player, we’ll plug a 0 into our z-score formula for the average player’s “hits above average.”)
With that settled, we’ve got everything we need for our z-scores. The averages for each category:
The standard deviations for each category are easy enough to compute, as well. (In a spreadsheet, use the STDEV() function.)
With the averages and standard deviations in hand, it is now possible to compute standard scores. Let’s say we have a pretty good player who is projected for 96 R, 101 RBI, 26 HR, 19 SB, 169 H, and 549 AB.
First, let’s convert batting average to hits above average:
xH = 169 – (549 * .284) = 13.1
Then, we’ll calculate z-scores:
mH = (13.1 + 0) / 8.0 = 1.6
mR = (96 – 76.8) / 11.6 = 1.7
mRBI = (101 – 75.7) / 14.4 = 1.8
mHR = (26 – 19.5) / 6.6 = 1.0
mSB = (19 – 10.5) / 9.9 = 0.9
Total = 1.6 + 1.7 + 1.8 + 1.0 + 0.9 = 7.0
Without any context, it may not be clear if those are good values or not. But if you do the same process for all the players, you’ll find that this player has a very high value in all five categories. In fact, he probably ends up as one of the highest valued players in this league.
Also notice that, if you plug in the stats of the theoretically average player, his value in each category will be 0. So any player with a positive value for a category is above average in that category; any player with a negative value is below average.
Step 2: Adjust for position
In our previous example, we had a standard Yahoo setup with 12 teams and 9 hitters per team, for 120 total players drafted. In this league, there will be 12 players drafted at each position.
Notice that, in an auction, the last catcher drafted will go for $1, and the last 1B will also go for $1. This is true even though the last 1B is expected to produce much better stats than the last C. And that’s the key point: Despite the variance in expected production, the last players drafted at each position have the exact same value.
With this in mind, we want to adjust our values so that the last players picked at each position have equal values. In our sample league, the 12th best SS has a value of -2.97. The 12th best catcher is much worse–at -6.26. So for all of the SS, then, we will add 2.97 (i.e. subtract -2.97). For catchers we will add 6.26.
Now the final SS and final C have the same value (0), and there are exactly 11 SS and 11 C with positive values. When this adjustment is done for all of the players, there will be exactly 120 players that have a value of zero or greater.
For baseball, this adjustment has the biggest impact on catcher values, making them much more valuable than their raw stats would suggest. (The opposite effect occurs in football, where kickers receive a significant drop in value.)
The change is less dramatic for the other positions. Traditionally, middle infielders received a small increase at the expense of corner infielders and outfielders. In today’s environment there’s barely any change.
There are a couple of complications when trying to find replacement levels. The first is dealing with “flex” positions like utility, corner-infield, and middle-infield. To handle these, first mark all of the players that are above the replacement level at each of the regular positions. In our sample league, we would mark 12 players at each of the primary positions, 96 in all.
Since our sample league uses two Util spots, we need to find the next 24 unmarked players and set the Util replacement to the 24th. First will probably be a few DHs who didn’t qualify at any other position. The remaining Util spots will be filled by the best of the rest, a mix of players who qualify at various positions. For each player that is counted as a Util, that player’s value is used as the new replacement level for his primary position.
So the previous replacement level for 1B was -0.71, the value of the 12th best 1B. But with the Util position, it turns out that several more 1B are also worth drafting. The new replacement level for 1B drops to -2.07, which is the 15th best 1B.
The second issue is handling players who are eligible at more than one position. Their value should be based on the most valuable position they are eligible at. However, if I move all of the multi-positional players to the most valuable position, it makes that position less valuable (because there is more talent available). Their old positions become more valuable, because we have fewer quality players to choose from.
There’s a possibility of getting stuck moving players back and forth between positions trying to find the most valuable position.
My algorithm on this site doesn’t factor in multi-position eligibility. It simply uses a player’s “most valuable” position from this sequence: C, SS, 2B, 3B, OF, 1B. In recent years, the value differences for non-catcher positions have mostly disappeared. The only real bonus is for being catcher-eligible.
If you are doing your values by hand in Excel, you may be able to move a couple players around to get a slightly more optimal draft pool.
For a straight draft, once we have done the positional adjustments, we’re done! The players should all be ranked correctly. However, if your league uses a salary cap draft, we have one more step to come up with suggested salaries.
Step 3: Match values to salaries
The final step in figuring out player values is to convert our values into suggested salaries. The example we’ve been working with is a standard Yahoo league–12 teams, 5x5, 10 hitters and 7 pitchers. For this last step, let’s also assume that each of the 12 teams has $260 to spend on starters at the auction, with a $1 minimum bid.
Since everyone has to spend at least $1 per position, we know there will be $17 per team that is essentially reserved from bidding. That gives everyone $243 marginal dollars to work with, and the league as a whole $2916 to spend.
We also know that if we add up the value of all of the “draftable” players (i.e. those with a positive value after the positional adjustment) we have 529 units of value that will be bought at the draft. Knowing the total amount of money and the total amount of value, we can set up this formula to determine the money each player is worth:
$ = (player value / 529) * $2916 + $1
Dividing the player’s value by 529 will give us a percentage of the total value that that player represents. We multiply that percentage by the total marginal money at the auction to get that player’s percent of the money. The $1 added on the end is what we reserved as the minimum bid for each player.
In Step 1, we calculated a first round player’s value in this league at about 7 units. After the positional adjustment in Step 2, he ended up at about 9.6. Plugging that value into our formula:
$ = (9.6 / 529) * $2916 + $1 = $54
The results are what we would expect for our last players picked, too. For the replacement level player with a value of 0:
$ = (0 / 529) * $2916 + $1 = $1
So the last player goes for $1, which conforms to what actually happens at the draft.
The 70/30 Split
It’s an accepted rule of thumb in fantasy that about 70% of money should be allocated for hitting, and the remaining 30% saved for pitchers. Why didn’t I split the money up that way when I determined the dollar values above? The short answer is that I didn’t have to.
If you use this method to calculate dollar values for all of the players, you will find that 64% of the money ends up allocated to hitters, and the remaining 36% goes to pitchers. For a traditional roto league with 14 hitters and 9 pitchers (AL-only, NL-only, or mixed), the split winds up right at 70/30. The Price Guide displays at the top of the results how the money ends up being allocated between hitters and pitchers, and it is usually pretty close to what you would expect.
So don’t worry about the various explanations as to why two-thirds of the auction money goes to hitters; the split is just a function of how players are valued. The numbers confirm what fantasy players already knew, even if they haven’t understood why.
Sidenote: The Optimal Draft Pool
If you are paying close attention, you may have noticed that Step 1 of our valuation system presents a bit of a catch-22: We need to know the “draftable” pool of players (for our average and standard deviations) before we can assign z-score values. However, we need to calculate values in order to figure out the draft pool!
For points leagues, this isn’t a problem; your optimal pool is simply the set of players with the most projected points. For category leagues, however, it is unclear what combination of stats makes up the optimal pool.
My solution is to perform the valuations iteratively. Each time it processes, it feeds the top players from the previous iteration as the draft pool for the current one. It keeps going through that process until the results from a previous run are identical to the current run. At that point it has found the optimal player pool.
Even using a random assortment of 120 players on the first iteration, the cream rises quickly to the top. The second time through, the rankings look like something you could bring to a draft without embarrassment.
Each successive valuation after that is really just tweaking the draft pool–moving guys up or down a couple of slots, balancing speed and power, switching around some of the bottom of the barrel players. Within 3 to 10 iterations, it has settled on the optimal draft pool.
You can do the same thing in a spreadsheet as long as you don’t use a hard-coded value for averages or standard deviations in your formulas. You will just keep clicking the sort button until the order stops shifting.
Note that this needs to be done after Step 2 (adjust for position).
Congratulations! You've got everything you need to calculate values for your fantasy draft.
Of course, if you don't want to deal with going through this process every year for every one of your leagues, you can find values already calculated at Projectile. Start with the overall ranks and then customize with your league details.