When Genetic Algorithms met Giannis Antetokounmpo

H2H Categories Fantasy Basketball Optimization

Gerrit Hall
8 min readOct 13, 2018

Part of my series on building bots to manage my fantasy teams

Moving attention from a bad sport to a good one, basketball became a testbed for the next iteration of draft strategy.

As argued previously, the important thing with a sports draft is largely to keep to a consistent strategy. My prior efforts at punting categories had been successful, but I that a strict punting strategy may not have optimized along the Pareto frontier.

People are decent at figuring out the Pareto frontiers when reduced to two dimensions. Consider when baseball people talk about a player who can give 20–20 value of stolen bases and steals. If you think in terms of the Pareto frontier as plotted below, you see how a 20–20 could be considered roughly as valuable as a 30–0 or 0–30 player.

Anybody outside the second farthest band is gone quickly in your draft. This style plot could illustrate the impressive feat of 2018 Jose Ramirez (34 steals / 39 HR), as it falls outside the farthest boundary.

“But Gerrit!” you decry, “I think I’ve been a pretty good person. I pay my taxes, sort my recycling and don’t tell racist jokes. So why are you punishing me by talking about baseball?”

It’s a fair point, baseball is indeed the worst. But it’s a somewhat simpler math problem because there’s fewer variables. For instance, although the chart here suggests Billy Hamilton is elite, if you play fantasy you’d know he’s hot garbage. He gets his jollies striking out and draining your batting average. So you would adjust for this by adding another axis for batting average, and drawing concentric spheres instead of circles.

Unfortunately, we just hit the limits of human comprehension. You could easily imagine this boundary for three dimensions, but try to add on another axis for RBIs and it’s tougher. It’s not that big of problem for baseball, since hitting categories number around 5–7 and you can collapse them easy enough (HR correlates with RBI, strikeouts with batting average, etc.)

It is when we turn to basketball (“About Time!”) this problem really gets juicy, as the typical league considers 8–9 categories. Toss in other considerations (games per season, minutes per game, draft position), and you find yourself optimizing among 12 dimensions. No wonder so many NBA stars believe the earth is flat, it should certainly appear that way when you’re immersed in more dimensions than string theorists.

Good Genetic Material

We now have the formulation for a fun and complex math problem. How can you devise a fantasy draft strategy that optimizes along a multi-dimensional Pareto Frontier. Also, assume you procrastinated and your draft is tomorrow so you don’t have a ton of time.

Fortunately, it’s fairly easy to devise an approximate solution with incredibly simple computing techniques. Here is my recommended solution:

  1. Reduce your draft strategy to a linear combination of projections

In other words, each player’s value is a simple formula:

k1 * PTS + k2 * 3PT + k3 * REB + k4 * AST + k5 * STL

+ k6 * BLK + k7 * FGP + k8 * FTP + k9 * TOV

Now, the problem is simply to determine the optimum values for k1 — k9 that give you an edge. I threw in additional terms for Minutes per Game and Games Played. That’s it — each player gets assigned a value and this ordered list becomes the basis for everything you do on draft day.

2. Set initial values for coefficients.

When you deconstruct how other sites rank their players, you see most people already think in terms of linear combinations. Hashtag Basketball is a great resource, and their stats reduced perfectly to the following linear model I could use as a starting point:

3. Simulate a Draft

A draft will necessarily be imprecise, so adding a little noise to your simulation and running it several times actually looks to improve the fidelity of the result. The heuristic I use is just to loop between 1 and the number of teams * number of players. Every other team picks the top player as sorted by ADP * a random number (1.0–1.2 looks right to me). I draft the top available player by the formula in part 1. This allows for some of the actual variance you see in drafts without sweating over it too much.

4. Generate Season Results

This topic could get quite complex, but an advantage of keeping things rough it that we don’t need a high level of precision. For these purposes, you can do fine by taking each players’ stats, weighting by total games played, summing them up, and adding a little noise. Compare your results against every other team and arrive at a number, any number, for your win %. Run enough trials that the number is not that volatile.

5. Shuffle Your Coefficients and Try Again

You have a set of coefficients that generate a number for how well you expect you’ll do in a head-to-head season, now take each coefficient and multiply it by a random number between 4/5 and 5/4. I will run ten sets of coefficients and take the winning batch and run the process again. It doesn’t usually take many generations before you get a strategy that arrives at a 60–70% edge.

