Basketball GM is a single-player basketball management simulation game. Set your roster, make trades, draft prospects, manage your finances, and try to build a dynasty. Play it in your browser now, completely 100% free!
Basketball GM has long had awards every season - MVP, Rookie of the Year, etc. But Most Improved Player (MIP) has been missing for a while. That's because MIP is harder to compute than other awards. You don't need just this year's stats, you need prior years too. And you also need to understand context - is a player actually improving, or just recovered from an injury? Or maybe he's an established star coming off a bad season? Or maybe his numbers went up, but only because he got more playing time without really improving? It's complicated.
Finally, I decided to actually make a decent effort at MIP. To do that, I had to find answers to all the above questions. To do that, I tested my method on NBA data. Real NBA data was helpful because, as an NBA fan, I could easily see if the results pass the smell test or if they revealed a problem in my reasoning. For more about the data, check out the GitHub repo.
I ended up using 7 variables in my formula:
The main part of the formula is:
0.02 * (ws - ws_old) + (ws48 - ws48_old)
This is meant to roughly equally value total production (win shares) and per-minute productivity (win shares per 48 minutes). Each increase of 5 WS is equivalent to an increase of 0.1 WS/48.
However, this formula alone will not deal well with many of the tricky situations I mentioned above. For example, a player who is injured one season will have nearly 0 WS, so normal production the following season would result in a huge score. To solve these problems, I introduced a number of penalties designed to decrease the scores of players who didn't really improve.
Penalty #1: lose 0.05 for every mp/game last season under 15, and an additional 0.05 for every mp/game last season under 10. Those numbers are assuming a full season of 82 games, so players who missed games were penalized even more. This lowers the score of players who didn't play much the previous season, because otherwise it typically looks like they improved a lot in WS.
Penalty #2: lose 0.01 for every mp/game this season under 30, again assuming 82 games. This solves the problem of players who don't have much playing time this season. As sample size decreases, it's increasingly likely that good performance (high WS/48) is a fluke. I didn't want to pick a player for MIP unless they had a lot of playing time, to be sure the improvement was real.
Penalty #3: lose 0.01 for every 1% that ws is below ws_max. This prevents an established star coming off a bad season from winning.
And that's it! You could imagine many more terms in a formula like this, but I like to keep things simple and the results from this method are pretty reasonable. It never picks the same MIP as was actually selected in the NBA, but often it's better.
The winners by my formula, in order from 2005, are Amar'e Stoudemire, Boris Diaw, Luol Deng (with teammates in second and ninth), Chris Paul, Kevin Durant (two years in a row!), Derrick Rose in his MVP season, Goran Dragic, JJ Hickson, Kyle Lowry, Gordon Hayward, Kemba Walker (who also finished #2 three seasons earlier), and Rudy Gobert. Amar'e had the highest score of them all and Dragic won the weakest season.
In comparison, the NBA often picked players like Paul George in 2013 who basically just got more playing time while keeping per-minute productivity the same.
Want to see more? Well you have to go look at the code! Come up with a better formula and maybe I'll put it in the next version of Basketball GM :)