{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
Peter Norvig
\n", "\n", "# WWW: Who Will Win?\n", "\n", "This is a notebook for reasoning about who will win playoff series in basketball (and could be used for other sports). The table of contents for this notebook:\n", "\n", "* [Model Discussion](#Models:-Introduction-and-Discussion) What model should I use to make predictions?\n", "* [2019 NBA Playoffs](#2019-NBA-Playoffs) **Will be updated as the playoffs progress.**\n", "* [2018 NBA Playoffs](#2018-NBA-Playoffs) An exciting season.\n", "* [2016 NBA Playoffs](#2016-NBA-Playoffs) Ancient history; sad saga.\n", "\n", "---\n", "\n", "# Models: Introduction and Discussion\n", "\n", "\"It's tough to make predictions, especially [about](https://en.wikiquote.org/wiki/Yogi_Berra) [the](https://en.wikiquote.org/wiki/Niels_Bohr) future.\" That's true for the NBA basketball playoffs, where there is a wide range of opinions. Here are some models you might choose to help you make predictions:\n", "\n", "1. **Holistic**: I just feel that my favorite team has about a 1 in 5 chance of winning it all.\n", "2. **Game by Game**: I think my team has a 75% chance of winning each game in the first round, then 65% for each game in the second round, but only 45% in the Conference finals, then 55% if they make it to the NBA finals. From that I'll calculate their overall chance.\n", "3. **Point by Point**: My team has a per-game average point differential of +5.79; I'll compare that to the other teams and calculate overall chances.\n", "4. **Play by Play**: Use [detailed statistics](https://www.basketball-reference.com/play-index/plus/shot_finder.cgi) and overhead video to [model](https://danvatterott.com/blog/2016/06/16/creating-videos-of-nba-action-with-sportsvu-data/) the game shot-by-shot, or even pass-by-pass. Not covered here.\n", "\n", "# Point by Point Model\n", "\n", "The **[Simple Rating System](https://www.sportingcharts.com/dictionary/nba/simple-rating-system-statistics.aspx) (SRS)** records the average point differential of a team over the season, with a slight adjustment for strength of schedule (see [basketball-reference.com](https://www.basketball-reference.com/leagues/NBA_2018.html)) . A great team has an SRS around 10; anything over 5 is very good.\n", "\n", "The Point-by-Point model says: a game is decided by a random sample from the distribution of point differentials, which is a normal (Gaussian) distribution centered around the difference of SRS scores of the two teams. So, if a team with an SRS of 7 plays an opponent with an SRS of 4, we can expect the team to win by 3, on average, but it will still lose some games. We need to know the standard deviation of the distribution to determine how often that happens; [Betlabs](https://www.betlabssports.com/blog/a-look-at-nba-team-totals/) says the standard deviation \n", "is 10.5 points across the NBA. \n", "The function `win_game` does the calculation of win probability given an SRS point differential, using Monte Carlo simulation:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "from statistics import mean\n", "from random import gauss\n", "from collections import Counter\n", "\n", "def win_game(srs_diff, 𝝈=10.5, n=100000):\n", " \"Given SRS point differential of a team against another, return game win probability.\"\n", " return mean(gauss(srs_diff, 𝝈) > 0 for game in range(n))" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.61201" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "win_game(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, if your team has a 3-point edge over an opponent, this model predicts your team will win 61% of the time." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "# Game by Game Model\n", "\n", "The next model says that a playoff series is a sequence of independent and identically distributed game results (where the probability of a single-game win could be specified using SRS, or holistically, or some other model). The idea here is to be consistent: if you believe that a team's win percentage is 60%, and you believe that games are independent, then you must believe that the team's chance of wining 4 in a row is 0.64 = 0.1296. This model ignores the fact that games aren't strictly independent, ignores the possibility of injuries, and ignores home court advantage. Why? Because these factors would change the final winning estimate by only a few percentage points, and I already have more uncertainty than that.\n", "\n", "The function `win_series` calculates the probability of winning a series, given the probability of winning a game:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def win_series(p, W=0, L=0):\n", " \"\"\"Probability of winning best-of-7 series, given a probability p of winning a game.\n", " The optional arguments say how many Wins and Losses the team has in the series so far.\"\"\"\n", " return (1 if W == 4 else\n", " 0 if L == 4 else\n", " p * win_series(p, W + 1, L) + \n", " (1 - p) * win_series(p, W, L + 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can make a table:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 point differential = 50% win game = 50% win series\n", "1 point differential = 54% win game = 58% win series\n", "2 point differential = 57% win game = 66% win series\n", "3 point differential = 61% win game = 73% win series\n", "4 point differential = 65% win game = 80% win series\n", "5 point differential = 68% win game = 85% win series\n", "6 point differential = 72% win game = 89% win series\n", "7 point differential = 75% win game = 93% win series\n", "8 point differential = 77% win game = 95% win series\n", "9 point differential = 80% win game = 97% win series\n" ] } ], "source": [ "for srs_diff in range(10):\n", " g = win_game(srs_diff)\n", " print('{} point differential = {:4.0%} win game = {:4.0%} win series'.format(\n", " srs_diff, g, win_series(g)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With a zero point differential obviously you're at 50% win percententage; with a 3 point differential you're at 61% to win a game, and 73% to win the series. This agrees very well with the \"Differential vs. Win Percentage\" [chart](http://a.espncdn.com/combiner/i?img=%2Fphoto%2F2018%2F0408%2F180408_differential.png&w=1140&cquality=40) on [this page](http://www.espn.com/nba/story/_/id/23071005/kevin-pelton-weekly-mailbag-including-nba-all-offensive-teams). \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "We can also do plots:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "diff = [d/10 for d in range(101)]\n", "game = [win_game(d) for d in diff]\n", "series = [win_series(p) for p in game]" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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OQsR6N+mPk9f0Y2uTSPtDtUnaIJwg7S0NCZNmsTy5cupV68egYGBPPLII1x55ZU1cvw+ffowY8YMevfuTVlZGXXr1mXatGmMGjUKsOo0vf3226SkpLBlyxYmT55cI3EpdTKZ+SV8lpjC7JXJJB3J/9173ZtFMvGCDlzYJZruzSK9fnBabaIJopqJCKNHj2b8+PHMmjULgH379vHll1/WWAzHSn337t2b9evX07FjRxISEhg1ahT5+fns3r2bXr160bdvX0aOHFljcSl1zO70PN5YtIs9GfkcPFrI4dxiRCCuVT3uGdqOLjGR1AuzylqHBJ55UU1VPXQ4bTVbtGgRgYGBv5vToVWrVkyYMAGAvXv3cu6559K3b1/69u1LQkICYA16Of/88xk1ahRt27Zl8uTJfPzxx/Tv358ePXqwe/duANLT07n66qvp168f/fr149dff/1DDIMHDz6+34SEBO6+++7j9ZxWrlxJbGws/v7+vP/++9x///0A3HLLLUycOJHBgwfTtm1b5s2b575fkvJZIsKHy/fxp9eW8MOWNEID/TmvQyMmXdiRhQ+ex7x7BnNtXAu6N4uiWd0QTQ428+4riG8nw6GNlb4VUl4G/lU4/SY94NIpJ3178+bN9O3b96TvN27cmB9++IHg4GB27tzJ9ddff7zM9/r169m6dSv169enbdu23HHHHaxcuZJXX32V119/nVdeeYUHHniASZMmcc4555CcnMzFF1/M1q1bf3eMIUOG8OSTTwJWgnjqqaeYPXs2ubm5JCQknLTUd2pqKkuXLmXbtm2MHDmSa6655kx/O0pVqqzcwco9mbz1SxI/70jn3A4NeenaXkRHBtsdmjoF704QtcB9993H0qVLCQwMZNWqVZSWlnL//fezbt06/P392bFjx/F1+/Xrd7wEeLt27RgxYgQAPXr0YPHixQD8+OOPbNmy5fg2OTk55OXlER7+W3/vVq1aUVJSwqFDh9i2bRudOnWiX79+rF69moSEhONXMycaPXo0fn5+dO3albS0tGr/XSjfciSvmITdGfy8PZ2ftqVxtKCU0EB/nhnZjXGDWmlbggfw7gRxim/6hW6qxdStWzc+++yz46/feOMNjhw5cnxaz//85z9ER0ezfv16HA4HwcG/fYOqWGrbz8/v+Gs/P7/jZbcdDgfLly//3XaVGTx4MHPnziUmJgZjDAMHDmT58uWsXLmSQYMGVbpNxeN7co0uZY9D2UWs2pvJqr2ZrNyTybZDuQBEBgcwvEs0F3drwvkdG+ltIw+ibRDV7IILLqCoqIg333zz+LKCgoLjz7Ozs4mJicHPz48PP/yQ8vLyM9r/iBEjeP3114+/rmyuCLASxCuvvHI8GQwaNIjZs2fTpEkToqKizuiYSp2MiPDLjnRufGc5A//1ExNmr2VeYgoNw4P468Wd+N99Q1jzt4v4z3W9uaR7E00OHsa7ryBsYIzhf//7H5MmTeKFF16gUaNGhIWF8e9//xuAe++9l6uvvpoPPviASy65pNKJgk7ltdde47777qNnz56UlZVx3nnnMW3atD+sN2TIECZNmnQ8QcTExOBwOE7a/qCUq0SE7Wm5LNlxhC/WHmBLag6NI6yEcF6HRnSJiSDAiybN8WVa7tuHaLlv3+Cucy53CDN+3cP0X5I4nGtNfdu5SQS3DWnDqD5NCQqw7+pA/85nRst9K6Wqzb6MfP4ydz2r9mZxboeG/GVEJ87t2JCYqBC7Q1NupAlCKfUHMxP28tHyfQQG+BFSx58tqTn4+xleHtOLK/s00x5IPsIrE4SI6D9gN/HkW5LKNfPXHeCpLzfTq0VdGoYFUlhazkVdo5l8aWe9YvAxXpcggoODycjIoEGDBpokqpmIkJGRcdoutspzrdyTyV/nbqB/m/p8eHt/W9sVlP28LkE0b96clJQU0tPTT7leUVGRz33QVcc5BwcH07x582qKSNkpLaeID5btZe+RAprVC6FJZDCvLdpJ8/ohTL85VpOD8r4EUadOHdq0aXPa9eLj4+nTp08NRFR7+OI5qz/acjCHd5Yk8dWGg5Q7hBb1Q/lhaxolZQ4ahgcy45Z+1A3VCXeUTQnCGPMA8GfAAG+LyCvGmPrAJ0BrYC8wRkSy7IhPKW8jIsTvSOedJUn8uiuD0EB/bhzQituGtKFlg1AcDuFIXjHhwQGEBnrd90ZVRTX+L8EY0x0rOfQHSoDvjDELgDuBn0RkijFmMjAZeLSm41PK2xzOLeLej9awel8W0ZFBTL60M9f3a0lUaJ3j6/j5GRpr4Tx1Aju+KnQBVohIAYAx5mfgKmAUMNS5zkwgHk0QSp2V9fuPcteHiWQXljLlqh5c1bc5gQE6ylm5psZHUhtjugDzgUFAIfATsBq4WUTqOtcxQNax1ydsfyfW1QbR0dGxc+bMqVIcJ1ZA9QV6zr7h2Dn/eqCUGZtLqBtkmNgniJaR3tvo7Mt/56oYNmyYSyOpbSm1YYy5HbgXyAc2A8XALRUTgjEmS0TqnWo/lZXacJUOzfcNvnjO3/+0mMXZDZm9MpmBbesz9cZY6od5d6OzL/6dvbbUhoi8C7wLYIz5J5ACpBljYkQk1RgTAxy2IzalPNneI/n8Y3kRybnJ3DO0HQ9f1FEL56kqs6sXU2MROWyMaYnV/jAQaAOMB6Y4H+fbEZtSnigrv4Sp8buYuWwfdYyDd8fHMbxLtN1hKQ9nV3+2z4wxDYBS4D4ROWqMmQJ86rz9tA8YY1NsSnmMsnIH7yzdwxuLdpFfUsaVfZozOCJDk4OqFnbdYjq3kmUZwHAbwlHKI+3LyGfSJ+tYk3yUC7s05pFLOtMxOoL4+Hi7Q1NeQkfEKOUhNh3IJulIPoUlZaTlFPPWz7vx8zO8OrY3o3o3szs85YU0QShVy5WVO3j5hx1Mjd/9u+WD2zXgxWt70ayuVlhV7qEJQqla7EheMRNnryVhdwZj+7Xg9nPaEBoUQFigP1EhdbRisXIrTRBK1TJl5Q5W7Mnkm42pfLMxlYKScl64pidj4lrYHZryMZoglKpFtqbmcPv7qziYXURIHX8u6NyYe4e1o1vTKLtDUz5IE4RStcTa5CzGv7eS0MAApt7Yl2GdGhMS6L3lMVTtpwlCqVpg2e4M7pi5igbhQXx8xwBa1A+1OySlNEEoZYeCkjLe+jmJDSlH2X4ol4PZRXRoHM5HdwwgWstuq1pCE4RSNSwtp4jbZ65i88EcOjeJpH+b+nRqEsnYfi2o5+VF9ZRn0QShVA3adCCbO2auJreolPfG92NY58Z2h6TUSWmCUKoGOBzCrJXJPP/1VuqF1mHePYPpEhNpd1hKnZImCKXcbH9mAY9+toGE3Rmc074hL4/ppdN7Ko+gCUIpN0lKz+ODZfv4ZNV+/P0M/7qqB2P7tdDRz8pjaIJQqpqlZhfyxBebWLTtMHX8DVf0bMrDF3fSmknK42iCUKoaHThayPXTl5OZX8KDF3bghgEtaRyht5OUZ9IEoVQ12Z9ZwPVvLye7sJSP7hhA7xZ1T7+RUrWYJgilzoKIsC+jgKW7jvBm/G7yisuYdcdAejTX2knK82mCUKqK1u8/yoTZa0nOLACgVYNQPr5jAN2baXJQ3kEThFJVUFRazkOfrqO03MFzo7oxpH1D2jQM0x5KyqtoglCqCqYu3sXu9Hxm3taf8zs2sjscpdzCz+4AlPI02w7lMDV+N1f1aabJQXk1TRBKnYGycgeTP9tIZEgdnry8q93hKOVWLt1iMsacA3QQkRnGmEZAuIjscW9oStlPRPhk1X5mLttHem4RmfklOAReHdub+lp5VdlBBLL2EFCa4/ZDnTZBGGOeAuKATsAMoA7wETDEvaEpZa+colIe/3wjCzak0qt5FBd1jaZheBCdmkTwpx4xdoenfIUIHNoAOxbC/pVwIBEKM2nU8R5gpFsP7coVxJVAH2ANgIgcNMZEuDUqpWy26UA29368hgNHC/nrxZ245/x2+PlpDyVVg9K3w+oZsG0BZO8HDDTuAp3/BM1iyUp3/6yDriSIEhERY4wAGGPC3ByTUraav+4Aj8zbQIOwQD65cyBxrevbHZLyFQ4HJC2G5VNh14/gHwTth8PQydDxEghreHzVovh4t4fjSoL41BjzFlDXGPNn4DbgbfeGpVTNK3cILyzcxls/J9G/dX2m3tSXhuFBdoelfEFhFqybDavfhYxdEB4Nw56EuFt/lxRq2mkThIi8ZIy5CMjBaof4u4j84PbIlKpB2w/l8vgXG0ncl8VNA1vy98u7ERignfyUm+WkQsJr1q2kskJoMQDOewS6jYYA+7+cuNSLyZkQNCkor1NYUs7ri3Yy/ZckIoID+M91vbiyT3O7w1LeqCgHdv8ExblQWgTpW2Htx+Aog57XwcB7IKan3VH+jiu9mHIBOWFxNrAaeFhEktwRmFLuVFRazscrkpn2827Sc4u5um9znvhTF+26qqpfcR6snG5dKRRm/bbcLwB63wDnPAT129gX3ym4cgXxCpACzAIMMBZoh9Wr6T1gqLuCU8odvtuUypP/28yRvGIGtq3PGzf0pX8bbYhW1UAE1n4EGz6B8hJwlENmEhRmQocRcM4kiGoBdUIhMAzq1O65QlxJECNFpFeF19ONMetE5FFjzOPuCkwpd1i2O4MJs9fSJSaSN27ow4C2DewOSXmLI7tgwYOwdwk06gLhjcHPH9oNgwF3Q4v+dkd4xlxJEAXGmDHAPOfra4Ai5/MTbz25xBgzCbjDuf1G4FYgBpgDNAASgZtFpKQq+1eqMrsO53LXh6tp3SCMD28fQFRIHbtDUp5MBNK3wd6lsO9X2PYNBATDFa9Cn3Hg5/mdHFxJEDcCrwJTsT7QlwM3GWNCgPvP9IDGmGbARKCriBQaYz7Fum11GfAfEZljjJkG3A68eab7V6oyR/KKufX9VQQG+PPeLf00OaiqO94l9T3I2Gkti2wGvcbCsCcgItre+KqRK91ck4ArTvL20rM4bogxphQIBVKBC4AbnO/PBJ5GE4SqBqnZhdzy3irSc4v55M5BtKjv/hGoyouUFsKhjbAvAZKXQVI8lBVB835w+SvQdijUaw1eOBeIK72YgrG+zXcDjreoiMhtVTmgiBwwxrwEJAOFwPdYt5SOikiZc7UUoFlV9q9URftzHUx+I4G84jLeHd+PXjpPtDodEWvA2qYvrAbm3IO/vdegA/S5GfqOq3VdUt3BiJy6GcEYMxfYhvXt/lmsW05bReSBKh3QmHrAZ8B1wFFgLlb7xtMi0t65TgvgWxHpXsn2dwJ3AkRHR8fOmTOnKmGQl5dHeHh4lbb1VL52zuvTy3hzXRHBAX48FBtEy0h/u0OqEb72d4bqO+eA0jw6bX+NRkdWkBvehvywNhSGxJAf1oLsqC6UBtaeLxhnc87Dhg1LFJG4064oIqf8AdY6Hzc4H+sAy0+33Sn2dy3wboXX47BuJR0BApzLBgELT7ev2NhYqarFixdXeVtP5SvnvDU1W8a9u0JaPbpABj/3taRkFdgdUo3ylb9zRdVyzskrRP7TXeSZ+iK/vi7icJz9Pt3obM4ZWC0ufF670khd6nw8aozpDhwCGruaqSqRDAw0xoRi3WIajjXobjFWD6k5wHhg/lkcQ/mgjLxiXly4nU9X7yc8KIAnLutCq9J9NKsbYndoqjbLPgA/PQsb5lhjFG79Dlr0szuqWsGVBDHdeVvoSeBLIBz4W1UPKCIrjDHzsAbalQFrgenA18AcY8w/nMvereoxlG8pdwgfr9jHSwu3U1BSzq1D2jDhgvbUDQ0kPj7Z7vBUbVJWDNu/hcNbrd5IBRmw/RtrQNs5D8G5D0GQzmZwjCsJ4icRyQJ+AdoCGGPOaly4iDwFPHXC4iTA80aSKFuVO4Tx761k6a4jDG7XgGdGdqNDtP4HVxWUl1kT7mycB+tnW6OaAYIiIaQudLoMhv/N6omkfseVBPEZ0PeEZfOA2OoPR6kz899Fu1i66wjPjOzGuEGtMF7Y1VBVQXkprHrHulpIWQ2l+eBXx5psp+84aHM++LtUq9SnnfQ3ZIzpjNW1NcoYc1WFtyKp0N1VKbus3pvJqz/tYHTvpowf3NrucFRtkZIIX02EtE0Q3d0qiNdyoDVewca5FTzRqVJoJ+ByoC6/HyiXC/zZnUEpdTrZhaU8MGcdzeuF8tzoP/SGVj4moDQPti6AHd9aJbQjYmDsLOuKQVXZSROEiMwH5htjBonIshqMSalKHTxayMo9mexIy2XJziOk5RQx9+5BRARr2Qyfk5Nq1UBKWQn7VzIkdQPggIAQ6HcHDP87BEfaHaXHc+Um3C5n1dbWFdeXKo6kVqoqNqZkc/3by8krLiPAz9CmYRj/vLIHfVrWszs0VZNEIPF9+PYRq5x2nTBo1pd9rcbQ+oLx0CwOAnROj+riSoKYDywBfgTK3RuOUn+UlJ7HLTNWEhVShzl3DqRjdIROB+qLSgrg64dh/SxoNxwufAoadwP/APbGx9O61WC7I/Q6riSIUBF51O2RKFWJQ9lF3PzuSgA+vL0/bRv5VgkJBRRlw6bPYfmbcGQHnD8Zzn/EmmtBuZUrCWKBMeYyEfnG7dEohTW2YW1yFj9sSWP+uoPkFZcx+88DNTn4gvIy2PUjZO2F3FTI2gM7voeyQmsSnhvnQoeL7I7SZ7iSIB4AHjfGlAAlWNOOiohoC5CqdtmFpVz9ZgK7DudRx98wqF1DHhjenh7No+wOTblTeSmsnwNLXrKSA1jjFiKaQO/roc9N0LSvV5bUrs1cmQ9Ch6WqGvPMl5vZcySfF67uySU9mhCpPZS8U1mxNW/z4W1WSe3UddYVQ0xvuO5jaDkIQup5xaxsnsyV+SAMVonvNiLynLMUd4yIrHR7dMqnfLMxlc/XHmDi8A6M6dfC7nCUu+SmwSc3WV1UA0KgfltrvubeN1m3j/QqodZw5RbTVMCBNePbc0Ae8Aag5Q5VtTmcU8TjX2ykZ/MoJlzQ3u5wlLscSIQ5N0HRUbhmBnS7UhNCLeZKghggIn2NMWsBRCTLGKMdjVW1ySsu4+G56yksKeflMb2p46+3FbxKeRnsiYcNc2HzFxAeDbd/D0162B2ZOg2X5oMwxvgDAmCMaYR1RaHUWVu0LY0nv9hEak4Rz4/uQfvG2lPJKxTlWHM37/wediyE/MMQFGU1OF/wN62J5CFcSRCvAV8AjY0xz2NN6vOkW6NSXq+4rJxH5m1g/rqDdGgczry7BxHbqr7dYamqKi+D5ATY84v1cyARHGVWSe12F0D3q6HDCKijdT49iSu9mD42xiRizfxmgNEistXtkSmv5XAID326nq83pPLA8A7cN6y9joz2VOVlsPFT+OUlyNwNxg+a9oHBE6D9RVbjs7/2RPNUrvRiGghsFpE3nK8jjTEDRGSF26NTXkdEeHbBFr7ekMrjl3XmzvPa2R2SOlOOcji4Fnb+YE3TmbXXak+4+l2rF1KwjlnxFq7cYnqT308YlFfJMqVc8tYvSbyfsJfbz2nDn89ta3c46kw4yiHhNfj1NeeSe6ZWAAAefUlEQVSsbMYar3DJFOh4ifZG8kKuJAgjInLshYg4jDE6FZM6Y6v3ZjLl222M7NWUJy7rorO/eZKM3fDF3dbYhQ4XQ88xVttCqLYbeTNXPuiTjDETsa4aAO7Fmj9aKZc5HMLTX22mSWQwU67ugZ+fJodabdlUSJwBAUFQJxQObbTaEq56B3pco1cLPsKVlsG7gcHAASAFGADc6c6glPeZm7ifTQdyeOyyzoQG6gVorbbmA1j4mNUDKaoF1AmBLlfAvcuh57WaHHzIKf+nOsc/3CgiY2soHuWFcopKeXHhduJa1WNkr6Z2h6NOZft38NWD1nwLN3yiPZB83CkThIiUG2OuB/5TQ/EoL/T6TzvJyC9hxi39td2hthCB/Stg1btWsbyo5tY8zonvWz2SxnygyUG51AbxqzHmv8AnQP6xhSKyxm1RKY92OKeI577eyp4jeaTlFJOeW8x1cS20ZHdtUJwHG+daiSFto3UbKaYXpG2CHd9B/XbWnAtBOqJduZYgejsfn62wTLCK9yn1O9kFpYx7byX7MgoY2LY+3ZtG0bxeCOMHt7Y7NN+WsduakW39HCjJhejucPkrVm+kwDBrnWOdFfUqTzm5MpJ6WE0EojxfQUkZt76/kqT0fN67pR/ndNB6O7YTgdXvwsInrOfdRkPc7dYI5xMTgSYGdQJXRlJHA/8EmorIpcaYrsAgEXnX7dEpj3Eou4hHPtvAuv1HeeOGvpocaoP8DPhyAmz/2mp0Hj3VmqFNKRe5covpfWAG8ITz9Q6s9ghNED7O4RC+2nCQeYkpLN11BIB/XdmDS3vE2ByZYsuX8PXD1rwLF/8LBtyts7OpM+ZKgmgoIp8aYx4DEJEyY0y5m+NSHmDKd9uY/ksSzeuFMOGCDlzVpxmtG4bZHZZvy02j26YpcGSZ1Rvpps8gpqfdUSkP5UqCyDfGNOC3+SAGAtlujUrVenNX72f6L0ncPLAVz4zspiOj7ZaxG5ZPhXWzaFBWCsP/DoMnaldVdVZcSRAPA18C7YwxvwKNsOaEUD5q9d5MHv9iI+e0b8hTV3TV5GCnjN3w41OwdYGVDHqMYVXgYAace6PdkSkv4EovpkRjzPlAJ6z5ILaLSKnbI1O10oGjhdz1YSLN64Xyxg19CdDpQWueCBRmwZL/gxVvWfWSzn0Y+t8JEdEUxsfbHaHyEidNEMaYDsBLQDtgI/AXETlwtgc0xnTCauQ+pi3wd+AD5/LWwF5gjIhkne3xVPUpK3fwwOy1FJc5eGd8HFGhevuixuz8Eb5/ErL2QFmRc6GBPjdaU3hq7yTlBqe6gngP60P7F2Ak8Dpw1dkeUES24xx856z1dABrStPJwE8iMsUYM9n5+tGzPZ6qPq8t2sXqfVm8OrY37RrpSNsakXMQvpsMW+ZDgw7Q/88QEGJN3dn+QmsUtFJucqoEESEibzufv2iMcUdpjeHAbhHZZ4wZBQx1Lp8JxKMJotZYnpTBfxft5JrY5ozq3czucLxb8grYuRD2LLHmdvavAxc8aTU6BwTZHZ3yIadKEMHGmD5Y7Q4AIRVfV1MtprHAbOfzaBFJdT4/BERXw/5VNcjKL+HBOeto1SCMZ0Z2szsc71VSYF0trJkJxh+axcI5D0Kfm6F+G7ujUz7IVJgs7vdvGLP4FNuJiJxVLSZjTCBwEOgmImnGmKMiUrfC+1kiUq+S7e7EOR9FdHR07Jw5c6p0/Ly8PMLDfes2SVXP+f1NxSw5UMbfBgbTOsrfDZG5j0f8nUUIz9tDl63/R2jBAZJbXkVyy2soDwit0u484pyrmZ7zmRk2bFiiiMSddkURseUHGAV8X+H1diDG+TwGq7fUKfcRGxsrVbV48eIqb+upqnLOmw4cldaTF8gzX26u/oBqQK39O6dtFZl7q8jUwSL/bC7yVKTIix1Fdi8+613X2nN2Iz3nMwOsFhc+p+2c2ut6fru9BNZYi/HAFOfjfDuCUr8REZ75agv1QgN5YHgHu8PxDqVFsOQlWPoKBIZCy0HQaoh1C6nHGAhrYHeESh1nS4IwxoQBFwF3VVg8BfjUGHM7sA8YY0ds6jffbDzEyj2ZPH9ld+3SerbKy2DTZ/DzFGuCnp5j4eLnIUyLGqray5YEISL5QIMTlmVg9WpStUBWfgn//GYrXWIiGduvpd3heK6CTNj8Bfz6KhzdB427ws3/g3ZaRV/Vfi4lCGNMM6BVxfVF5Bd3BaXssW7/UaZ8u5Vdh/M5klcMwP+N6YW/ltI4MyUFsOYD2LYA9iWAlFs9ki6ZAh0v0aqqymO4Mh/Ev4HrgC3AsSqugjWATnmJzPwS7vpwNQAXdG5Eu0bhxLWuR2yr+jZH5mFSVsMXd0HGLmjUxeqm2ulP0KyvTsijPI4rVxCjgU4iUuzuYJQ9RIS/zF1PVn4pX9w3mG5Nde7oM+JwWCUw1s2CpS9DRFMYNx/aDrU7MqXOiisJIgmoA2iC8FLv/bqXRdsO8/QVXTU5nImURPj+CUjdAKX51rJeN8ClUyBYf4/K87mSIAqAdcaYn6iQJERkotuiUjUmcV8WU77dyoVdohk/uLXd4XiO1A3w0ZUQGA59boIm3aFpX+tRKS/hSoL40vmjvMx3mw4x6ZN1NIkK5sVremL0Hrlr0rfDh1dCYATc9i3U1V5eyju5Mh/EzJoIRNUcEeGtX5L493fb6NW8Lm+Pi6NeWKDdYdVeuYdg149QeBSKc521kvysdgZNDsqLnWo+iE9FZIwxZiPO6UYrEhGd6NZDvbhwO1Pjd3N5zxheurYXwXU8q75SjcnaZ41fWPsRlFdogqvbCm6aDQ3b2xebUjXgVFcQDzgfL6+JQFTN+Gr9QabG7+b6/i14fnQPnS60Mkf3w8//tnol+flD7xug/10Q2RSCIqxlSvmAUyWI64wxCcAaESmrqYCU+yTnlPOvnzYQ16oez4zsrsnhRNkHIOE1WP2e9brfHdY4hsim9sallE1OlSCaA68AnZ23mX4FEoAEEcmsieDU2Sl3CClZBZQ5hMKScl5fW0xkSCBTb+pLYICO5gWsGkm7foTE961Jeo5N43neI1C3hd3RKWWrkyYIEfkLHJ+3IQ4YDNwKTHfO3dC1ZkJUVZFbVMotM1aRuO+3ab0DDMy9NZbGEcE2RlYLlBZZSWHb17DjOyjMhLDGMORBiB0P9VrbHaFStYIr3VxDgEggyvlzENjozqDU2ckpKmXcuyvZdCCbxy7tTJOoYPz9DNn7ttGn5R/mYPItB9fCZ3dYpTCC60LHi6HLSOvRXyvWKlXRqXoxTQe6AbnACqzbSy+LSNbJtlH2yy4sZdx7K9lyMJupN/ZlRLcmx9+Lz9xhY2Q2czis9oVF/4CwRjB2NnS4SJOCUqdwqiuIlkAQsBM4AKQAR2siKFV1kz5Z50wOsVzUVaf1BmDvUvjhKTiw2rpauOJVCNUihEqdzqnaIC4x1tDabljtDw8D3Y0xmcAyEXmqhmJULvp5RzqLth3m8cs6a3JwOCBlJT02PAvxiVYBvdHToNdYraqqlItO2QbhnLt0kzHmKJDt/Lkc6A9ogqhFysodPP/1Flo1CPXdmkrOpMDmL2DLl5B7kMiAMLjwGRhwF9QJsTtCpTzKqdogJmJdOQwGSnF2cQXeQxupa505q/azIy2PaTf1JSjAxwZyZSZZE/Rs/Ayyk8E/yGpf6PoMyw+Hc+45l9kdoVIe6VRXEK2BucAkEUmtmXBUVeQUlfKfH3YwoE19Lq7QKO0TNn0O8++DsmJodwFc8CR0vswa8QyUx8fbG59SHuxUbRAP1WQgqur+u2gXmQUl/O3yrr5TkdVRbvVIWvoytBgA18yAqGZ2R6WUV3FpTmpVe207lMN7S/dwbWxzujfz4klqystg3UfWOIbcNOu20pHt0Hc8XPYiBATZHaFSXkcThAdzOITHP99IZEgdHru0i93huM+BRPjqATi0EUIbQkSMVQZjyERrsh6llFtogvBgs1clsyb5KP93bS/vms+hKAcObYC0LZCyCjbOhYgmcO1M6DpKu6kqVUM0QXiow7lFTPl2G4PaNuCqvl507337d/D5n6E4x3odHGV1UR32BARH2hubUj5GE4QHyi0q5eFP11Nc6uD5K7t7R8O0wwFL/g8WPw9NesAFf7Pmd46I0SsGpWyiCcLD7EjL5e4PE9mXWcDzo7vTtlG43SGdHUc57PkFlr9pldvuMcYqhREYandkSvk8TRAe5NuNqTz06XrCggKYdccABrRtYHdIVVeQaV0xbJwLeWkQGAEjnodB9+kVg1K1hCYID7F4+2Hun72WXs2jePOmWKIjPXROB4fD6q76w1NQlA2dLoUe11rltrUUhlK1iiYID7B+/1Hu/WgNnZtE8MHtAwgP8tA/W24afDoO9i+HloPgspesdgalVK3koZ80vmNfRj63vb+KBuGBzLi1n+cmh8w98OFoyEuH0W9Cr+v1VpJStZyHftr4hsR9mdw/ay0OEWbe1t9zpwo9tAk+ugrKS2D8V9A81u6IlFIu0ARRCzkcwttLknhh4Xaa1Q3h7XFxtPOk3ko7f4Bl/7WuFopzIe+QNQL6toXQqJPd0SmlXGRLgjDG1AXeAboDAtwGbAc+waoiuxcY44vTmzocwn2z1vDtpkNc1qMJU67uSWSwh0yLeXgrLHwCdv8EdVtCk54QFGnN3jbgbqs8hlLKY9h1BfEq8J2IXGOMCQRCgceBn0RkijFmMjAZeNSm+Gzz7tI9fLvpEH+9uBP3Dm1XuwfBFWRa8zAcXAOp6yFrLwRFWd1V+98JAV5U/kMpH1TjCcIYEwWcB9wCICIlQIkxZhQw1LnaTCAeH0sQmw5k88LCbVzcLbp2JwcR2PApLHwcCo5AvdYQ0wtib4E+4yDMg8dnKKWOs+MKog2QDswwxvQCEoEHgOgKExMdAnxqUuXCknIemLOW+mGBTLmqZ+1NDln74KuJkBQPzeJg3P+s0hhKKa9jrGmna/CAxsQBy4EhIrLCGPMqkANMEJG6FdbLEpF6lWx/J3AnQHR0dOycOXOqFEdeXh7h4bWj4bfMIby/uYSlB8p4pF8wXRu4Z8rQszpnEaLT4umw8y0AktqO52DTEWBq9/SmtenvXFP0nH3D2ZzzsGHDEkUk7rQrikiN/gBNgL0VXp8LfI3VSB3jXBYDbD/dvmJjY6WqFi9eXOVtq9PibWky7MXF0urRBfLCd1vde6yqnnPhUZFPx4s8FSny7iUimXurMyy3qi1/55qk5+wbzuacgdXiwud1jd9iEpFDxpj9xphOIrIdGA5scf6MB6Y4H+fXdGw1qdwhPDBnLQs2pNKmYRgzbu3HsE6N7Q7rj7JT4KNrIGMnDP87DHkQ/Gr3VYNSqnrY1YtpAvCxswdTEnAr4Ad8aoy5HdgHjLEpthoxZ1UyCzakcv+w9kwY3p6ggFr4oZu6AWaNgZJ8uOkzaDvU7oiUUjXIlgQhIuuAyu5/Da/pWOxwJK+Yf3+7jYFt6/PwiI61p0E6fQdsmAP56VYX1qR4a8Ke276D6G52R6eUqmE6ktoG//xmK4Wl5fxjdC2Z7MfhgOVT4adnwVEGYQ0htIF1xXDZixDZ1O4IlVI20ARRw5YnZfD5mgPcO7Qd7RtH2B2OdRvpu8mw71fodBlc/gpE+FQPY6XUSWiCcLPM/BIuf20J+SXl1AutQ3ZhKc3qhjDhgg72BVVWAlu/hJXTYf8KqxyGVlhVSp1AE4SbvRm/i0M5RYzt35LcojJyCku5+/x2hATa1Ci9Zwl8/RAc2QH128LF/4TeN0DIH4acKKV8nCYIN0rLKeKDZfsY3acZ/7zShtHGeYfh0AarNIY46Lx1KsTHQ91WMHYWdLwU/PxqPi6llEfQBOFGry/aSblDeHB4x5o98NH98OurViG98uLjixubADj3L3DuwxAYWrMxKaU8jiYIN9mfWcCclfu5rl8LWjaooQ9jRzkseg4SXgcM9Bpr/fgHgfFj+ea9DB5+dc3EopTyeJog3OSVH3fi72dqrjG6JB8+uwO2fwO9b4Shj/1h/oWSXbk1E4tSyitogqhm+cVlvPzDDj5fm8LtQ9rQJKoGpgnNSYXZ18GhjXDpCzDgLvcfUynl9TRBVKMft6Tx9/mbOJhdxA0DWvLQiBpoe9j7K8y7DUry4Po50PFi9x9TKeUTNEFUk193HeGOD1bTKTqCz27oQ2yr+u49oIjVEP3Ts9aEPTd/ruUwlFLVShNENSgrd/DMV5tpUT+E+fcPIbiOG8c4FOdZg9wSZ8L+5dB1FIz8LwRHuu+YSimfpAmiGny8IpkdaXlMuynWfckh+wD88qI11WdpPtRrA3/6P4i7XUc/K6XcQhPEWcrKL+HlH3YwpH0DLu7mhhpGBZmw9GVYMR0Q6Hkd9LkJWgzQxKCUcitNEGfp5R92kFdcxlNXdKu+yqylRbBzIWycCzu+h/ISq07S0MlQr1X1HEMppU5DE8RZ2HQgm49X7GPcoNZ0jK6myqzbvoEFkyDvEIQ1hrhbIfYWaNylevavlFIu0gRRRaXlDv46bwMNwoOYdGE1dGctyIRvH7GuGqK7w+g3oM1Q8Nc/kVLKHvrpU0XT4nezNTWH6TfHEhVap2o7ydwD27+F3Ytg71JwlFojoM95CAICqzdgpZQ6Q5ogqmBHWi6vLdrJFb2aMqJbkzPfgQismAbf/81KCg3aQ99xEDtexzIopWoNTRAuKHcIi7cdprC0HIcI7y7dQ0RwHZ6+ouuZ76woG76cAFvmWzO4XfIva6CbUkrVMpogXDBrZTJ/+9+m46/9DLx+fV8ahAedfuPk5TD3FijIgIAQkHIoLYSLnoPBE7SrqlKq1tIEcRolZQ7eXLyLPi3r8uI1PQFDRHAA0ZEuFOHb+pVVYTWyGQwcA2XFUF5qjWVoOcDtsSul1NnQBHEan61J4WB2Ef+6uiftG7vYlbW0CBJnwHePQfM4uP4TCGvg3kCVUqqaaYI4hdJyB28s3kWvFnU5r0PDU69cXgbrPrZ6Je35GUoLrCk9r3lPZ29TSnkkTRCn8MWaA6RkFfLsqNOMks7PgHm3Womhbktrwp4OI6D9cPBzY+E+pZRyI00QJ5FfXMZ/F++iR7MohnVqfPIVD66DT262Rj6PfB363KwNz0opr6AJooI9R/J5/PON7ErPIz23GIC3x8VVfvUgAqvege+fhNAGcNt30Cy2hiNWSin30QRRwSs/7mB9ylEu7xlDqwZhdG8WxfkdG/1xxdxDMP8+2PUjtL8QRk+D8ErWU0opD6YJwik9t5hvNqZy44BWPD3yhNHMST/D909ASb71Ou8wOMrhspeg3x16S0kp5ZU0QTjNWZlMablw86ATymlvXWA1QEe1+O0WUkAwDJ4IjWpgzmmllLKJJgisKUNnrUzm3A4Nadco/Lc31s2ybiU1i4UbPoVQN88zrZRStYgmCODHrWmkZhfx+oCjMHUSFByxaiaVFUHbYXDdRxAUfvodKaWUF7ElQRhj9gK5QDlQJiJxxpj6wCdAa2AvMEZEsmoinpkJ+xgRmUzssmchIgY6XgLBURDV3JqsJ8CFmktKKeVl7LyCGCYiRyq8ngz8JCJTjDGTna8fdXcQq/dmkr5nPTPC/oWJiIZbv4UIN8wtrZRSHqY23WIaBQx1Pp8JxOPGBLH3aBmPvbuA/N3L+ChoNoFBQXDzF5oclFLKya4EIcD3xhgB3hKR6UC0iKQ63z8EuO2TOn7WS1y2/XVuMUchEByhjfC7+Quo38Zdh1RKKY9jRKTmD2pMMxE5YIxpDPwATAC+FJG6FdbJEpF6lWx7J3AnQHR0dOycOXPO+PiOlJWEp8QT2rQbRfW6kB/WCvGBmkl5eXmEh/tWY7ues2/Qcz4zw4YNSxSRuNOtZ0uC+F0AxjwN5AF/BoaKSKoxJgaIF5FOp9o2Li5OVq9eXaXjxsfHM3To0Cpt66n0nH2DnrNvOJtzNsa4lCD8qrT3s2CMCTPGRBx7DowANgFfAuOdq40H5td0bEoppX5jRxtENPCFswBeADBLRL4zxqwCPjXG3A7sA8bYEJtSSimnGk8QIpIE9KpkeQYwvKbjUUopVbkav8WklFLKM2iCUEopVSlNEEoppSqlCUIppVSlNEEopZSqlO0D5c6GMSYdq0tsVTQEjpx2Le+i5+wb9Jx9w9mccysROe08yR6dIM6GMWa1KyMJvYmes2/Qc/YNNXHOeotJKaVUpTRBKKWUqpQvJ4jpdgdgAz1n36Dn7Bvcfs4+2wahlFLq1Hz5CkIppdQp+GSCMMZcYozZbozZ5Zz/2qsZY1oYYxYbY7YYYzYbYx6wO6aaYIzxN8asNcYssDuWmmCMqWuMmWeM2WaM2WqMGWR3TO5mjJnk/De9yRgz2xgTbHdM1c0Y854x5rAxZlOFZfWNMT8YY3Y6H/8wuVp18LkEYYzxB94ALgW6AtcbY7raG5XblQEPi0hXYCBwnw+cM8ADwFa7g6hBrwLfiUhnrIrJXn3uxphmwEQgTkS6A/7AWHujcov3gUtOWDYZ+ElEOgA/OV9XO59LEEB/YJeIJIlICTAHGGVzTG4lIqkissb5PBfrg6OZvVG5lzGmOfAn4B27Y6kJxpgo4DzgXQARKRGRo/ZGVSMCgBBjTAAQChy0OZ5qJyK/AJknLB4FzHQ+nwmMdsexfTFBNAP2V3idgpd/WFZkjGkN9AFW2BuJ270CPAI47A6khrQB0oEZzttq7zhnbPRaInIAeAlIBlKBbBH53t6oaky0iKQ6nx/Cmoit2vligvBZxphw4DPgQRHJsTsedzHGXA4cFpFEu2OpQQFAX+BNEekD5OOm2w61hfO++yis5NgUCDPG3GRvVDVPrK6obumO6osJ4gDQosLr5s5lXs0YUwcrOXwsIp/bHY+bDQFGGmP2Yt1CvMAY85G9IbldCpAiIseuDOdhJQxvdiGwR0TSRaQU+BwYbHNMNSXNGBMD4Hw87I6D+GKCWAV0MMa0McYEYjVqfWlzTG5lrAnA3wW2isjLdsfjbiLymIg0F5HWWH/fRSLi1d8sReQQsN8Y08m5aDiwxcaQakIyMNAYE+r8Nz4cL2+Yr+BLYLzz+XhgvjsOUuNzUttNRMqMMfcDC7F6PbwnIpttDsvdhgA3AxuNMeucyx4XkW9sjElVvwnAx84vPknArTbH41YissIYMw9Yg9VTby1eOKLaGDMbGAo0NMakAE8BU4BPjTG3Y1W0HuOWY+tIaqWUUpXxxVtMSimlXKAJQimlVKU0QSillKqUJgillFKV0gShlFKqUpoglMcxxpQbY9Y5K3jONcaEnmb9BBf2+eDJ9mOMiXdW/93grJT6X2NM3cr2b4x50Vld9EVjTCNjzApn6Ytzz+Qcz4QxprUx5oYKr+OMMa+dZpuhvlLlVlWdJgjliQpFpLezgmcJcPepVhYRV0bXPohV7O1kbhSRnkBPoJgKA5NO2P+dQE8R+SvWwK2NItJHRJa4EMOxasNnqjVwPEGIyGoRmViF/Sj1O5oglKdbArQHMMY85Lyq2GSMefDYCsaYPOfjUOfVwLE5Ez42lolYtXwWG2MWn+pgzgrAjwAtjTG9Ttj/l0A4kGiMeRR4ARjlvNoJMcaMMMYsM8ascV75hDu322uM+bcxZg1wrTGmnTHmO2NMojFmiTGms3O9940xrxljEowxScaYa5xhTQHOdR5nUsWrA2NMf+cx1zq364RSLvK5kdTKezhLPF8KfGeMicUaOTwAMMAKY8zPIrL2hM36AN2wykL/CgwRkdeMMQ8Bw0TkyOmOKyLlxpj1QGdgfYXlI40xeSLS2xlfGtZcBfcbYxoCTwIXiki+M4E8BDzr3DxDRPo6t/sJuFtEdhpjBgBTgQuc68UA5ziP/SVWzaXJwF9E5HLn9kMrhLsNONdZQeBC4J/A1ac7R6VAE4TyTCEVSoYswaozdQ/whYjkAxhjPgfOxSq/UNFKEUlxrrMO6/bM0irEYM5w/YFYE1T9apUNIhBYVuH9T5wxhWMVnJvrXA8gqMJ6/xMRB7DFGONKiecoYKYxpgNWxc86Zxi38mGaIJQnKjz2Lf2YCh+mp1Nc4Xk5Vfg/4Gwn6MGZFYYzwA8icv1J3s93PvoBR088vwoqxu/KST8HLBaRK401F0i8C9soBWgbhPIeS4DRzsqeYcCVzmWuygUiTreSs2z6v4D9IrLhDPa/HBhijDnWXhJmjOl44krOeTr2GGOuda5njrV1VDH2KH4rZ3/LGcSrlCYI5R2cU6q+D6zEmi3vnUraH05lOlZbxskaqT82xmwANgFhnOE0tSKSjvUBPdu5n2VY7QiVuRG43dnOsdmFY20Ayo0x640xk0547wXgX8aYtegdA3WGtJqrUkqpSukVhFJKqUppglBKKVUpTRBKKaUqpQlCKaVUpTRBKKWUqpQmCKWUUpXSBKGUUqpSmiCUUkpV6v8BphLyFy0Y8g0AAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(diff, [100*s for s in series], label='Series Win')\n", "plt.plot(diff, [100*g for g in game], label='Game Win')\n", "plt.legend(loc='best'); plt.grid()\n", "plt.xlabel('Point Differential'); plt.ylabel('Win Percentage');" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYgAAAEKCAYAAAAIO8L1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzt3Xd8HNW5//HPo2LLttyLcMO9xIB7oyTYtAskFwidhFAuYAJcWuAXSgohITck4dICJEAophpMNYTQjE3HuPeKq9xwlSXZqvv8/pgx6BpJXktajaT9vl+vZXdmZ3aew8j77Jxz5hxzd0RERPaVEnUAIiJSNylBiIhIuZQgRESkXEoQIiJSLiUIEREplxKEiIiUSwlCRETKpQQhIiLlUoIQEZFypUUdQHW0a9fOu3fvXqV98/PzadasWc0GVMepzMlBZU4O1SnzzJkzt7p7+/1tV68TRPfu3ZkxY0aV9p06dSpjxoyp2YDqOJU5OajMyaE6ZTazNfFspyomEREplxKEiIiUSwlCRETKpQQhIiLlUoIQEZFyJSxBmNnjZva1mS0os66Nmb1nZsvD59bhejOz+81shZnNM7OhiYpLRETik8griCeBE/dZdzMw2d37AJPDZYCTgD7hYxzw9wTGJSIicUjYfRDu/pGZdd9n9anAmPD1eGAqcFO4/ikP5j/9wsxamVlHd9+YqPhERKrL3dlTXEpuQQm5BSXsKSpld1EJe4pLKSyJBY/iUkpiTklpjOJSpzTmlHrw7O7EHGLh1M/u4P/3ABUeu9We0m++TBOltm+Uyyrzpb8JyApfdwbWldkuO1z3nQRhZuMIrjLIyspi6tSpVQokLy+vyvvWVypzclCZq68k5mzb42wrcLbtibG9wMkpcnIKnV2FTm6xk1/k5JdArOLv8BphFaw/u5cn/DxHdie1u7uZHfD/Wnd/BHgEYPjw4V7VOwl152VyUJmTQ1XLvLuohKWbclm2OZclm3L5aks+q7fmk71j93e++Fs1Tad9Zgbt2jSmb7NGtGqaTqum6TTPSKd5RhqZjdNo2iiNpo1SyUhPJSM9hcZpqTRKTSE9zUhLSSE91UhNCR4p9u2zARZmArOKUkLNlPlA1HaC2Ly36sjMOgJfh+vXA13LbNclXCciUiNiMWfFljymr97O7LU7mZ+dw/Kvc79JBE3SU+nVoRmDurbitMGd6NqmKZ1bN6FLq6ZktWxM47TUaAsQgdpOEJOAC4E7w+fXy6z/bzObAIwCctT+ICLVtWZbPh8t38rHy7bw5ert7NxdDEDbZo04rEtL/uPQgzikUwv6H9Scrq2bkpIS36/3ZJGwBGFmzxM0SLczs2zgNoLE8KKZXQKsAc4ON38LOBlYAewGLk5UXCLScJXGnFlrd/Duwk28t2gzq7ftBqBzqyacMCCLEd3bMLJHGw5u0zTuqpxklsheTOdV8Nax5WzrwFWJikVEGi5356udpUydtJA3521ka14h6anGEb3acfGRPfhB3/Z0b6uEUBX1erhvEUleX+cW8NLMbF6cvo7V2wpolLaWY/t34OTDOjKmX3uaZ6RHHWK9pwQhIvWGuzNt1Xae/HQ17y3eTGnMGdmjDcd2LOHaM8fQQkmhRilBiEidV1waY9KcDTz2ySoWbdxF66bpXHpUD84Z0ZWe7TOZOnWqkkMCKEGISJ1VUFzKxBnr+MeHK1m/cw99OmTyp9MP47TBnWnSKPm6ndY2JQgRqXOKSmK8MH0tf/tgBV/nFjL04Fb84bRDGNuvgxqba5EShIjUGbGYM2nuBu5+bxlrt+9mRPfW3HvuYA7v2VaJIQJKECJSJ8xcs4Pfv7GQudk5fK9jC564aARj+rVXYoiQEoSIROrrXQX8z1uLeW3OBjo0b8xdZw3i9CGddVdzHaAEISKRiMWcZ79cy1/+vYTCkhhXje3FlWN606yxvpbqCp0JEal1yzfn8suX5zF77U6O6NWWO047lJ7tM6MOS/ahBCEitaY05jz68UrufncZzRqncvfZg/jxkM5qZ6ijlCBEpFas3prP9S/OYfbanfzHIVnccdphtG/eOOqwpBJKECKSUO7Oy7PWc9vrC0hNMe47dzCnDOqkq4Z6QAlCRBImt6CYX726gElzNzCyRxvuPWcwnVo1iTosiZMShIgkxJJNu7jimVms3b6bG47vy5Vje5Oqrqv1ihKEiNS4V2Zlc+ur82mekc5zl45iVM+2UYckVaAEISI1prg0xh1vLmL852sY3bMN9583hA7NM6IOS6pICUJEasSO/CKufHYWn6/cxmXf78FNJ/YnLTUl6rCkGpQgRKTalm3O5ZLx09m8q5D/PWsQZwzrEnVIUgOUIESkWj5dsZWfPz2TjEapvDBuNEMObh11SFJDlCBEpMomzljHLa/Mp2f7Zjxx8Ug6qwtrg6IEISIHzN25f/IK7nl/GUf1bsdD5w/VlJ8NkBKEiByQWMz53RsLeerzNZw+tDN/PmMg6WqMbpCUIEQkboUlpdzw4lzenLeRcT/oyS0n9deQGQ2YEoSIxGVPUSk/f2YmHy7bwi0n9efyo3tFHZIkmBKEiOxXfmEJl4yfzrRV27nz9MM4d+TBUYcktUAJQkQqlbOnmIuf+JK52Tnce85gTh3cOeqQpJYoQYhIhXL2FHPBY9NYtHEXD/5kCCce2jHqkKQWKUGISLl2FRRzweNfsmjjLv7+02EcNyAr6pCklqlvmoh8x66CYn722Jcs2pDDQ0oOSSuSBGFm15vZQjNbYGbPm1mGmfUws2lmtsLMXjCzRlHEJpLs8gtLuPiJ6SzakMODPxnK8UoOSavWE4SZdQauAYa7+6FAKnAu8GfgHnfvDewALqnt2ESSXUFxKZc9NYPZa3dw/7lDOOGQg6IOSSIUVRVTGtDEzNKApsBG4BjgpfD98cBpEcUmkpSKSmLfDNd911mDOOkwNUgnu1pPEO6+HrgLWEuQGHKAmcBOdy8JN8sG1JdOpJaUxpxfvDiHD5Z8zR2nHcrpQzVct4C5e+0e0Kw18DJwDrATmEhw5fC7sHoJM+sK/Dusgtp3/3HAOICsrKxhEyZMqFIceXl5ZGZmVmnf+kplTg4HWmZ35+nFRXywtoSz+6Vzco/61/yn83xgxo4dO9Pdh+9vuyi6uR4HrHL3LQBm9gpwJNDKzNLCq4guwPrydnb3R4BHAIYPH+5jxoypUhBTp06lqvvWVypzcjjQMt/z3jI+WLucy3/Qk1tO/l7iAksgnefEiKINYi0w2syaWjDK17HAImAKcGa4zYXA6xHEJpJUnv58NfdNXs6Zw7pw80n9ow5H6pgo2iCmEVQpzQLmhzE8AtwE/MLMVgBtgcdqOzaRZPLOwk38dtJCju3fgTtPP0yjssp3xFXFZGbdgD7u/r6ZNQHS3D23qgd199uA2/ZZvRIYWdXPFJH4zVyzg2uen82gLq144CdDSdN8DlKO/f5VmNllBL/4Hw5XdQFeS2RQIpI4K7fkcen46XRsmcFjFw6nSaPUqEOSOiqenw1XETQi7wJw9+VAh0QGJSKJsT2/iIufnI6Z8eTFI2mb2TjqkKQOiydBFLp70d6F8Oa22u0bKyLVVlhSyuVPz2BjTgGPXjCc7u2aRR2S1HHxJIgPzexWgjufjye4b+GNxIYlIjXJ3fnlS/OYvnoH/3vWIIZ1ax11SFIPxJMgbga2EPQ4uhx4C/h1IoMSkZp13+TlvD5nAzee0Jf/HNQp6nCknthvLyZ3jwGPhg8RqWfenLeBe99fzulDO3PV2N5RhyP1yH4ThJnN57ttDjnADOAOd9+WiMBEpPrmZ+dw48S5DOvWmj/pXgc5QPHcB/FvoBR4Llw+l2AE1k3Ak8B/JiQyEamWr3cVcNlTM2jbrDH/OH8YjdPUnVUOTDwJ4jh3H1pmeb6ZzXL3oWZ2fqICE5GqKyguZdzTM8nZU8zLVxxB++bqzioHLp5G6lQz++YOZzMbQTDJD0BJ+buISFTcnd++voA563ZyzzmDGNCpRdQhST0VzxXEpcDjZpYJGMENc5eaWTPgT4kMTkQO3OS1Jby4OJtrjunNiYdq0h+punh6MU0HDjOzluFyTpm3X0xUYCJy4D7/ahvPLSni2P4duO64vlGHI/VcvIP1/RA4BMjY2wvC3X+fwLhE5ABt2LmH/35uFh2aGvecO5iUFPVYkuqJZ7C+fxDM/nY1QRXTWUC3BMclIgegsKSUK56dRWFJjGuGZNAiIz3qkKQBiKeR+gh3vwDY4e63A4cDunYVqUNuf2MRc9ft5K6zBtIpU0N3S82I5y9pT/i828w6AcWAWr5E6ogXZ6zjuWlr+fnRvdQoLTUqnjaIN82sFfBXglngHPhnQqMSkbgsWJ/Dr19bwJG923LjCbqwl5oVT4L4i7sXAi+b2ZtABlCQ2LBEZH9y9hRz5bOzaNusEfefO0SzwkmNi+cv6vO9L9y9MOzm+nkl24tIgsVizg0vzmXDzj088JOhmvhHEqLCKwgzOwjoTDAPxBCCHkwALQjGYhKRiDz80UreX7yZ2/5zgOZ2kISprIrpP4CLCOagvrvM+lzg1gTGJCKVmLZyG399Zwk/HNiRi47oHnU40oBVmCDcfTww3szOcPeXazEmEanA1rxCrpkwm25tm3Gnhu+WBIu3F9NPgO5lt9ed1CK1KxZzrn9hDjt2F/P4RSNorpvhJMHiSRCvE0wQNBMoTGw4IlKRB6es4OPlW/mfHx/GIZ1aRh2OJIF4EkQXdz8x4ZGISIW+WLmNe95fxqmDO3HeyK5RhyNJIp5urp+Z2WEJj0REyrUtr5Brw3aHP/5Y7Q5Se+K5gjgKuMjMVhFUMRng7j4woZGJSHC/w8S537Q7ZDaOawBmkRoRz1/bSQmPQkTK9c9PVjJ16Rb+cOohaneQWrffKiZ3XwN0BY4JX++OZz8RqZ4563byl7eXctKhB3H+aI2wL7UvnvkgbgNuAm4JV6UDzyQyKJFkt6ugmKufn0VWiwzuPGOg2h0kEvFcCfwYOAXIB3D3DUDzRAYlkszcnV+9uoANOwu4/7whtGyi+x0kGvEkiCJ3d4JhvjGzZtU9qJm1MrOXzGyJmS02s8PNrI2ZvWdmy8NnDTAjSWnijGzemLuBXxzfV+MsSaTiSRAvmtnDQCszuwx4H3i0mse9D3jb3fsDg4DFwM3AZHfvA0wOl0WSyldb8rht0kIO79mWnx/dK+pwJMnttxeTu99lZscDu4B+wG/d/b2qHtDMWgI/IBgIEHcvAorM7FRgTLjZeGAqQduHSFIoLCnl6udmk5Gewr3nDiY1Re0OEi0Lao8q2cCsB7DR3QvC5SZAlruvrtIBzQYDjwCLCK4eZgLXAuvdvVW4jRHMgd2qnP3HAeMAsrKyhk2YMKEqYZCXl0dmZmaV9q2vVOa67fklhbyzuoRrhzZmSIeq3+9Qn8pcU1TmAzN27NiZ7j58vxu6e6UPYAbQqMxyI2D6/var5POGAyXAqHD5PuAPwM59ttuxv88aNmyYV9WUKVOqvG99pTLXXVOWbPZuN73pv3ltfvU/q56UuSapzAcGmOFxfF/H0waR5kE10N6EUhQmiarKBrLdfVq4/BIwFNhsZh0Bwuevq3EMkXpjS24hN06cR7+s5tx68veiDkfkG/EkiC1mdsrehbCtYGtVD+jum4B1ZtYvXHUsQXXTJODCcN2FBKPIijRo7s4vX5rLroJi7j9vCBnpqVGHJPKNeCo6fw48a2YPhMvZwM+qedyrw89sBKwELiZIVi+a2SXAGuDsah5DpM576vM1TFm6hdtPOYR+B+n2IqlbKk0QZpYCDHP30WaWCeDuedU9qLvPIWiL2Nex1f1skfpi6aZc/vjWYsb2a88Fh2soDal7Kq1icvcY8MvwdV5NJAcRgYLiUq6dMJsWGWn89axBGkpD6qR42iDeN7MbzaxreLdzGzNrk/DIRBqwP7+9hCWbcvnrmYNol9k46nBEyhVPG8Q54fNVZdY50LPmwxFp+D5ctoUnPl3NRUd0Z2z/DlGHI1KheO6k7lEbgYgkg215hdw4cS59szK5+aT+UYcjUql4hvtuama/NrNHwuU+ZvajxIcm0rC4Oze9PJ+c3cXce466tErdF08bxBNAEXBEuLweuCNhEYk0UM9/uY73F2/mlyf2Y0CnFlGHI7Jf8SSIXu7+F6AYwN13E8xLLSJxWrkljz+8uYijerfjv45Ura3UD3HNBxEO0Ld3PoheQGFCoxJpQIpLY1z3whwap6dw11mDSNEorVJPxNOL6XfA20BXM3sWOJJwqG4R2b/73l/OvOwcHvrpUA5qmRF1OCJxi6cX07tmNhMYTVC1dK27V3ksJpFkMn31dh6auoIzh3Xh5MM6Rh2OyAGpMEGYWQfgVqA3MB/4k7vvqq3AROq7XQXFXP/CHLq0bsrvTjkk6nBEDlhlbRBPAfnA34BM4P5aiUikgfjdpIVs2LmHe84ZTGbjqk8AJBKVyv5qO7r7r8LX75jZrNoISKQheHPeBl6ZtZ5rju3DsG6tow5HpEr2N5pra77t0ppadtndtyc4NpF6aWPOHn716gIGd23F1cf0jjockSqrLEG0JJgvumyfvL1XERqLSaQcsZhz48S5FJfGuOecwaSnxtOTXKRuqjBBuHv3WoxDpEF4/NNVfLpiG3eefhg92jWLOhyRatHPG5EasnjjLv7y9lKOH5DFOSO6Rh2OSLUpQYjUgILiUq6bMIeWTdP58xkDNQGQNAjqeydSA/7y9lKWbs7liYtH0KZZo6jDEakRcSUIM0sFsspu7+5rExWUSH3y8fItPP7pKi48vBtj+2kCIGk49psgzOxq4DZgMxALVzswMIFxidQLO/KLuHHiXHp3yOSWk78XdTgiNSqeK4hrgX7uvi3RwYjUJ+7OLa/MZ3t+EY9fNEITAEmDE08j9TogJ9GBiNQ3E2dk8/bCTdx4Qj8O6dQy6nBEalw8VxArgalm9i/KzAPh7ncnLCqROm711nx+98ZCRvdsw2Xf1z2j0jDFkyDWho9G4UMkqRWXxrj2hTmkpRh3nz1YEwBJgxXPfBC310YgIvXF3yYvZ+66nTz4k6F0atUk6nBEEqay+SDudffrzOwNwulGy3L3UxIamUgdNH31dh6YsoIzhnbhhwM1AZA0bJVdQTwdPt9VG4GI1HU5e4q5bsLeCYAGRB2OSMJVliC6mtk6d/+w1qIRqaPcnd+8toBNuwp46eeH0zwjPeqQRBKusm6u5wOzzWy5mY03s3FmdmhtBSZSl7w6ez2T5m7gumP7MORgTQAkyaHCBOHuZ7p7Z+B44B2CO6fHm9kWM3urugc2s1Qzm21mb4bLPcxsmpmtMLMXzEw9pqROWLttN799fSEju7fhyrGaAEiSx35vlHP31QQTBc0G5gBfAzXRdeNaYHGZ5T8D97h7b2AHcEkNHEOkWopLY1wzYTZmcPc5g0hVl1ZJIhUmCDO71czeMLMvgFsI7oF4ABjo7mOrc1Az6wL8EPhnuGzAMcBL4SbjgdOqcwyRmnDv+8uYs24nfzr9MLq0bhp1OCK1qrJG6guAfOAN4DNgmrvX1JAb9wK/BJqHy22Bne5eEi5nA51r6FgiVfL5V9t4aOpXnD28Cz8a2CnqcERqnbl/5xaHb980awMcET5GA5nAXOAzd3+iSgc0+xFwsrtfaWZjgBuBi4AvwuolzKwr8G93/06juJmNA8YBZGVlDZswYUJVwiAvL4/MzMwq7VtfqcwHsF+R85tP99A4FX53RBMy0upP1ZLOc3KoTpnHjh07092H73dDd9/vg+BKYxTw/4AVQGk8+1XwWX8iuEJYDWwCdgPPAluBtHCbw4F39vdZw4YN86qaMmVKlfetr1Tm+MRiMb9s/HTvfeu/fH72zpoPKsF0npNDdcoMzPA4vq8ra4M4xczuNLOPCRqm7yKoCroBOKgqWStMSLe4exd37w6cC3zg7j8FpgBnhptdCLxe1WOIVMczX6zh3UWbuenE/hzaWaO0SvKqrA3iIuBTgraCme5elOBYbgImmNkdBD2mHkvw8US+Y/HGXfzhX4sZ0689/3Vkj6jDEYlUhQnC3U9P9MHdfSowNXy9EhiZ6GOKVGR3UQlXPz+blk3SueusQRqlVZJeXHNSiySD2yct4qsteTxzySjaZTaOOhyRyMUzo5xIg/f6nPW8MGMdV47pxZG920UdjkidcEAJwsxam9nARAUjEoVVW/O59ZX5jOjemuuP6xt1OCJ1xn4ThJlNNbMW4T0Rs4BHzUzTjUqDUFhSyn8/N4v0tBTuO3cIaam6qBbZK55/DS3dfRdwOvCUu48CjktsWCK143/+tZiFG3Zx15mDNDucyD7iSRBpZtYROBt4M8HxiNSaf83byPjP13DpUT04bkBW1OGI1DnxJIjfEwz3/ZW7TzeznsDyxIYlklirt+Zz08vzGHJwK246qX/U4YjUSfvt5uruE4GJZZZXAmckMiiRRCooLuXKZ2eRlmo88JOhpKvdQaRc8TRS9zWzyWa2IFweaGa/TnxoIonx+zcXsWjjLu4+exCd1e4gUqF4fjo9SjAfRDGAu88jGENJpN55ZVY2z01by+VH9+SY/mp3EKlMPAmiqbt/uc+6knK3FKnDlmzaxa2vzmdUjzb8vxP6RR2OSJ0XT4LYama9AAcwszOBjQmNSqSG5RYUc+Uzs2iekc7ffqL7HUTiEc9YTFcBjwD9zWw9sAo4P6FRidQgd+eml+exZvtunrt0FB2aZ0Qdkki9EE8vppXAcWbWDEhx99zEhyVScx75aCVvzd/ErSf3Z1TPtlGHI1JvVJggzOx8d3/GzH6xz3oA3F3DbUidt2hbKXfNWMIPD+vIZd/vGXU4IvVKZVcQzcLn5rURiEhN27BzD3+fU0DP9pn8+cyB3/y4EZH4VDZh0MNmlgrscvd7ajEmkWorKC7limdmUhyDh382jMzGmvpE5EBV2pXD3UuB82opFpEa4e786tUFzM3OYdzAxvRqnxl1SCL1Ujw/qz41sweAF4D8vSvdfVbCohKphic+Xc3Ls7K5/ri+DEpbH3U4IvVWPAlicPj8+zLrHDim5sMRqZ7PVmzlj28t5oQBWVx9TG8++kgJQqSq4unmOrY2AhGprjXb8rnyuVn0bNeMu88ZTEqKGqVFqiOewfqyzOwxM/t3uDzAzC5JfGgi8cstKOaS8TMAePSC4WqUFqkB8Yw38CTBfBCdwuVlwHWJCkjkQJXGnGuen83qrfk89NOhdG/XbP87ich+xZMg2rn7i0AMwN1LgNKERiVyAO7892KmLN3C7045hCN6tYs6HJEGI54EkW9mbfl2sL7RQE5CoxKJ03PT1vLox6u44PBunD+6W9ThiDQo8VTU/gKYBPQys0+B9sCZCY1KJA4fL9/Cb15fwJh+7fntjwZEHY5IgxNPL6ZZZnY00A8wYKm7Fyc8MpFKLNucy5XPzKJPh0z+dp6G7xZJhAr/VZnZCDM7CL5pdxgG/BH4XzNrU0vxiXzH17sKuPiJ6WQ0SuWxi0bQPCM96pBEGqTKfnY9DBQBmNkPgDuBpwjaHx5JfGgi35VXWMLFT05nx+4iHr9whOaUFkmgyqqYUt19e/j6HOARd38ZeNnM5iQ+NJH/q7g0xpXPzmLJplz+eeFwDuvSMuqQRBq0yq4gUs1sbwI5FvigzHu6C0lqlbtz6yvz+WjZFv542qGM7dch6pBEGrzKEsTzwIdm9jqwB/gYwMx6U41urmbW1cymmNkiM1toZteG69uY2Xtmtjx8bl3VY0jD8+e3lzJxZjbXHNuHc0ceHHU4IkmhwgTh7n8EbiC4k/ood/cy+1xdjWOWADe4+wBgNHCVmQ0AbgYmu3sfYHK4LMKjH63kHx9+xU9HHcz1x/WJOhyRpFFpVZG7f1HOumXVOaC7bwQ2hq9zzWwx0Bk4FRgTbjYemArcVJ1jSf330sxs/vjWYn54WEd+f+qhmhVOpBbZtxcGERzcrDvwEXAosNbdW4XrDdixd3mffcYB4wCysrKGTZgwoUrHzsvLIzMzuSaSqW9lnrGphIfmFtK/TQrXD8sgvQqjs9a3MtcElTk5VKfMY8eOnenuw/e7obtH8gAygZnA6eHyzn3e37G/zxg2bJhX1ZQpU6q8b31Vn8o8Zclm733rv/zHD37ieQXFVf+celTmmqIyJ4fqlBmY4XF8T0dy+6mZpQMvA8+6+yvh6s1m1jF8vyPwdRSxSfS+WLmNy5+eSd+s5jxx8UiaaehukUjUeoIIq48eAxa7+91l3poEXBi+vhB4vbZjk+jNWL2dS56czsFtmvL0JaNo2UR3SYtEJYqfZkcCPwPml7nh7laCO7VfDCcjWgOcHUFsEqEZq7dz4eNfktUig2cvHUWbZo2iDkkkqdV6gnD3TwgG/SvPsbUZi9QdM9d8mxyeHzeaDi0yog5JJOlpCEyJ3JertnPh49PpECaHLCUHkTpBCUIi9cnyrVzw+DSyWjTm+cuUHETqEnUPkchMXryZK56dRc92zXjm0lG0y2wcdUgiUoYShETitdnruXHiXAZ0asFT/zWSVk3VIC1S16iKSWrd45+s4roX5jC8e2ueuXSUkoNIHaUrCKk17s5d7y7lwSlfceIhB3HvuYPJSE+NOiwRqYAShNSKopIYN788j1dmr+e8kQdzx2mHklqFsZVEpPYoQUjC5ewu5vJnZvDFyu3ceEJfrhrbW6OyitQDShCSUGu25fNfT05n3fY93HvOYE4b0jnqkEQkTkoQkjCfLN/KVc/NwgyeumQko3u2jTokETkAShBS49ydJz5dzR3/WkSfDs159ILhHNy2adRhicgBUoKQGpVfWMKtr87n9TkbOGFAFnefM5hMDdctUi/pX67UmBVf53LFM7P4akseN57QlyvH9CZFPZVE6i0lCKk2d+fV2ev5zWsLyEhP5elLRnFk73ZRhyUi1aQEIdWyq6CY37y2gNfnbGBk9zbcd95gOrZsEnVYIlIDlCCkyr5ctZ0bJs5hw84Cbji+L1eO7a2b30QaECUIOWB7ikq5692lPP7pKrq0bsKLlx/OsG6tow5LRGqYEoQckGkrt3HLK/NZuTWfn43uxs0n9aeZeimJNEj6ly1x2ZFfxJ/+vZhCySGOAAAMyElEQVQXZ2TTpXUTnr1UDdEiDZ0ShFSqNOZMnLGOv7yzlJw9xfz86F5ce2wfmjTSKKwiDZ0ShFRo2spt3P7GIhZt3MXwbq35w2mH8r2OLaIOS0RqiRKEfMfSTbnc9e5S3lu0mU4tM7j/vCH858COGoFVJMkoQcg31mzL577Jy3l19noyG6Vxw/F9ufT7PVWdJJKklCCEZZtzeWjKCibN3UB6agqXfb8nVxzdi9bNNBWoSDJTgkhS7s5nX23jiU9X8f7ir2naKJVLjurBZd/vSYcWGVGHJyJ1gBJEksktKGbS3A08/fkalmzKpW2zRlxzbB8uPqK7rhhE5P9QgkgCsZgzY80OHptfyBWTJ7OnuJTvdWzBX84cyCmDOpGRrjYGEfkuJYgGyt1ZsH4Xb87fwBtzNrAhp4DGqfDjoV05d+TBDOrSUr2SRKRSShANyJ6iUr5cvZ0PFm/mvUWb2ZBTQGqK8YM+7bjppP403rqME48bGHWYIlJPKEHUY4UlpczLzuHLVdv5/KttfLl6O0UlMTLSU/h+n/Zcf3xfjv1eFm3CtoWpU5dHHLGI1Cd1KkGY2YnAfUAq8E93vzPikOqM4tIYq7fms2BDDvOyg8f89TkUlcQA6NMhk5+N7sb3+7RjVI+2undBRKqtziQIM0sFHgSOB7KB6WY2yd0XRRtZ7YnFnC15hWTv2MPa7fms2rqb1VvzWbY5l5Vb8ikqDZJBRnoKh3ZqyQWjuzGiRxuGd2tN28zGEUcvIg1NnUkQwEhghbuvBDCzCcCpQL1KELGYU1Qao7A4xu7iEvYUlbK7qJTcghLyCkvILShmx+5idu4uYnt+EVvzCtmSW8jXuYVs3lVAcal/81kpBp1bN6FX+0yO7teeflnNGdCpBb3bZ5KWmhJhKUUkGdSlBNEZWFdmORsYlYgDvTh9Hfd+sptmsz4EwMu85/7tkof/8XC9AzF3YrHguTQWPIpLY5TEnJJS/+ZX/v6kGLRskk775o1p37wxw7u1pmOrJnRq1YQurZrQtU1TurZpQuM0VRWJSDTqUoKIi5mNA8YBZGVlMXXq1AP+jOzNJWQ1jpFqe8p8bplj7HvM8P3g2TCCL/i9j1SD1BQj1VJIT0klPRXSU4zGqdAoNXhummY0SYMmaUazdKNpOqSYEaSfgvCREzxtguxNQYasSXl5eVX6/1WfqczJQWVOjLqUINYDXcssdwnX/R/u/gjwCMDw4cN9zJgxB3ygMcDQqVOpyr712VSVOSmozMmhNspclyqypwN9zKyHmTUCzgUmRRyTiEjSqjNXEO5eYmb/DbxD0M31cXdfGHFYIiJJq84kCAB3fwt4K+o4RESkblUxiYhIHaIEISIi5VKCEBGRcilBiIhIuZQgRESkXFZ2aIn6xsy2AGuquHs7YGsNhlMfqMzJQWVODtUpczd3b7+/jep1gqgOM5vh7sOjjqM2qczJQWVODrVRZlUxiYhIuZQgRESkXMmcIB6JOoAIqMzJQWVODgkvc9K2QYiISOWS+QpCREQqkZQJwsxONLOlZrbCzG6OOp5EMLOuZjbFzBaZ2UIzuzZc38bM3jOz5eFz66hjrUlmlmpms83szXC5h5lNC8/1C+FQ8g2GmbUys5fMbImZLTazw5PgHF8f/k0vMLPnzSyjoZ1nM3vczL42swVl1pV7Xi1wf1j2eWY2tKbiSLoEYWapwIPAScAA4DwzGxBtVAlRAtzg7gOA0cBVYTlvBia7ex9gcrjckFwLLC6z/GfgHnfvDewALokkqsS5D3jb3fsDgwjK3mDPsZl1Bq4Bhrv7oQRTA5xLwzvPTwIn7rOuovN6EtAnfIwD/l5TQSRdggBGAivcfaW7FwETgFMjjqnGuftGd58Vvs4l+OLoTFDW8eFm44HToomw5plZF+CHwD/DZQOOAV4KN2lo5W0J/AB4DMDdi9x9Jw34HIfSgCZmlgY0BTbSwM6zu38EbN9ndUXn9VTgKQ98AbQys441EUcyJojOwLoyy9nhugbLzLoDQ4BpQJa7bwzf2gRkRRRWItwL/BKIhcttgZ3uXhIuN7Rz3QPYAjwRVqv908ya0YDPsbuvB+4C1hIkhhxgJg37PO9V0XlN2HdaMiaIpGJmmcDLwHXuvqvsex50YWsQ3djM7EfA1+4+M+pYalEaMBT4u7sPAfLZpzqpIZ1jgLDe/VSC5NgJaMZ3q2IavNo6r8mYINYDXcssdwnXNThmlk6QHJ5191fC1Zv3Xn6Gz19HFV8NOxI4xcxWE1QbHkNQP98qrIqAhneus4Fsd58WLr9EkDAa6jkGOA5Y5e5b3L0YeIXg3Dfk87xXRec1Yd9pyZggpgN9wl4PjQgauCZFHFONC+vfHwMWu/vdZd6aBFwYvr4QeL22Y0sEd7/F3bu4e3eCc/qBu/8UmAKcGW7WYMoL4O6bgHVm1i9cdSywiAZ6jkNrgdFm1jT8G99b5gZ7nsuo6LxOAi4IezONBnLKVEVVS1LeKGdmJxPUV6cCj7v7HyMOqcaZ2VHAx8B8vq2Tv5WgHeJF4GCCkXDPdvd9G8PqNTMbA9zo7j8ys54EVxRtgNnA+e5eGGV8NcnMBhM0yjcCVgIXE/zwa7Dn2MxuB84h6Kk3G7iUoM69wZxnM3seGEMwYutm4DbgNco5r2GifICgqm03cLG7z6iROJIxQYiIyP4lYxWTiIjEQQlCRETKpQQhIiLlUoIQEZFyKUGIiEi5lCAkUmaWZWbPmdlKM5tpZp+b2Y9r8fizw66imFmameWZ2fll3p9pZkPN7JQDHfnXzErNbE446uhEM2ta0/HHGcd1UR1b6jclCIlM2H/7NeAjd+/p7sMIbnLrUothfAocEb4eBCzbuxyOa9QLmOvuk9z9zgP87D3uPjgcdbQI+Hm8O4ajDteU6wgGtRM5IEoQEqVjgCJ3/8feFe6+xt3/BsEgg2b2sZnNCh97v7jHmNmHZvZ6eOVxp5n91My+NLP5ZtYr3K69mb1sZtPDx5HlxPAZ3yaII4B/AIPD5ZHATHcvNbOLzOyB8HOfDMff/yw8/pnf/djv+BjoHe5/fhjrHDN7eG8yCK9e/tfM5gKHm9mI8Bhzw+2bWzDfxV/D8swzs8vL/D+Zat/ODfFseGftNQRjFk0xsynhtn83sxkWzKlw+94AzezkcN+ZYfn2zqnRzIL5Cb4Mr7ga3OjHUgF310OPSB4E4/rfU8n7TYGM8HUfYEb4egywE+gINCYYd+b28L1rgXvD188BR4WvDyYYdmTfY3QDVoavnwf6Ewzb0Bz4FfCH8L2LgAfC108CEwl+YA0gGD6+vPjzwuc0gmERrgC+B7wBpIfvPQRcEL52grtj4ds7o0eEyy3CzxkH/Dpc1xiYQTBw3RiCkU27hHF9Xqbsq4F2ZeJqEz6nAlOBgUAGwYigPcr8v3gzfP0/BHcmA7QiuMpqFvXfjx6Jf+wd3Eokcmb2IHAUwVXFCCAdeCBsIygF+pbZfLqH482Y2VfAu+H6+cDY8PVxwICgJguAFmaW6e55e1e4+xoza2RmBxEkh6UE43WNIrii+FsF4b7m7jFgkZlVNJx2EzObE77+mGBsrHHAMGB6GFcTvh10rZRgcEWAfsBGd58exrkrLOsJwMAyVy0tCZJnEfClu2eH280BugOflBPX2WY2jiDhdCRIcikEiXJVuM3zYawAJxAMhHhjuJxBmHArKLc0EEoQEqWFwBl7F9z9KjNrR/CrGOB6gnFoBhF8gRWU2bfsODuxMssxvv27TgFGu3vZ/crzGXAWwReym9kXBCOEjiT4JV6esse3CrbZ4+6Dy64I213Gu/st5Wxf4O6l+4nVgKvd/Z19PnfMPjGVUs6/bzPrAdxIcGWyw8yeJPjC398xz3D3pfvZThoYtUFIlD4AMszsijLryjamtiT40o4BPyOoEjkQ7wJX713Y21upHJ8RNOTuTQafAxcAm9w95wCPuT+TgTPNrEMYUxsz61bOdkuBjmY2ItyuuQXDWb8DXGHBUO6YWd+wMb0yuQRVZhBUVeUDOeGVz0lljtfTgsmlIBgMb693gKvD5IaZDYm3sFK/KUFIZNzdCaZNPNrMVpnZlwRTKd4UbvIQcGHYaNuf4IvtQFwDDA8bcxdRcS+iT4GehAkirLpKJUgcNcrdFwG/Bt41s3nAewTVPPtuV0TwJf23sPzvEfzS/yfB8NazLJjQ/mH2XxPwCPC2mU1x97kEo50uIWij+TQ83h7gynC7mQRJZW9y/ANBdd88M1sYLksS0GiuIgIEsw+6e154pfAgsNzd74k6LomOriBEZK/LwsbthQTVew9HHI9ETFcQIiJSLl1BiIhIuZQgRESkXEoQIiJSLiUIEREplxKEiIiUSwlCRETK9f8BHu1s5IXqIuMAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "P = range(101)\n", "plt.plot(P, [100*win_series(p/100) for p in P])\n", "plt.grid()\n", "plt.xlabel('Game Win Percentage'); plt.ylabel('Series Win Percentage');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Series by Series Model\n", "\n", "The probability of winning a championship can be modeled by assuming that each series is independent, and multiplying the probability of winning each series. The function `playoffs` does this; it takes as arguments a team name and then some playoff round entries, each consisting of the opponent team name, the game win percentage against this opponent, and optionally the wins and losses in the series so far.\n", "\n", "The function `playoffs` does two calculations, one based on my subjective probability of the team winning a single game (as specified in the entry for each round), and one based on the SRS differential. In each line of the output and for each of these two calculations, we show the probability of winning a single game, the probability of winning the series (given that the two teams are still playing), and the probability of winning all the series up to this point." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def playoffs(team, *rounds):\n", " \"Print probability for team winning each series (subjective and SRS).\"\n", " all_p = all_srs = 1.0 # Probabilities of winning it all\n", " print('{} {:8} | Subjective Probabilities | SRS Differential'\n", " .format('Team'.ljust(len(team)), 'Opponent'))\n", " for (opponent, p, *WL) in rounds:\n", " p_srs = win_game(SRS[team] - SRS[opponent])\n", " all_p, str_p = update(all_p, p, *WL)\n", " all_srs, str_srs = update(all_srs, p_srs, *WL)\n", " print('{} vs {:8} | {} |{}'.format(team, opponent, str_p, str_srs))\n", " \n", "def update(all_p, p, W=0, L=0):\n", " \"Update the probability of winning it all, `all_p`, and also return a string.\"\n", " series_p = win_series(p, W, L)\n", " all_p *= series_p\n", " return all_p, '{} Game;{} Series;{} All'.format(pct(p), pct(series_p), pct(all_p))\n", "\n", "pct = '{:4.0%}'.format " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "# 2019 NBA Playoffs\n", "\n", "## 12 April, 2019\n", "\n", "Here are the SRS scores and my subjective ratings for what I consider the two top teams in 2019, the Warriors and Bucks, and their likely playoff opponents:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Clippers | 80% Game; 97% Series; 97% All | 69% Game; 87% Series; 87% All\n", "Warriors vs Rockets | 65% Game; 80% Series; 77% All | 56% Game; 62% Series; 54% All\n", "Warriors vs Nuggets | 70% Game; 87% Series; 68% All | 58% Game; 68% Series; 36% All\n", "Warriors vs Bucks | 52% Game; 54% Series; 37% All | 44% Game; 37% Series; 13% All\n" ] } ], "source": [ "SRS = dict(Bucks=8.04, Warriors=6.42, Raptors=5.49, Rockets=4.96, Nuggets=4.19, \n", " Celtics=3.90, Sixers=2.25, Clippers=1.09, Pistons=-0.56)\n", "\n", "playoffs('Warriors',\n", " ('Clippers', 0.80),\n", " ('Rockets', 0.65),\n", " ('Nuggets', 0.70),\n", " ('Bucks', 0.52))" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Bucks vs Pistons | 80% Game; 97% Series; 97% All | 79% Game; 96% Series; 96% All\n", "Bucks vs Celtics | 67% Game; 83% Series; 80% All | 65% Game; 81% Series; 78% All\n", "Bucks vs Raptors | 60% Game; 71% Series; 57% All | 60% Game; 70% Series; 54% All\n", "Bucks vs Warriors | 48% Game; 46% Series; 26% All | 56% Game; 63% Series; 34% All\n" ] } ], "source": [ "playoffs('Bucks',\n", " ('Pistons', 0.80),\n", " ('Celtics', 0.67),\n", " ('Raptors', 0.60),\n", " ('Warriors', 0.48))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's compare championship predictions for four methods: my subjective evaluations, the SRS point differentials, and two methods from [538](https://projects.fivethirtyeight.com/2019-nba-predictions/): ELO, which is similar to SRS, and their more complex CARM-ELO model:\n", "\n", "\n", "|Method|Warriors|Bucks|\n", "|------|--------|-----|\n", "|Subjective| 37% | 26% |\n", "|SRS | 13% | 35% |\n", "| ELO | 16% | 23% |\n", "| CARM-ELO| 61% | 15% |\n", "\n", "\n", "\n", "Which prediction method is best? I have low confidence in the SRS ratings, because the Warriors seemed like they were coasting for parts of the regular season and are capable of \"flipping the switch\" in the playoffs, and because the Bucks have significant injuries to Brogdon, Mirotic and Gasol, all of whom contributed to the Bucks' great record in the season but will miss parts of the playoffs.\n", "\n", "# 1 May, 2019\n", "\n", "The first round of playoffs was pretty uneventful—the favored team won in each of the eight matchups. Here's where we are today:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Clippers | 80% Game;100% Series;100% All | 69% Game;100% Series;100% All\n", "Warriors vs Rockets | 65% Game; 95% Series; 95% All | 56% Game; 88% Series; 88% All\n", "Warriors vs Nuggets | 70% Game; 87% Series; 83% All | 59% Game; 68% Series; 60% All\n", "Warriors vs Bucks | 52% Game; 54% Series; 45% All | 44% Game; 37% Series; 22% All\n" ] } ], "source": [ "playoffs('Warriors',\n", " ('Clippers', 0.80, 4, 2),\n", " ('Rockets', 0.65, 2, 0),\n", " ('Nuggets', 0.70),\n", " ('Bucks', 0.52))" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Bucks vs Pistons | 80% Game;100% Series;100% All | 79% Game;100% Series;100% All\n", "Bucks vs Celtics | 67% Game; 80% Series; 80% All | 65% Game; 77% Series; 77% All\n", "Bucks vs Raptors | 60% Game; 71% Series; 56% All | 60% Game; 70% Series; 54% All\n", "Bucks vs Warriors | 48% Game; 46% Series; 26% All | 56% Game; 64% Series; 34% All\n" ] } ], "source": [ "playoffs('Bucks',\n", " ('Pistons', 0.80, 4, 0),\n", " ('Celtics', 0.67, 1, 1),\n", " ('Raptors', 0.60),\n", " ('Warriors', 0.48))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 8 May, 2019\n", "\n", "The favored teams keep winning: three of them are ahead 3-2, and the fourth, the Bucks, won their series 4-1. But the Warriors suffered the loss of a second starter, Keven Durant, to injury, and it is unclear how long he'll be out,\n", "so I'm uncertain how to adjust the subjective probabilities:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Clippers | 80% Game;100% Series;100% All | 70% Game;100% Series;100% All\n", "Warriors vs Rockets | 50% Game; 75% Series; 75% All | 56% Game; 80% Series; 80% All\n", "Warriors vs Nuggets | 60% Game; 71% Series; 53% All | 59% Game; 68% Series; 55% All\n", "Warriors vs Bucks | 50% Game; 50% Series; 27% All | 44% Game; 37% Series; 20% All\n" ] } ], "source": [ "playoffs('Warriors',\n", " ('Clippers', 0.80, 4, 2),\n", " ('Rockets', 0.50, 3, 2),\n", " ('Nuggets', 0.60),\n", " ('Bucks', 0.50))" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Bucks vs Pistons | 80% Game;100% Series;100% All | 79% Game;100% Series;100% All\n", "Bucks vs Celtics | 67% Game;100% Series;100% All | 65% Game;100% Series;100% All\n", "Bucks vs Raptors | 60% Game; 71% Series; 71% All | 60% Game; 71% Series; 71% All\n", "Bucks vs Warriors | 50% Game; 50% Series; 36% All | 56% Game; 63% Series; 45% All\n" ] } ], "source": [ "playoffs('Bucks',\n", " ('Pistons', 0.80, 4, 0),\n", " ('Celtics', 0.67, 4, 1),\n", " ('Raptors', 0.60),\n", " ('Warriors', 0.50))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "# 2018 NBA Playoffs\n", "\n", "## 12 April, 2018\n", "\n", "The Las Vegas oddsmakers have the Warriors and Rockers as co-favorites at 35% chance to win the title, while [538](https://fivethirtyeight.com/features/the-nba-playoffs-sleepers-favorites-and-best-first-round-matchups/), using their CARM-ELO model, favor the Rockets at 44% and give the Warriors only a 4% chance. Those big differences underscore that rational people can use different models with different assumptions and come to different conclusions. " ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "SRS = dict(Raptors=7.29, Celtics=3.23, Sixers=4.30, Cavs=0.59, Rockets=8.21, Warriors=5.79, \n", " Blazers=2.60, Thunder=3.42, Jazz=4.47, Spurs=2.89, Wolves=2.35)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Rockets vs Wolves | 75% Game; 93% Series; 93% All | 71% Game; 89% Series; 89% All\n", "Rockets vs Jazz | 70% Game; 87% Series; 81% All | 64% Game; 79% Series; 70% All\n", "Rockets vs Warriors | 55% Game; 61% Series; 49% All | 59% Game; 69% Series; 49% All\n", "Rockets vs Raptors | 60% Game; 71% Series; 35% All | 54% Game; 58% Series; 28% All\n" ] } ], "source": [ "playoffs('Rockets',\n", " ('Wolves', 0.75),\n", " ('Jazz', 0.70),\n", " ('Warriors', 0.55),\n", " ('Raptors', 0.60))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So I'm in good agreement with the Vegas oddsmakers about the Rockets: my subjective probabilities have the Rockets at 49% winning the conference and 35% winning the title, while Vegas had them at 44% and 35%. The SRS differential has them at 48% and 27%." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Spurs | 75% Game; 93% Series; 93% All | 61% Game; 73% Series; 73% All\n", "Warriors vs Blazers | 65% Game; 80% Series; 74% All | 62% Game; 75% Series; 54% All\n", "Warriors vs Rockets | 45% Game; 39% Series; 29% All | 41% Game; 31% Series; 17% All\n", "Warriors vs Raptors | 55% Game; 61% Series; 18% All | 45% Game; 39% Series; 6% All\n" ] } ], "source": [ "playoffs('Warriors',\n", " ('Spurs', 0.75),\n", " ('Blazers', 0.65),\n", " ('Rockets', 0.45),\n", " ('Raptors', 0.55))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the Warriors my subjective probabilities are splitting the difference between 538's low estimate (8% win conference, 4% win title) and Vegas's high estimate (44% and 35%, tied with the Rockets); I have them at 29% and 18%. The SRS differential at 17% and 6% is closer to 538.\n", "\n", "How do I reconcile the discrepancy between my subjective probabilities and the SRS numbers? I guess I would say that I have less faith in the point differential model, for several reasons: it counts games from the distant past, when some teams had very different lineups than they have now (due to injuries and trades); different teams have different approaches to how they handle games whose outcome is already decided; the metric puts too much emphasis on blowouts, for example, in the Warriors' final game, it was to their strategic advantage to lose, and they did it very convincingly—by 40 points, which dropped their average point differential for the entire year by 0.5 points." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "# 2016 NBA Playoffs\n", "\n", "\n", "## 18 April 2016\n", "\n", "The Golden State Warriors have had a historic basketball season, winning more games than any other team ever has. But will they top that off by winning the championship? There are 15 other teams in contention, including one, the Spurs, that has had a historic season as the best second-best team ever. The web site fivethirtyeight, using a complicated scoring system, [gives](http://projects.fivethirtyeight.com/2016-nba-picks/) the Warriors a 44% chance of winning, with the Spurs at 28%. Basketball-reference [has](http://www.basketball-reference.com/friv/playoff_prob.cgi) the Warriors at 41% and Spurs at 32.5%, while a [betting site](http://www.oddsshark.com/nba/nba-futures) had the Warriors at 54% and Spurs at 18%. Here is my analysis:\n", " " ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Rockets | 83% Game; 98% Series; 98% All | 83% Game; 98% Series; 98% All\n", "Warriors vs Clippers | 73% Game; 91% Series; 89% All | 72% Game; 90% Series; 89% All\n", "Warriors vs Spurs | 58% Game; 67% Series; 60% All | 50% Game; 51% Series; 45% All\n", "Warriors vs Cavs | 67% Game; 83% Series; 50% All | 68% Game; 85% Series; 38% All\n" ] } ], "source": [ "SRS = dict(Warriors=10.38, Spurs=10.28, Thunder=7.09, Cavs=5.45, Raptors=4.08,\n", " Rockets=0.34, Clippers=4.13, Pistons=0.43, Hawks=3.49, Memphis=-2.14,\n", " Blazers=4.43, Dallas=-0.87)\n", "\n", "playoffs('Warriors',\n", " ('Rockets', 0.83),\n", " ('Clippers', 0.73),\n", " ('Spurs', 0.58),\n", " ('Cavs', 0.67))" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Spurs vs Memphis | 83% Game; 98% Series; 98% All | 88% Game; 99% Series; 99% All\n", "Spurs vs Thunder | 62% Game; 75% Series; 73% All | 62% Game; 74% Series; 74% All\n", "Spurs vs Warriors | 42% Game; 33% Series; 24% All | 50% Game; 49% Series; 37% All\n", "Spurs vs Cavs | 67% Game; 83% Series; 20% All | 68% Game; 84% Series; 31% All\n" ] } ], "source": [ "playoffs('Spurs',\n", " ('Memphis', 0.83),\n", " ('Thunder', 0.62),\n", " ('Warriors', 0.42),\n", " ('Cavs', 0.67))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Cavs vs Pistons | 83% Game; 98% Series; 98% All | 68% Game; 85% Series; 85% All\n", "Cavs vs Hawks | 60% Game; 71% Series; 70% All | 57% Game; 66% Series; 56% All\n", "Cavs vs Raptors | 55% Game; 61% Series; 42% All | 55% Game; 61% Series; 34% All\n", "Cavs vs Warriors | 33% Game; 17% Series; 7% All | 32% Game; 16% Series; 5% All\n" ] } ], "source": [ "playoffs('Cavs',\n", " ('Pistons', 0.83),\n", " ('Hawks', 0.60),\n", " ('Raptors', 0.55),\n", " ('Warriors', 0.33))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I have the Warriors at 50% (for the estimate of winning it all) and the Spurs at 20%, so I'm more of a Warriors fan than fivethirtyeight and basketball-reference. Interestingly, while fivethirtyeight does not think this year's Warriors are better than the 1995 Bulls, they [do think](http://fivethirtyeight.com/features/the-warriors-still-arent-the-best-team-ever/) the Spurs, Thunder, and Cavs are the best ever second-, third-, and fourth-best teams in a season." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# WWWWC: Will Warriors Win Without Curry?\n", "\n", "## 27 April 2016\n", "\n", "The Playoff picture has changed! \n", "\n", "We have some results for first-round series, and there have been key injuries to players including Steph Curry, Avery Bradley, Chris Paul, and Blake Griffin. We don't know for sure how long Curry will be out, but here are my updated odds for the Warriors, under the assumption that Curry misses the second round, and comes back in time for the Western Conference Finals at a mildly reduced capacity:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Rockets | 70% Game; 97% Series; 97% All | 83% Game;100% Series;100% All\n", "Warriors vs Blazers | 55% Game; 61% Series; 59% All | 71% Game; 89% Series; 89% All\n", "Warriors vs Spurs | 55% Game; 61% Series; 36% All | 50% Game; 51% Series; 45% All\n", "Warriors vs Cavs | 60% Game; 71% Series; 26% All | 68% Game; 85% Series; 38% All\n" ] } ], "source": [ "playoffs('Warriors',\n", " ('Rockets', 0.70, 3, 1),\n", " ('Blazers', 0.55),\n", " ('Spurs', 0.55),\n", " ('Cavs', 0.60))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Spurs and Cavs are rolling; let's update their odds:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Spurs vs Memphis | 83% Game;100% Series;100% All | 88% Game;100% Series;100% All\n", "Spurs vs Thunder | 62% Game; 75% Series; 75% All | 62% Game; 74% Series; 74% All\n", "Spurs vs Warriors | 45% Game; 39% Series; 29% All | 49% Game; 49% Series; 36% All\n", "Spurs vs Cavs | 67% Game; 83% Series; 24% All | 68% Game; 85% Series; 31% All\n" ] } ], "source": [ "playoffs('Spurs',\n", " ('Memphis', 0.83, 4, 0),\n", " ('Thunder', 0.62),\n", " ('Warriors', 0.45),\n", " ('Cavs', 0.67))" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Cavs vs Pistons | 83% Game;100% Series;100% All | 68% Game;100% Series;100% All\n", "Cavs vs Hawks | 60% Game; 71% Series; 71% All | 57% Game; 65% Series; 65% All\n", "Cavs vs Raptors | 55% Game; 61% Series; 43% All | 55% Game; 61% Series; 40% All\n", "Cavs vs Warriors | 40% Game; 29% Series; 13% All | 32% Game; 15% Series; 6% All\n" ] } ], "source": [ "playoffs('Cavs',\n", " ('Pistons', 0.83, 4, 0),\n", " ('Hawks', 0.60),\n", " ('Raptors', 0.55),\n", " ('Warriors', 0.40))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So my updated odds are that the Warriors and Spurs are roughly equally likely to win (26% and 24%); the Cavs are still less likely (13%), and there is more uncertainty.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# WWWWCB: Will Warriors Win With Curry Back?\n", "\n", "## 10 May 2016\n", "\n", "Curry has returned from his injury, and after a slow shooting start, had the highest-scoring overtime period in the history of the NBA. Meanwhile, the Thunder lead the Spurs, 3-2, and the Cavaliers have been dominant in the East, hitting a historic number of 3-point shots. Here is my revised outlook: " ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Rockets | 70% Game;100% Series;100% All | 83% Game;100% Series;100% All\n", "Warriors vs Blazers | 67% Game; 96% Series; 96% All | 71% Game; 98% Series; 98% All\n", "Warriors vs Spurs | 60% Game; 71% Series; 68% All | 50% Game; 51% Series; 50% All\n", "Warriors vs Cavs | 55% Game; 61% Series; 42% All | 68% Game; 84% Series; 42% All\n" ] } ], "source": [ "playoffs('Warriors',\n", " ('Rockets', 0.70, 4, 1),\n", " ('Blazers', 0.67, 3, 1),\n", " ('Spurs', 0.60),\n", " ('Cavs', 0.55))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Spurs vs Memphis | 83% Game;100% Series;100% All | 88% Game;100% Series;100% All\n", "Spurs vs Thunder | 60% Game; 36% Series; 36% All | 62% Game; 39% Series; 39% All\n", "Spurs vs Warriors | 40% Game; 29% Series; 10% All | 50% Game; 49% Series; 19% All\n", "Spurs vs Cavs | 50% Game; 50% Series; 5% All | 68% Game; 84% Series; 16% All\n" ] } ], "source": [ "playoffs('Spurs',\n", " ('Memphis', 0.83, 4, 0),\n", " ('Thunder', 0.60, 2, 3),\n", " ('Warriors', 0.40),\n", " ('Cavs', 0.50))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Thunder vs Dallas | 83% Game;100% Series;100% All | 78% Game;100% Series;100% All\n", "Thunder vs Spurs | 40% Game; 64% Series; 64% All | 38% Game; 62% Series; 62% All\n", "Thunder vs Warriors | 40% Game; 29% Series; 19% All | 38% Game; 25% Series; 15% All\n", "Thunder vs Cavs | 45% Game; 39% Series; 7% All | 56% Game; 64% Series; 10% All\n" ] } ], "source": [ "playoffs('Thunder',\n", " ('Dallas', 0.83, 4, 1),\n", " ('Spurs', 0.40, 3, 2),\n", " ('Warriors', 0.40),\n", " ('Cavs', 0.45))" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Cavs vs Pistons | 83% Game;100% Series;100% All | 68% Game;100% Series;100% All\n", "Cavs vs Hawks | 60% Game;100% Series;100% All | 58% Game;100% Series;100% All\n", "Cavs vs Raptors | 65% Game; 80% Series; 80% All | 55% Game; 61% Series; 61% All\n", "Cavs vs Warriors | 45% Game; 39% Series; 31% All | 32% Game; 15% Series; 9% All\n" ] } ], "source": [ "playoffs('Cavs',\n", " ('Pistons', 0.83, 4, 0),\n", " ('Hawks', 0.60, 4, 0),\n", " ('Raptors', 0.65),\n", " ('Warriors', 0.45))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So overall, from the start of the playoffs up to May 10th, I have:\n", "\n", "- **Warriors:** Dropped from 50% to 26% with Curry's injury, and rebounded to 42%. \n", "- **Spurs:** Dropped from 20% to 5% after falling behind Thunder.\n", "- **Thunder:** Increased to 7%.\n", "- **Cavs:** Increased to 31%.\n", "\n", "# Time to Panic Yet?\n", "\n", "## 17 May 2016\n", "\n", "The Thunder finished off the Spurs and beat the Warriors in game 1. Are the Thunder, like the Cavs, peaking at just the right time, after an inconsistant regular season? Is it time for Warriors fans to panic?\n", "\n", "Sure, the Warriors were down a game twice in last year's playoffs and came back to win both times. Sure, the Warriors are still 3-1 against the Thunder this year, and only lost two games all season to elite teams (Spurs, Thunder, Cavs, Clippers, Raptors). But the Thunder are playing at a top level. Here's my update, showing that the loss cost the Warriors 5%:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Rockets | 70% Game;100% Series;100% All | 83% Game;100% Series;100% All\n", "Warriors vs Blazers | 67% Game;100% Series;100% All | 72% Game;100% Series;100% All\n", "Warriors vs Thunder | 63% Game; 61% Series; 61% All | 62% Game; 59% Series; 59% All\n", "Warriors vs Cavs | 55% Game; 61% Series; 37% All | 68% Game; 85% Series; 50% All\n" ] } ], "source": [ "playoffs('Warriors',\n", " ('Rockets', 0.70, 4, 1),\n", " ('Blazers', 0.67, 4, 1),\n", " ('Thunder', 0.63, 0, 1),\n", " ('Cavs', 0.55))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Yet!\n", "\n", "## 24 May 2016\n", "\n", "The Thunder won two in a row (first time the Warriors had lost two in a row all year), putting the Warriors down 3-1. And the Cavs are looking mortal, losing two to the Raptors. So now it looks to me like the Thunder are favorites to win it all:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Warriors vs Rockets | 70% Game;100% Series;100% All | 83% Game;100% Series;100% All\n", "Warriors vs Blazers | 67% Game;100% Series;100% All | 71% Game;100% Series;100% All\n", "Warriors vs Thunder | 55% Game; 17% Series; 17% All | 62% Game; 24% Series; 24% All\n", "Warriors vs Cavs | 55% Game; 61% Series; 10% All | 68% Game; 85% Series; 21% All\n" ] } ], "source": [ "playoffs('Warriors',\n", " ('Rockets', 0.70, 4, 1),\n", " ('Blazers', 0.67, 4, 1),\n", " ('Thunder', 0.55, 1, 3),\n", " ('Cavs', 0.55))" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Cavs vs Pistons | 83% Game;100% Series;100% All | 68% Game;100% Series;100% All\n", "Cavs vs Hawks | 60% Game;100% Series;100% All | 58% Game;100% Series;100% All\n", "Cavs vs Raptors | 55% Game; 57% Series; 57% All | 55% Game; 58% Series; 58% All\n", "Cavs vs Thunder | 45% Game; 39% Series; 23% All | 44% Game; 37% Series; 21% All\n" ] } ], "source": [ "playoffs('Cavs',\n", " ('Pistons', 0.83, 4, 0),\n", " ('Hawks', 0.60, 4, 0),\n", " ('Raptors', 0.55, 2, 2),\n", " ('Thunder', 0.45))" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Team Opponent | Subjective Probabilities | SRS Differential\n", "Thunder vs Dallas | 83% Game;100% Series;100% All | 77% Game;100% Series;100% All\n", "Thunder vs Spurs | 40% Game;100% Series;100% All | 38% Game;100% Series;100% All\n", "Thunder vs Warriors | 45% Game; 83% Series; 83% All | 37% Game; 75% Series; 75% All\n", "Thunder vs Cavs | 55% Game; 61% Series; 51% All | 56% Game; 63% Series; 48% All\n" ] } ], "source": [ "playoffs('Thunder',\n", " ('Dallas', 0.83, 4, 1),\n", " ('Spurs', 0.40, 4, 2),\n", " ('Warriors', 0.45, 3, 1),\n", " ('Cavs', 0.55))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1 June 2016: The Finals\n", "\n", "The Warriors completed their comeback against the Thunder, putting them in a great position to win this year (and they are already established as [favorites for next year](http://www.foxsports.com/nba/story/golden-state-warriors-title-favorites-cleveland-cavaliers-odds-2016-17-053016)). I think the Warriors have about a 55% game win probability (and thus about 61% series probability) against the Cavs. Rather than update this game by game, I'll give a table of series win probability based on game win probability and the number of games won so far. For example, if you agree the Warriors have a 55% game win percentage, and if they win the first game, then check the \"1-0\" row and the \"55%\" column to see that their series win probability has gone up to 74%." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "W-L | Game Win Percentage\n", " | 15% 20% 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85%\n", "----+---------------------------------------------------------------------------\n", "0-3 | 0% 0% 0% 1% 2% 3% 4% 6% 9% 13% 18% 24% 32% 41% 52%\n", "0-2 | 0% 1% 2% 3% 5% 9% 13% 19% 26% 34% 43% 53% 63% 74% 84%\n", "0-1 | 1% 2% 4% 7% 12% 18% 26% 34% 44% 54% 65% 74% 83% 90% 95%\n", "0-0 | 1% 3% 7% 13% 20% 29% 39% 50% 61% 71% 80% 87% 93% 97% 99%\n", "----+---------------------------------------------------------------------------\n", "1-3 | 0% 1% 2% 3% 4% 6% 9% 12% 17% 22% 27% 34% 42% 51% 61%\n", "1-2 | 1% 3% 5% 8% 13% 18% 24% 31% 39% 48% 56% 65% 74% 82% 89%\n", "1-1 | 3% 6% 10% 16% 24% 32% 41% 50% 59% 68% 76% 84% 90% 94% 97%\n", "1-0 | 5% 10% 17% 26% 35% 46% 56% 66% 74% 82% 88% 93% 96% 98% 99%\n", "----+---------------------------------------------------------------------------\n", "2-3 | 2% 4% 6% 9% 12% 16% 20% 25% 30% 36% 42% 49% 56% 64% 72%\n", "2-2 | 6% 10% 16% 22% 28% 35% 43% 50% 57% 65% 72% 78% 84% 90% 94%\n", "2-1 | 11% 18% 26% 35% 44% 52% 61% 69% 76% 82% 87% 92% 95% 97% 99%\n", "2-0 | 16% 26% 37% 47% 57% 66% 74% 81% 87% 91% 95% 97% 98% 99% 100%\n", "----+---------------------------------------------------------------------------\n", "3-3 | 15% 20% 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85%\n", "3-2 | 28% 36% 44% 51% 58% 64% 70% 75% 80% 84% 88% 91% 94% 96% 98%\n", "3-1 | 39% 49% 58% 66% 73% 78% 83% 88% 91% 94% 96% 97% 98% 99% 100%\n", "3-0 | 48% 59% 68% 76% 82% 87% 91% 94% 96% 97% 98% 99% 100% 100% 100%\n" ] } ], "source": [ "pcts = [p/100 for p in range(15, 90, 5)]\n", "\n", "print('W-L | Game Win Percentage')\n", "print(' | ' + ' '.join(map(pct, pcts)))\n", "for W in range(4):\n", " print('----+' + '-' * 5 * len(pcts))\n", " for L in reversed(range(4)):\n", " results = [win_series(p, W, L) for p in pcts]\n", " print('{}-{} | {}'.format(W, L, ' '.join(map(pct, results))))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 20 June 2016 \n", "\n", "Congratulations to LeBron, Kyrie, Coach Lue, and all the Cavs for overcoming long odds to win a championship for Cleveland. My model says the Warriors were at 91% win probability when they were up 3-1 (97% if you go by point differential):" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9088750000000001" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "win_series(0.55, W=3, L=1)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.966948562677312" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "win_series(win_game(SRS['Warriors'] - SRS['Cavs']), W=3, L=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Additional Calculations: Series Length\n", "\n", "Given a team's game win percentage, how many games should we expect a series to run? For example, for a team with a game win percentage of 55%, how likely is it to sweep all 4 games? To go to 7 games? Here's a chart of the probability of each possible series outcome, based on the win percentage of the first team:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "W-L | Game Win Percentage\n", " | 15% 20% 25% 30% 35% 40% 45% 50% 55% 60% 65% 70% 75% 80% 85%\n", "----+---------------------------------------------------------------------------\n", "4-0 | 0% 0% 0% 1% 2% 3% 4% 6% 9% 13% 18% 24% 32% 41% 52%\n", "4-1 | 0% 1% 1% 2% 4% 6% 9% 12% 16% 21% 25% 29% 32% 33% 31%\n", "4-2 | 0% 1% 2% 4% 6% 9% 12% 16% 19% 21% 22% 22% 20% 16% 12%\n", "4-3 | 1% 2% 3% 6% 8% 11% 14% 16% 17% 17% 15% 13% 10% 7% 4%\n", "3-4 | 4% 7% 10% 13% 15% 17% 17% 16% 14% 11% 8% 6% 3% 2% 1%\n", "2-4 | 12% 16% 20% 22% 22% 21% 19% 16% 12% 9% 6% 4% 2% 1% 0%\n", "1-4 | 31% 33% 32% 29% 25% 21% 16% 12% 9% 6% 4% 2% 1% 1% 0%\n", "0-4 | 52% 41% 32% 24% 18% 13% 9% 6% 4% 3% 2% 1% 0% 0% 0%\n" ] } ], "source": [ "def series_results(p, weight=1, W=0, L=0) -> Counter:\n", " \"\"\"Return {(win, loss): probability} for all possible outcomes of the series.\"\"\"\n", " if W == 4 or L == 4:\n", " return Counter({(W, L): weight})\n", " else:\n", " return (series_results(p, weight * p, W + 1, L)\n", " + series_results(p, weight * (1 - p), W, L+1))\n", " \n", "def series_results_table(pcts=pcts):\n", " outcomes = [(4, 0), (4, 1), (4, 2), (4, 3), (3, 4), (2, 4), (1, 4), (0, 4)]\n", " print('W-L | Game Win Percentage')\n", " print(' | ' + ' '.join(map(pct, pcts)))\n", " print('----+' + '-' * 5 * len(pcts))\n", " for (W, L) in outcomes:\n", " results = [series_results(p)[W, L] for p in pcts]\n", " print('{}-{} | {}'.format(W, L, ' '.join(map(pct, results))))\n", "\n", "series_results_table()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our hypothetical 55% team has a 9% chance of sweeping, and a 17+14 = 31% chance of going to 7 games." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.2" } }, "nbformat": 4, "nbformat_minor": 2 }