Congratulations, you have a genetic algorithm and it didn’t take more than a few lines of code! Run it for a few hours and see if the results make sense. Make any adjustments and keep going.

Results!

I’ve ran many permutations on this, and the results have been strong. Last year in my 14 team league, the algorithm suggested punting points, and I ran with a “3 and D” strategy. My team was built around Chris Paul and Draymond Green, and while they both had down years I still ended up first in the standings going into the playoffs.

I’ve tried a few other permutations this year. One version I tried to eschew the idea of using draft coefficients, and instead simply to assign a rank to players and move the rank up or down. For various reasons, I found the results unsatisfactory. So far the method seemed to hit strange equilibria (ie, boosting a 50th round player to the top of the draft) where it would get stuck, and after a few trials the algorithm would actually be producing worse results than initial. It can likely be solved by what many genetic algorithms do, which is reverting to previous states if it runs too many trials below the median. At any rate, the coefficients were working just fine, so I opted to stay with them.

One other adjustment did work very well. I encountered a lot of difficulty due to the sensitivity of the first pick. At first, I would randomize the draft order, but then I found that the balance of coefficients mattered less than the draft seed. The problem was reduced when I instead ran fourteen different trials for the fourteen possible draft positions, to generate one unified algorithm that would work no matter what the draft order. However, I realized this needed a more nuanced approach.

First Round Strategy

The final consideration worth mentioning is that basketball, more than baseball, is heavily dependent on star power. This year, I’m taking a different approach, which is to come up with 14 separate draft strategies based on the 14 possible draft positions. That is, in the first set I grab Anthony Davis first, and run the numbers to optimize the rest of my draft team from pick 27 onward. In the last set I grab Ben Simmons at pick 14, and optimize my team from pick 15 onwards (snake draft).

Here’s the strategy I’m bringing to my draft this year:

Relative weight of draft coefficients by player/pick

Essentially, the “Score” columns is the results, the remaining columns are the relative weight I assign to the various categories. The first row is the initial baseline ADP which is no better than a coin flip. Remaining rows are roughly sorted by draft order.

In other words, if I snag Giannis Antetokounmpo first, my genetic algorithm suggests that building the rest of the team on steals, blocks, and turnovers will generally get me a 70% record. If I’m in the middle rounds grabbing James, Jokic, or Dipo I might aim for assists instead. Late first round strategies looked to emphasize three point shooting.

The chart is colorful but not intuitive to interpret because it’s only showing weights relative to other strategies. If you want to derive meaning from this, you have to compare with the first line (“baseline”). For instance, rebounds looks to be quite flooded with red ink, but most of these strategies actually place double the weight of rebounds on the typical ADP weights. They just look low compared to the optimum Steph Curry strategy, which seems to be a maniacal in its emphasis on rebounds.

Indeed, the typical draft in this case would follow Curry with centers Andre Drummond, DeAndre Jordan, and Dwight Howard, followed by a smattering of guards and forwards. It seems aggressive, but it does end up with an edge on most categories.

In comparing with this very good guide on punting strategies over at RotoBaller, you’ll notice key differences. If you’re looking for an actionable draft guide, you’d be best served by deferring to the guy who is paid to do this for his living.

This aside, one thing I’d note about these differences is that the genetic algorithm results does not constitute a pure “punting” strategy, but rather a weighted draft strategy. That is, it will weight categories to the extent it will cause you to overdraft or underdraft players with certain attributes based on where they fall in the draft. As with the Steph Curry build above, the coefficients almost ignore blocks, but the strategy ends up with a large number of blocks due to the early weight on rebounds.

For further example, I’ve run two mock drafts using these strategies (placing 1st both times), using the Anthony Davis and Kevin Durant strategies. The Durant strategy might look to be punting Blocks and Rebounds, but this formula actually nabbed so many high FG% bigs that I ended up winning Blocks and Rebounds by a large margin. Similarly, the Anthony Davis strategy ended up only punting Assists, with mid-range to high values for everything else.

If you’re interested in learning more, or if you’d like some supplemental data and aren’t competing against me in a league, please email me at gbball@onymail.com. Also, if you’d like to help in this season’s basketball project, please join http://beeballer.com/

--

--