{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import pandas as pd\n", "np=pd.np\n", "from sdd_api.api import Api\n", "from credentials import *\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "api = Api(username=username, password=password, client_id=client_id, client_secret=client_secret)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What We're Going to Do\n", "1. Get salary information\n", "2. Get projected points\n", "3. Run lineup optimizer\n", "4. Tweak player pool or select highest rated lineups\n", "5. Generate lineup csv" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
seasonweek_numplayer_nameteam_namepositionopp_namefd_pointsfd_salarydk_pointsdk_salaryyh_pointsyh_salaryplayer_id
7098201716Blair WalshSEAKDAL3.04700.0NaNNaNNaNNaN23083
6785201715Ameer AbdullahDETRBCHI3.65400.05.13800.03.613.09
7279201716Chad HansenNYJWRLAC0.04500.00.03000.00.010.08941
5139201712Maxx WilliamsBALTEHOU1.74500.02.22500.01.710.024073
97320173Travis KelceKCTELAC0.67100.01.16000.00.624.011963
\n", "
" ], "text/plain": [ " season week_num player_name team_name position opp_name fd_points \\\n", "7098 2017 16 Blair Walsh SEA K DAL 3.0 \n", "6785 2017 15 Ameer Abdullah DET RB CHI 3.6 \n", "7279 2017 16 Chad Hansen NYJ WR LAC 0.0 \n", "5139 2017 12 Maxx Williams BAL TE HOU 1.7 \n", "973 2017 3 Travis Kelce KC TE LAC 0.6 \n", "\n", " fd_salary dk_points dk_salary yh_points yh_salary player_id \n", "7098 4700.0 NaN NaN NaN NaN 23083 \n", "6785 5400.0 5.1 3800.0 3.6 13.0 9 \n", "7279 4500.0 0.0 3000.0 0.0 10.0 8941 \n", "5139 4500.0 2.2 2500.0 1.7 10.0 24073 \n", "973 7100.0 1.1 6000.0 0.6 24.0 11963 " ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "salaries=api.get_dataframe(\"dfs_salaries\",season_start=2017)\n", "salaries.sample(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We're working on creating our own projections but for this example we'll use the ones published by [Fantasy Football Analytics](fantasyfootballanalytics.net). \n", "For your convenience I've already downloaded week 1 for draft kings. The whole process is as follows \n", " \n", "Go to http://apps.fantasyfootballanalytics.net\n", "- create a free account\n", "- update your scoring settings to reflect the league your interested in. \n", " -A handy guide to dfs scoring is available here https://rotogrinders.com/pages/nfl-site-scoring-comparison-357433\n", "- Set the general settings to week 1 and only the positions you have in your league. \n", "- Download custom rankings\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "salaries=salaries[salaries['week_num']==1]" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
player_namepositionpredicted_ptsriskteam_namelowerupperweek_num
0Aaron RodgersQB23.4961233.593419GB22.63000023.8971351
1Tom BradyQB22.6423423.253799NE19.82700023.9757221
2David JohnsonRB22.5466920.753315ARI20.61000023.8983481
3LeVeon BellRB21.9167831.098975PIT18.82876523.7081311
4Matt RyanQB21.8500694.874363ATL20.60000023.0960791
\n", "
" ], "text/plain": [ " player_name position predicted_pts risk team_name lower \\\n", "0 Aaron Rodgers QB 23.496123 3.593419 GB 22.630000 \n", "1 Tom Brady QB 22.642342 3.253799 NE 19.827000 \n", "2 David Johnson RB 22.546692 0.753315 ARI 20.610000 \n", "3 LeVeon Bell RB 21.916783 1.098975 PIT 18.828765 \n", "4 Matt Ryan QB 21.850069 4.874363 ATL 20.600000 \n", "\n", " upper week_num \n", "0 23.897135 1 \n", "1 23.975722 1 \n", "2 23.898348 1 \n", "3 23.708131 1 \n", "4 23.096079 1 " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dk_projections=pd.read_csv(\"data/FFA-projs-2017-week1-dk.csv\",index_col=False)[['player','position','points','risk','team','lower','upper']]\n", "dk_projections.rename(columns={'player':'player_name','points':'predicted_pts',\n", " 'team':'team_name'},inplace=True)\n", "dk_projections['team_name']=dk_projections['team_name'].replace(\"SD\",\"LAC\").replace(\"LA\",\"LAR\")\n", "dk_projections['week_num']=1\n", "dk_projections.head()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
seasonweek_numplayer_nameteam_namepositionopp_namefd_pointsfd_salarydk_pointsdk_salary...yh_salaryplayer_idmerge_nameplayer_name_ffaposition_ffapredicted_ptsriskteam_name_ffalowerupper
23720171Eric TomlinsonNYJTEBUF3.54500.04.52500.0...10.022300ERIC TOMLINSONNaNNaNNaNNaNNaNNaNNaN
25920171Ben WatsonBALTECIN0.04900.00.02800.0...11.023295BEN WATSONNaNNaNNaNNaNNaNNaNNaN
32320171Keelan ColeJACWRHOU0.04500.00.03000.0...10.04191KEELAN COLENaNNaNNaNNaNNaNNaNNaN
36620171Trey EdmundsNORBMIN0.04500.00.03000.0...10.06221TREY EDMUNDSNaNNaNNaNNaNNaNNaNNaN
\n", "

4 rows × 21 columns

\n", "
" ], "text/plain": [ " season week_num player_name team_name position opp_name fd_points \\\n", "237 2017 1 Eric Tomlinson NYJ TE BUF 3.5 \n", "259 2017 1 Ben Watson BAL TE CIN 0.0 \n", "323 2017 1 Keelan Cole JAC WR HOU 0.0 \n", "366 2017 1 Trey Edmunds NO RB MIN 0.0 \n", "\n", " fd_salary dk_points dk_salary ... yh_salary player_id \\\n", "237 4500.0 4.5 2500.0 ... 10.0 22300 \n", "259 4900.0 0.0 2800.0 ... 11.0 23295 \n", "323 4500.0 0.0 3000.0 ... 10.0 4191 \n", "366 4500.0 0.0 3000.0 ... 10.0 6221 \n", "\n", " merge_name player_name_ffa position_ffa predicted_pts risk \\\n", "237 ERIC TOMLINSON NaN NaN NaN NaN \n", "259 BEN WATSON NaN NaN NaN NaN \n", "323 KEELAN COLE NaN NaN NaN NaN \n", "366 TREY EDMUNDS NaN NaN NaN NaN \n", "\n", " team_name_ffa lower upper \n", "237 NaN NaN NaN \n", "259 NaN NaN NaN \n", "323 NaN NaN NaN \n", "366 NaN NaN NaN \n", "\n", "[4 rows x 21 columns]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def cleanNames(row):\n", " name=row['player_name']\n", " name=name.upper()\n", " if row['position'] in ['Def','DST']:\n", " #print(row)\n", " return row['team_name']\n", " else:\n", " name=name.replace(\" JR\",\"\").replace(\".\",\"\").replace(\" III\",\"\").replace(\"'\",\"\")\n", " #fix a few nicknames\n", " name=name.replace(\"PHILLY BROWN\",\"COREY BROWN\").replace(\"KEITH SMITH\", \"ROD SMITH\").replace(\"ROBERT KELLEY\", \"ROB KELLEY\")\n", " return name\n", "\n", "salaries['merge_name']=salaries.apply(cleanNames,axis=1)\n", "dk_projections['merge_name']=dk_projections.apply(cleanNames,axis=1)\n", "merged=salaries[salaries['week_num']==1].merge(dk_projections, how=\"left\", on=['merge_name','week_num'], suffixes=[\"\",\"_ffa\"])\n", "merged=merged.drop_duplicates(subset=[\"player_name\", \"position\",\"team_name\"])\n", "merged[(pd.isnull(merged['predicted_pts']))&(merged['position']!='K')]#no kickers in draft kings/dk predictions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eric Tomlinson doesn't have a prediction. Given his dk salary is 2500 we will just ignore him" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Lineup Optimizer" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from itertools import combinations,product\n", "from collections import defaultdict\n", "from operator import itemgetter, attrgetter\n", "\n", "def mapPos(row):\n", " pos=row['position']\n", " args=[]\n", " #Vectorize to make position groups easier to handle\n", " if pos=='QB':\n", " args.append(np.array((row['salary'], 1,0,0,0,0,0)))\n", " elif pos=='RB':\n", " args.append(np.array((row['salary'], 0,1,0,0,0,0)))\n", " args.append(np.array((row['salary'], 0,0,0,0,1,0)))\n", " elif pos=='WR':\n", " args.append(np.array((row['salary'], 0,0,1,0,0,0)))\n", " args.append(np.array((row['salary'], 0,0,0,0,1,0)))\n", " elif pos=='TE':\n", " args.append(np.array((row['salary'], 0,0,0,1,0,0)))\n", " args.append(np.array((row['salary'], 0,0,0,0,1,0)))\n", " elif pos=='DST':\n", " args.append(np.array((row['salary'], 0,0,0,0,0,1)))\n", " return args\n", "class Lineup:#'W/R/T':1\n", " \n", " def __init__(self,players=[]):\n", " self.rem_lookup={'QB':1,'WR':3,'RB':2,'TE':1,'DST':1}#draft kings settings\n", " self.score=0.\n", " self.predictedScore=0.\n", " self.players=players\n", " self.salary=50000\n", " for player in players:\n", " self.addFull(player)\n", " \n", " def isValid(self):\n", " if len(self.rem_lookup.keys())<=0:\n", " return True\n", " else:\n", " return False\n", " \n", " def nextPos(self):\n", " return list(self.rem_lookup.keys())[0]\n", " \n", " def addFull(self,player):\n", " pos=player['position']\n", " self.salary-=player['salary']\n", " \n", " try:\n", " self.score+=player['score']\n", " except:\n", " pass\n", " try:\n", " self.predictedScore+=player['predictedScore']\n", " except:\n", " pass\n", " \n", " def add(self,player):\n", " self.players.append(player)\n", " pos=player['position']\n", " self.rem_lookup[pos]-=1\n", " if self.rem_lookup[pos]<=0:\n", " self.rem_lookup.pop(pos)\n", " self.salary-=player['salary']\n", " print(player['predictedScore'])\n", " self.score+=player['predictedScore']\n", " def __repr__(self):\n", " names=', '.join([p['player_name'] for p in self.players])\n", " return str(self.score)+' '+str(self.predictedScore)+\" \"+str(self.salary)+' '+names\n", " def __hash__(self):\n", " l=sorted([p['player_name'] for p in self.players])\n", " strings=','.join(l)\n", " return hash(strings)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def hashPlayer(p):\n", " return p['player_name']+p['position']\n", "\n", "\n", "class lineupGenerator:\n", "\n", " def __init__(self,pool,locks=[],goodDef=[]):\n", " self.rem_lookup={'QB':1,'WR':3,'RB':2,'TE':1,'DST':1}\n", " self.score=0.\n", " keys=['QB','WR','RB','TE','DST']\n", " self.players=[]\n", " self.pool=set()\n", " self.lineups=[]\n", " self.goodDef=goodDef\n", " pDict={}\n", " self.locks=pool[pool['player_name'].isin(locks)].to_dict(orient=\"records\")\n", " for lock in self.locks:\n", " self.rem_lookup[lock['position']]-=1\n", " pool=pool[~pool['player_name'].isin(locks)]\n", " for pos,group in pool.groupby(\"position\"):\n", " pDict[pos]=group.to_dict(orient=\"records\")\n", " for p in pDict[pos]:\n", " self.pool.add(hashPlayer(p))\n", " options={pos:combinations(pDict[pos],self.rem_lookup[pos]) for pos in self.rem_lookup}\n", " self.pDict=pDict\n", " self.salary=50000\n", " lineups=[]\n", " lineups=options[keys[0]]\n", " for idx in range(1,len(keys)):\n", " lineups=product(lineups,options[keys[idx]])\n", " self.lineups=lineups\n", " \n", " def genLineups(self):\n", " for l in self.lineups:\n", " fromTeam=defaultdict(int)\n", " fromSkill=defaultdict(int)\n", " fromPos=defaultdict(int)\n", " oppDST=defaultdict(int)\n", " attempt=list(l[1]+l[0][1]+l[0][0][1]+l[0][0][0][1]+l[0][0][0][0])\n", " for lock in self.locks:\n", " attempt.append(lock)\n", " sal=0\n", " valid=True\n", " for p in attempt:\n", " if p['position']!='DST':\n", " fromTeam[p['team_name']]+=1\n", " fromPos[hashPlayer(p)]+=1\n", " oppDST[p['opp_name']]+=1\n", " if p['position']!='QB':\n", " fromSkill[p['team_name']]+=1\n", " else:\n", " if oppDST[p['team_name']]>5:#more than 1 player from team facing defense in lineup\n", " valid=False\n", " sal+=p['salary']\n", " #add flex generator that checks if in pool\n", " \n", " #unique player\n", " unique_player=all(fromPos[pos]<=1 for pos in fromPos)\n", " #3 from same team\n", " from_same=all(oppDST[t]<=4 for t in oppDST)\n", " if sal<=48000\\\n", " and unique_player\\\n", " and from_same\\\n", " and all(p['opp_name'] not in self.goodDef for p in attempt) and valid:\n", " yield attempt" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def prune(this):\n", " '''\n", " Prunes player pool to generate maximum expected value follows:\n", " if a player has a higher predicted score and lower salary, remove all players with a higher salary than the player\n", " Additionally\n", " if all position spots are unused, keep up to the remaining number of slots left\n", " with a lower score than the player we are on but higher predicted point total than the next best option\n", " Here's an example:\n", " Odell beckam salary 8000 predicted 19\n", " Alshon Jeffrey salary 7900 predicted 20\n", " Mohammed sanu salary 5100 predicted 15\n", " \n", " Because there are 3+1 spots for WR (including FLEX), we can't remove odell beckham because he would contribute more\n", " to our point total than removing him. If there was only 1 WR slot we'd be safe to remove him.\n", " \n", " '''\n", " FLEX=['WR', 'RB', 'TE']\n", " best=pd.DataFrame()\n", " this=this.sort_values(by=\"predictedScore\",ascending=False)\n", " \n", " for pos, group in this.groupby('position'):\n", " group=group.to_dict(orient='records')\n", " bad=[]\n", " for idx,best_player in enumerate(group): \n", " salary=best_player['salary']\n", " rem_lookup={'QB':1,'WR':3,'RB':2,'W/R/T':1,'TE':1,'DST':1}\n", " rem_lookup['W/R/T']+=rem_lookup[pos]\n", " for player in group[idx+1:]:\n", " if player['salary']>=salary:\n", " remove_player=False\n", " if rem_lookup[pos]<=1:\n", " remove_player=True\n", " if pos in FLEX :\n", " if rem_lookup['W/R/T']<1:\n", " remove_player=True\n", " else:\n", " remove_player=False\n", " rem_lookup['W/R/T']-=1\n", " else:\n", " rem_lookup[pos]-=1\n", " if remove_player:\n", " group.remove(player)\n", " best=pd.concat([best,pd.DataFrame(group)])\n", " best=best[this.columns]#maintain passed col order\n", " return best.sort_values(by='predictedScore', ascending=False)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
team_nameplayer_namepositionopp_namesalarypredictedScore
0ARIArizona CardinalsDSTDET2800.07.260014
\n", "
" ], "text/plain": [ " team_name player_name position opp_name salary predictedScore\n", "0 ARI Arizona Cardinals DST DET 2800.0 7.260014" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dfs=merged.copy()\n", "dfs=dfs[dfs['position']!=\"K\"][['player_name', 'team_name', 'position',\n", " 'opp_name', 'dk_salary',\n", " 'player_id', 'predicted_pts', 'lower',\n", " 'upper']]\n", "dfs['predictedScore']=dfs['predicted_pts']#you could change this to upper or lower depending on the type of lineup your looking for\n", "dfs['salary']=dfs['dk_salary']\n", "dfs=dfs[['team_name', 'player_name', 'position',\n", " 'opp_name', 'salary','predictedScore']]\n", "dfs.head(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Prune\n", "In order to speed up our lineup generator we can prune out overly expensive players. Read the comments in the prune function to get the exact description" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
team_nameplayer_namepositionopp_namesalarypredictedScore
0GBAaron RodgersQBSEA7000.023.496123
0ARIDavid JohnsonRBDET9400.022.546692
1PITLe'Veon BellRBCLE9800.021.916783
1ATLMatt RyanQBCHI6900.021.850069
2WASKirk CousinsQBPHI6400.021.002631
0PITAntonio BrownWRCLE8800.020.669101
1ATLJulio JonesWRCHI8500.020.014099
3BUFTyrod TaylorQBNYJ6200.018.318134
4DETMatthew StaffordQBARI6100.018.122957
2GBJordy NelsonWRSEA7600.017.889505
5CINAndy DaltonQBBAL5700.017.515457
2BUFLeSean McCoyRBNYJ8200.017.165540
3CINA.J. GreenWRBAL8000.016.705215
4NOMichael ThomasWRMIN7400.016.630797
3ATLDevonta FreemanRBCHI7000.016.515971
6NYGEli ManningQBDAL5600.016.209205
4LACMelvin GordonRBDEN6600.015.697834
5SEADoug BaldwinWRGB6700.015.669086
5CHIJordan HowardRBATL6300.015.435095
6DALDez BryantWRNYG7500.015.405977
7KCAlex SmithQBNE5400.015.373665
7OAKAmari CooperWRTEN7200.015.356374
8NEBrandin CooksWRKC7700.015.240044
8PHICarson WentzQBWAS5300.015.016477
9WASTerrelle PryorWRPHI6100.014.843060
10LACKeenan AllenWRDEN6100.014.780777
11DENDemaryius ThomasWRLAC6300.014.753063
12ARILarry FitzgeraldWRDET5900.014.708424
13HOUDeAndre HopkinsWRJAC5900.014.629065
14OAKMichael CrabtreeWRTEN6000.014.621326
.....................
46LACTravis BenjaminWRDEN3400.06.707451
16ARIJermaine GreshamTEDET2700.06.691666
47OAKSeth RobertsWRTEN3300.06.659285
17CHIZach MillerTEATL2800.06.652618
21INDMarlon MackRBLAR3400.06.650975
5KCKansas City ChiefsDSTNE2300.06.398443
18LARTyler HigbeeTEIND2600.06.180053
22NOAlvin KamaraRBMIN3500.05.926684
48BUFAndre HolmesWRNYJ3000.05.878436
19CHIDion SimsTEATL2500.05.808481
20OAKClive WalfordTETEN2500.05.662776
49OAKCordarrelle PattersonWRTEN3000.05.617378
21SFGarrett CelekTECAR2600.05.515040
6CHIChicago BearsDSTATL2200.05.391771
7SFSan Francisco 49ersDSTCAR2100.05.348293
23MINJerick McKinnonRBNO3200.05.305845
24CHITarik CohenRBATL3000.05.062552
50WASBrian QuickWRPHI3100.04.515122
25BALJavorius AllenRBCIN3000.04.376774
51HOUBruce EllingtonWRJAC3000.04.280907
26JACChris IvoryRBHOU3600.04.245769
13INDScott TolzienQBLAR4500.04.053128
52DALBrice ButlerWRNYG3000.03.868858
8CLECleveland BrownsDSTPIT2000.03.625214
27DENDe'Angelo HendersonRBLAC3600.03.555085
53SEALuke WillsonWRGBNaN2.948455
28SEAChris CarsonRBGBNaN2.113196
54DETT.J. JonesWRARINaN1.645612
55SEANick VannettWRGBNaN0.389983
14INDJacoby BrissettQBLAR4000.00.298763
\n", "

131 rows × 6 columns

\n", "
" ], "text/plain": [ " team_name player_name position opp_name salary predictedScore\n", "0 GB Aaron Rodgers QB SEA 7000.0 23.496123\n", "0 ARI David Johnson RB DET 9400.0 22.546692\n", "1 PIT Le'Veon Bell RB CLE 9800.0 21.916783\n", "1 ATL Matt Ryan QB CHI 6900.0 21.850069\n", "2 WAS Kirk Cousins QB PHI 6400.0 21.002631\n", "0 PIT Antonio Brown WR CLE 8800.0 20.669101\n", "1 ATL Julio Jones WR CHI 8500.0 20.014099\n", "3 BUF Tyrod Taylor QB NYJ 6200.0 18.318134\n", "4 DET Matthew Stafford QB ARI 6100.0 18.122957\n", "2 GB Jordy Nelson WR SEA 7600.0 17.889505\n", "5 CIN Andy Dalton QB BAL 5700.0 17.515457\n", "2 BUF LeSean McCoy RB NYJ 8200.0 17.165540\n", "3 CIN A.J. Green WR BAL 8000.0 16.705215\n", "4 NO Michael Thomas WR MIN 7400.0 16.630797\n", "3 ATL Devonta Freeman RB CHI 7000.0 16.515971\n", "6 NYG Eli Manning QB DAL 5600.0 16.209205\n", "4 LAC Melvin Gordon RB DEN 6600.0 15.697834\n", "5 SEA Doug Baldwin WR GB 6700.0 15.669086\n", "5 CHI Jordan Howard RB ATL 6300.0 15.435095\n", "6 DAL Dez Bryant WR NYG 7500.0 15.405977\n", "7 KC Alex Smith QB NE 5400.0 15.373665\n", "7 OAK Amari Cooper WR TEN 7200.0 15.356374\n", "8 NE Brandin Cooks WR KC 7700.0 15.240044\n", "8 PHI Carson Wentz QB WAS 5300.0 15.016477\n", "9 WAS Terrelle Pryor WR PHI 6100.0 14.843060\n", "10 LAC Keenan Allen WR DEN 6100.0 14.780777\n", "11 DEN Demaryius Thomas WR LAC 6300.0 14.753063\n", "12 ARI Larry Fitzgerald WR DET 5900.0 14.708424\n", "13 HOU DeAndre Hopkins WR JAC 5900.0 14.629065\n", "14 OAK Michael Crabtree WR TEN 6000.0 14.621326\n", ".. ... ... ... ... ... ...\n", "46 LAC Travis Benjamin WR DEN 3400.0 6.707451\n", "16 ARI Jermaine Gresham TE DET 2700.0 6.691666\n", "47 OAK Seth Roberts WR TEN 3300.0 6.659285\n", "17 CHI Zach Miller TE ATL 2800.0 6.652618\n", "21 IND Marlon Mack RB LAR 3400.0 6.650975\n", "5 KC Kansas City Chiefs DST NE 2300.0 6.398443\n", "18 LAR Tyler Higbee TE IND 2600.0 6.180053\n", "22 NO Alvin Kamara RB MIN 3500.0 5.926684\n", "48 BUF Andre Holmes WR NYJ 3000.0 5.878436\n", "19 CHI Dion Sims TE ATL 2500.0 5.808481\n", "20 OAK Clive Walford TE TEN 2500.0 5.662776\n", "49 OAK Cordarrelle Patterson WR TEN 3000.0 5.617378\n", "21 SF Garrett Celek TE CAR 2600.0 5.515040\n", "6 CHI Chicago Bears DST ATL 2200.0 5.391771\n", "7 SF San Francisco 49ers DST CAR 2100.0 5.348293\n", "23 MIN Jerick McKinnon RB NO 3200.0 5.305845\n", "24 CHI Tarik Cohen RB ATL 3000.0 5.062552\n", "50 WAS Brian Quick WR PHI 3100.0 4.515122\n", "25 BAL Javorius Allen RB CIN 3000.0 4.376774\n", "51 HOU Bruce Ellington WR JAC 3000.0 4.280907\n", "26 JAC Chris Ivory RB HOU 3600.0 4.245769\n", "13 IND Scott Tolzien QB LAR 4500.0 4.053128\n", "52 DAL Brice Butler WR NYG 3000.0 3.868858\n", "8 CLE Cleveland Browns DST PIT 2000.0 3.625214\n", "27 DEN De'Angelo Henderson RB LAC 3600.0 3.555085\n", "53 SEA Luke Willson WR GB NaN 2.948455\n", "28 SEA Chris Carson RB GB NaN 2.113196\n", "54 DET T.J. Jones WR ARI NaN 1.645612\n", "55 SEA Nick Vannett WR GB NaN 0.389983\n", "14 IND Jacoby Brissett QB LAR 4000.0 0.298763\n", "\n", "[131 rows x 6 columns]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pruned=prune(dfs)\n", "pruned" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I like to use this pruned set as a starting point and then tweak my final player pool using a custom web app I've developed -- not ready for release as of now" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "54\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
team_nameplayer_namepositionopp_namesalarypredictedScore
35HOUDeAndre HopkinsWRJAC5900.014.629065
47PHIAlshon JefferyWRWAS5800.014.134176
53ATLJulio JonesWRCHI8500.020.014099
54DETMarvin JonesWRARI4100.010.560241
58BUFZay JonesWRNYJ3500.010.168998
88BALJeremy MaclinWRCIN5000.012.654458
96BUFJordan MatthewsWRNYJ4400.011.564966
97TENRishard MatthewsWROAK4200.011.564457
156WASTerrelle PryorWRPHI6100.014.843060
168JACAllen RobinsonWRHOU5200.013.162698
174PITEli RogersWRCLE3900.07.916191
183ATLMohamed SanuWRCHI4200.010.467134
188NYGSterling ShepardWRDAL4100.010.951218
203PHITorrey SmithWRWAS3700.08.048873
258LARSammy WatkinsWRIND6200.012.617658
269CHIKevin WhiteWRATL4200.011.486123
288LARRobert WoodsWRIND4000.09.236753
292PITAntonio BrownWRCLE8800.020.669101
295ARIJohn BrownWRDET4800.010.361549
297DALDez BryantWRNYG7500.015.405977
299PITMartavis BryantWRCLE6000.08.538977
319CLESammie CoatesWRPIT3800.04.603813
333OAKAmari CooperWRTEN7200.015.356374
337OAKMichael CrabtreeWRTEN6000.014.621326
354TENEric DeckerWROAK5000.011.569751
362NEPhillip DorsettWRKC3300.05.168265
382ARILarry FitzgeraldWRDET5900.014.708424
395LARTavon AustinWRIND3800.07.921712
397SFPierre GarconWRCAR5300.012.918005
411SEAJimmy GrahamWRGBNaN12.641802
\n", "
" ], "text/plain": [ " team_name player_name position opp_name salary predictedScore\n", "35 HOU DeAndre Hopkins WR JAC 5900.0 14.629065\n", "47 PHI Alshon Jeffery WR WAS 5800.0 14.134176\n", "53 ATL Julio Jones WR CHI 8500.0 20.014099\n", "54 DET Marvin Jones WR ARI 4100.0 10.560241\n", "58 BUF Zay Jones WR NYJ 3500.0 10.168998\n", "88 BAL Jeremy Maclin WR CIN 5000.0 12.654458\n", "96 BUF Jordan Matthews WR NYJ 4400.0 11.564966\n", "97 TEN Rishard Matthews WR OAK 4200.0 11.564457\n", "156 WAS Terrelle Pryor WR PHI 6100.0 14.843060\n", "168 JAC Allen Robinson WR HOU 5200.0 13.162698\n", "174 PIT Eli Rogers WR CLE 3900.0 7.916191\n", "183 ATL Mohamed Sanu WR CHI 4200.0 10.467134\n", "188 NYG Sterling Shepard WR DAL 4100.0 10.951218\n", "203 PHI Torrey Smith WR WAS 3700.0 8.048873\n", "258 LAR Sammy Watkins WR IND 6200.0 12.617658\n", "269 CHI Kevin White WR ATL 4200.0 11.486123\n", "288 LAR Robert Woods WR IND 4000.0 9.236753\n", "292 PIT Antonio Brown WR CLE 8800.0 20.669101\n", "295 ARI John Brown WR DET 4800.0 10.361549\n", "297 DAL Dez Bryant WR NYG 7500.0 15.405977\n", "299 PIT Martavis Bryant WR CLE 6000.0 8.538977\n", "319 CLE Sammie Coates WR PIT 3800.0 4.603813\n", "333 OAK Amari Cooper WR TEN 7200.0 15.356374\n", "337 OAK Michael Crabtree WR TEN 6000.0 14.621326\n", "354 TEN Eric Decker WR OAK 5000.0 11.569751\n", "362 NE Phillip Dorsett WR KC 3300.0 5.168265\n", "382 ARI Larry Fitzgerald WR DET 5900.0 14.708424\n", "395 LAR Tavon Austin WR IND 3800.0 7.921712\n", "397 SF Pierre Garcon WR CAR 5300.0 12.918005\n", "411 SEA Jimmy Graham WR GB NaN 12.641802" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#example\n", "def toIncl(s):\n", " return s.split(\", \")\n", "inclusions=toIncl(\"Le'Veon Bell, David Johnson, Antonio Brown, Pittsburgh Steelers, Julio Jones, AJ Green, Dez Bryant, Amari Cooper, Kirk Cousins, Sammy Watkins, Terrelle Pryor, Martavis Bryant, Michael Crabtree, Todd Gurley, Larry Fitzgerald, DeAndre Hopkins, Jordan Reed, Alshon Jeffery, Pierre Garcon, Allen Robinson, Lamar Miller, Jimmy Graham, Jeremy Maclin, Eric Decker, Matt Forte, Bilal Powell, John Brown, Jared Goff, Kevin White, Rishard Matthews, Marvin Jones, Sterling Shepard, Robert Woods, Eli Rogers, Jason Witten, Sammie Coates, Will Fuller, Tavon Austin, Terrance West, Jordan Matthews, Mohamed Sanu, JJ Nelson, Torrey Smith, Jaguars, Zay Jones, Zach Ertz, Jared Cook, Phillip Dorsett, Los Angeles Rams, Brian Cook, Marquess Wilson, Austin Hooper, Vernon Davis, Lance Dunbar, Evan Engram, Zach Miller, Vance McDonald, Austin Seferian-Jenkins, Jermaine Gresham, Detroit Lions, Dion Sims, Adam Shaheen, San Francisco 49ers\")\n", "player_pool=dfs[dfs['player_name'].isin(inclusions)]\n", "print(len(player_pool))\n", "player_pool[player_pool['position']=='WR']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Constraints\n", "Next, we can impose constrains on our lineups. I'll walk through the types of supported constraints: \n", "- ONE_OF -- All lineups must contain only 1 of the players in each added list\n", "- ONLY_ONE -- All lineups can contain no more than 1 of the players in each added list\n", "- AT_LEAST -- All lineups must have at least 1 of the players in each added list\n", "\n", "Last season this was great for dealing with position groups like the Falcons Offense or the Redskins Receiving core. It was tough to say who will score but you can be quite confident they will have a touchdown. Constraints help you take advantage of that" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
team_nameplayer_namepositionopp_namesalarypredictedScore
0DENDenver BroncosDSTLAC3600.08.655786
1CARCarolina PanthersDSTSF3500.07.520136
2BALBaltimore RavensDSTCIN2800.07.454143
3INDIndianapolis ColtsDSTLAR2700.07.285907
4OAKOakland RaidersDSTTEN2500.06.774250
5KCKansas City ChiefsDSTNE2300.06.398443
6CHIChicago BearsDSTATL2200.05.391771
7SFSan Francisco 49ersDSTCAR2100.05.348293
8CLECleveland BrownsDSTPIT2000.03.625214
\n", "
" ], "text/plain": [ " team_name player_name position opp_name salary predictedScore\n", "0 DEN Denver Broncos DST LAC 3600.0 8.655786\n", "1 CAR Carolina Panthers DST SF 3500.0 7.520136\n", "2 BAL Baltimore Ravens DST CIN 2800.0 7.454143\n", "3 IND Indianapolis Colts DST LAR 2700.0 7.285907\n", "4 OAK Oakland Raiders DST TEN 2500.0 6.774250\n", "5 KC Kansas City Chiefs DST NE 2300.0 6.398443\n", "6 CHI Chicago Bears DST ATL 2200.0 5.391771\n", "7 SF San Francisco 49ers DST CAR 2100.0 5.348293\n", "8 CLE Cleveland Browns DST PIT 2000.0 3.625214" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#last years example\n", "tweaked=pruned\n", "ONE_OF=[]\n", "ONE_OF.append(['Ty Montgomery'])#forces Ty Montgomery in each lineup\n", "ONE_OF.append([\"LeGarrette Blount\",\"Dion Lewis\"])\n", "ONE_OF.append([\"Devonta Freeman\",\"Tevin Coleman\"])\n", "ONLY_ONE=[]\n", "ONLY_ONE.append(['Devonta Freeman', 'Tevin Coleman'])\n", "ONLY_ONE.append(['Antonio Brown','Eli Rogers'])#never more than one of these guys\n", "ONLY_ONE.append(['Julio Jones','Mohamed Sanu'])\n", "AT_LEAST=[]\n", "#AT_LEAST.append()\n", "locks=[]#[\"Julien Edelman\"]\n", "tweaked[tweaked['position']=='DST']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll just use locks for this example. Besides that we have some standard GPP constraints like:\n", "- don't face your starting defense\n", "- don't have too many players from one team\n", "- too many players from the same skill group on a team\n", "- our max expected value pruned player pool." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42921" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#gen lineups without flex\n", "tweaked=prune(dfs)\n", "locks=[\"Matt Ryan\",\"David Johnson\",\"Baltimore Ravens\", \"Rob Gronkowski\"]\n", "lineGen=lineupGenerator(tweaked, locks, [])\n", "lineups=lineGen.genLineups()\n", "lineups=list(lineups)\n", "HIGH_RISK_SWAPS=[]\n", "ONE_OF=[]\n", "AT_LEAST=[]\n", "ONLY_ONE=[]\n", "len(lineups)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add flex player" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.0 0\n", "0.023298618391929357 6390\n", "0.046597236783858714 19955\n", "0.06989585517578807 30532\n", "0.09319447356771743 44339\n", "0.1164930919596468 55705\n", "0.13979171035157614 70795\n", "0.1630903287435055 82151\n", "0.18638894713543486 103313\n", "0.20968756552736423 116089\n", "0.2329861839192936 129248\n", "0.25628480231122297 143191\n", "0.2795834207031523 155311\n", "0.30288203909508166 176609\n", "0.326180657487011 195047\n", "0.3494792758789404 212601\n", "0.3727778942708697 237882\n", "0.3960765126627991 259376\n", "0.41937513105472846 273899\n", "0.4426737494466578 299379\n", "0.4659723678385872 317347\n", "0.4892709862305165 341994\n", "0.5125696046224459 375628\n", "0.5358682230143752 396803\n", "0.5591668414063046 422707\n", "0.5824654597982339 457043\n", "0.6057640781901633 479318\n", "0.6290626965820927 508150\n", "0.652361314974022 539459\n", "0.6756599333659514 566522\n", "0.6989585517578808 602524\n", "0.7222571701498102 629243\n", "0.7455557885417394 664840\n", "0.7688544069336688 696454\n", "0.7921530253255982 735515\n", "0.8154516437175275 768074\n", "0.8387502621094569 806197\n", "0.8620488805013863 842271\n", "0.8853474988933157 880323\n", "0.908646117285245 921004\n", "0.9319447356771744 962802\n", "0.9552433540691037 1007226\n", "0.978541972461033 1052553\n" ] } ], "source": [ "finals=[]\n", "flex=tweaked[tweaked['position'].isin([\"WR\",\"TE\",\"RB\"])]\n", "for run,l in enumerate(lineups):\n", " if run%1000==0:\n", " print(float(run)/len(lineups),len(finals))\n", " names=[player['player_name'] for player in l]\n", " for f in flex[~flex['player_name'].isin(names)].to_dict(orient=\"records\"):\n", " final=l[:]\n", " originalPos=f['position']\n", " f['position']='FLEX'\n", " final.append(f)\n", " fromTeam=defaultdict(int)\n", " fromSkill=defaultdict(int)\n", " fromPos=defaultdict(int)\n", " fromTeamTE=defaultdict(int)\n", " oppDST=defaultdict(int)\n", " sal=0\n", " valid=True\n", " swap=0\n", " one_of=[0]*len(ONE_OF)\n", " at_least=[0]*len(AT_LEAST)\n", " only_one=[0]*len(ONLY_ONE)\n", " #ADD SWAPS. \n", " ONE_OF_COPY=ONE_OF.copy()\n", " AT_LEAST_COPY=AT_LEAST.copy()\n", " ONLY_ONE_COPY=ONLY_ONE.copy()\n", " dst=None\n", " for p in final:\n", " if p['position']=='FLEX':\n", " p[\"position\"]=originalPos\n", " if p['position']!='DST':\n", " fromTeam[p['team_name']]+=1\n", " if p['position']=='TE':\n", " fromTeamTE[p['team_name']]+=1\n", " fromPos[hashPlayer(p)]+=1\n", " oppDST[p['opp_name'].replace('@','')]+=1\n", " if p['position']!='QB':\n", " fromSkill[p['team_name']]+=1\n", " else:\n", " dst=p['team_name']\n", " sal+=p['salary']\n", " if p['player_name'] in HIGH_RISK_SWAPS:\n", " swap+=1\n", " for idx, players in enumerate(ONE_OF_COPY):\n", " if p['player_name'] in players:\n", " one_of[idx]+=1\n", " #ONE_OF_COPY.remove(players)\n", " for idx, players in enumerate(AT_LEAST_COPY):\n", " if p['player_name'] in players:\n", " at_least[idx]+=1\n", " #AT_LEAST_COPY.remove(players)\n", " for idx, players in enumerate(ONLY_ONE_COPY):\n", " if p['player_name'] in players:\n", " only_one[idx]+=1\n", " #ONLY_ONE_COPY.remove(players)\n", " #add flex generator that checks if in pool\n", " final[-1][\"position\"]=\"FLEX\"\n", " if sal<=50000 and all(fromSkill[pos]<=2 for pos in fromSkill) \\\n", " and all(fromTeamTE[team]<=1 for team in fromTeamTE)\\\n", " and all(fromPos[pos]<=1 for pos in fromPos)\\\n", " and sal>=40000 and valid and swap<=1 \\\n", " and all(one_of==1 for one_of in one_of)\\\n", " and all(at>=1 for at in at_least)\\\n", " and all(one<=1 for one in only_one):\n", " if oppDST[dst]<=1:\n", " #print(oppDST)\n", " #print(lineup)\n", " lineup=Lineup(final)\n", " finals.append(lineup)\n" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "577321" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "allHash=set()\n", "for f in finals:\n", " phash=set()\n", " for p in f.players:\n", " phash.add(p[\"player_name\"]+\",\"+p[\"team_name\"]+\",\"+str(p[\"predictedScore\"]))\n", " allHash.add(frozenset(phash))\n", "len(allHash)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inspect Lineups Generated" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "500,000 lineups! The lower number is without duplicates caused by flex vs normal spot" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": true }, "outputs": [], "source": [ "#Grab top 10 lineups\n", "finals=sorted(list(allHash)[:10],key=lambda x: sum([float(xi.split(\",\")[-1]) for xi in x]),reverse=True)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 10 0.0\n", "Player count 32\n", "Players used ['A.J. Green', 'Aaron Rodgers', 'Alex Smith', 'Alshon Jeffery', 'Alvin Kamara', 'Andre Holmes', 'Andy Dalton', 'Antonio Brown', 'Baltimore Ravens', 'Bilal Powell', 'Brandon LaFell', 'Brandon Marshall', 'Brian Hoyer', 'C.J. Anderson', 'C.J. Fiedorowicz', 'Carlos Hyde', 'Carolina Panthers', 'Carson Wentz', 'Chicago Bears', 'Chris Thompson', 'Cleveland Browns', 'Clive Walford', 'Coby Fleener', 'Cordarrelle Patterson', 'Davante Adams', 'David Johnson', 'DeAndre Hopkins', 'DeShone Kizer', 'Denver Broncos', 'Devonta Freeman', 'Dez Bryant', 'Donte Moncrief', 'Doug Baldwin', 'Eli Manning', 'Indianapolis Colts', 'James White', 'Jared Cook', 'Jarvis Landry', 'Javorius Allen', 'Jay Ajayi', 'Jeremy Maclin', 'Jerick McKinnon', 'Jermaine Gresham', 'Jordan Howard', 'Jordy Nelson', 'Josh McCown', 'Julio Jones', 'Kansas City Chiefs', 'Keenan Allen', 'Kendall Wright', 'Kenny Britt', 'Kirk Cousins', 'Kyle Rudolph', 'Larry Fitzgerald', \"Le'Veon Bell\", 'LeSean McCoy', 'Marlon Mack', 'Marquise Goodwin', 'Matt Ryan', 'Matthew Stafford', 'Melvin Gordon', 'Michael Thomas', 'Mike Glennon', 'Mike Wallace', 'Oakland Raiders', 'Odell Beckham', 'Paul Perkins', 'Rob Gronkowski', 'Robby Anderson', 'Robert Kelley', 'San Francisco 49ers', 'Scott Tolzien', 'Shane Vereen', 'Sterling Shepard', 'Tarik Cohen', 'Ted Ginn', 'Terrelle Pryor', 'Todd Gurley', 'Travis Kelce', 'Tyler Higbee', 'Tyrod Taylor', 'Zach Ertz', 'Zay Jones']\n", "83\n" ] }, { "data": { "text/plain": [ "{'Alshon Jeffery': 0.1,\n", " 'Alvin Kamara': 0.2,\n", " 'Andre Holmes': 0.3,\n", " 'Baltimore Ravens': 1.0,\n", " 'Brandon LaFell': 0.1,\n", " 'Brandon Marshall': 0.3,\n", " 'C.J. Fiedorowicz': 0.1,\n", " 'Chris Thompson': 0.2,\n", " 'Clive Walford': 0.3,\n", " 'Davante Adams': 0.1,\n", " 'David Johnson': 1.0,\n", " 'DeAndre Hopkins': 0.2,\n", " 'Devonta Freeman': 0.1,\n", " 'Dez Bryant': 0.1,\n", " 'Donte Moncrief': 0.2,\n", " 'James White': 0.2,\n", " 'Jermaine Gresham': 0.1,\n", " 'Julio Jones': 0.1,\n", " 'Keenan Allen': 0.1,\n", " 'Kenny Britt': 0.2,\n", " 'Larry Fitzgerald': 0.2,\n", " 'Marlon Mack': 0.1,\n", " 'Marquise Goodwin': 0.4,\n", " 'Matt Ryan': 1.0,\n", " 'Mike Wallace': 0.1,\n", " 'Rob Gronkowski': 1.0,\n", " 'Robby Anderson': 0.2,\n", " 'Shane Vereen': 0.2,\n", " 'Sterling Shepard': 0.2,\n", " 'Tarik Cohen': 0.2,\n", " 'Terrelle Pryor': 0.2,\n", " 'Zay Jones': 0.2}" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "new=[]\n", "for idx, f in enumerate(finals):\n", " if idx%1000==0:\n", " print(idx,len(finals), idx/len(finals))\n", " l=[]\n", " posis={\"WR\": 3,\"TE\":1,\"RB\":2}\n", " for i,n in enumerate(list(f)):\n", " p={}\n", " p[\"player_name\"]=n.split(\",\")[0]\n", " p[\"team_name\"]=n.split(\",\")[1]\n", " p['predictedScore']=float(n.split(\",\")[2])\n", " filtered=pruned[(pruned[\"player_name\"]==p[\"player_name\"])&(pruned[\"team_name\"]==p[\"team_name\"])].iloc[0]\n", " p[\"position\"]=filtered[\"position\"]\n", " p[\"salary\"]=filtered[\"salary\"]\n", " if p[\"position\"] in posis.keys():\n", " posis[p[\"position\"]]-=1\n", " if p[\"position\"] in posis.keys() and posis[p[\"position\"]]<0:\n", " p[\"position\"]=\"FLEX\"\n", " l.append(p)\n", " new.append(l)\n", "new_lineups= [Lineup(l) for l in new]\n", "sort=sorted(new_lineups,key=attrgetter(\"predictedScore\"),reverse=True)\n", "playerCounts=defaultdict(int)\n", "for l in new:\n", " for p in l:\n", " playerCounts[p[\"player_name\"]]+=1\n", "print(\"Player count\", len(playerCounts.keys()))\n", "print(\"Players used\",sorted(tweaked['player_name'].unique()))\n", "print(len(tweaked['player_name'].unique()))\n", "{key: playerCounts[key]/float(len(new)) for key in playerCounts}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our constraints we're honored. Matt Ryan, Rob Gronkowski and the Baltimore Ravens are in all of our lineups" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0.0 127.83853357199999 300.0 David Johnson, Zay Jones, Terrelle Pryor, Matt Ryan, C.J. Fiedorowicz, Baltimore Ravens, Devonta Freeman, Sterling Shepard, Rob Gronkowski,\n", " 0.0 122.81643964300002 600.0 Larry Fitzgerald, David Johnson, Matt Ryan, Marquise Goodwin, Alshon Jeffery, Kenny Britt, Baltimore Ravens, Shane Vereen, Rob Gronkowski,\n", " 0.0 121.79694265100001 2500.0 David Johnson, Brandon Marshall, Matt Ryan, Kenny Britt, Baltimore Ravens, Chris Thompson, Sterling Shepard, Rob Gronkowski, James White,\n", " 0.0 120.00725186100001 2700.0 David Johnson, Marlon Mack, Matt Ryan, Marquise Goodwin, Baltimore Ravens, Brandon Marshall, Robby Anderson, Rob Gronkowski, DeAndre Hopkins,\n", " 0.0 118.747398385 1100.0 David Johnson, Dez Bryant, Alvin Kamara, Matt Ryan, Marquise Goodwin, Brandon LaFell, Baltimore Ravens, Brandon Marshall, Rob Gronkowski,\n", " 0.0 117.52101673800001 2500.0 David Johnson, Clive Walford, Tarik Cohen, Matt Ryan, Davante Adams, Baltimore Ravens, Rob Gronkowski, Donte Moncrief, DeAndre Hopkins,\n", " 0.0 117.518967094 1200.0 Larry Fitzgerald, David Johnson, Clive Walford, Julio Jones, Tarik Cohen, Matt Ryan, Baltimore Ravens, Andre Holmes, Rob Gronkowski,\n", " 0.0 117.447469314 2800.0 David Johnson, Terrelle Pryor, Matt Ryan, Mike Wallace, Baltimore Ravens, Andre Holmes, Shane Vereen, Rob Gronkowski, James White,\n", " 0.0 112.57136247100001 6000.0 David Johnson, Jermaine Gresham, Zay Jones, Matt Ryan, Marquise Goodwin, Baltimore Ravens, Chris Thompson, Rob Gronkowski, Donte Moncrief,\n", " 0.0 109.646602266 5200.0 David Johnson, Clive Walford, Alvin Kamara, Matt Ryan, Baltimore Ravens, Keenan Allen, Andre Holmes, Robby Anderson, Rob Gronkowski]" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "new_lineups" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our highest expected value with our constraints is 127.838 points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Output Lineup CSV" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Download the draft kings lineup template by going to the lineups tab on Draft Kings.com. We've included the all game template for week 1 for your convenience" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
positionName + IDplayer_nameIDSalaryGame Infoteam_name
0RBLe'Veon Bell (9359211)LeVeon Bell93592119800PIT@CLE 01:00PM ETPIT
1RBDavid Johnson (9359235)David Johnson93592359400ARI@DET 01:00PM ETARI
2WRAntonio Brown (9358987)Antonio Brown93589878800PIT@CLE 01:00PM ETPIT
\n", "
" ], "text/plain": [ " position Name + ID player_name ID Salary \\\n", "0 RB Le'Veon Bell (9359211) LeVeon Bell 9359211 9800 \n", "1 RB David Johnson (9359235) David Johnson 9359235 9400 \n", "2 WR Antonio Brown (9358987) Antonio Brown 9358987 8800 \n", "\n", " Game Info team_name \n", "0 PIT@CLE 01:00PM ET PIT \n", "1 ARI@DET 01:00PM ET ARI \n", "2 PIT@CLE 01:00PM ET PIT " ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "id_table=pd.read_csv(\"data/dk-lineup-template-week1.csv\",skiprows=7)\n", "id_table.index=range(len(id_table))\n", "id_table.columns=range(len(id_table.columns))\n", "id_table=id_table[[9,10,11,12,13,14,15]]\n", "id_table.columns=[\"position\",\"Name + ID\",\"player_name\",\"ID\",\"Salary\",\"Game Info\",\"team_name\"]\n", "def cleanName(name):\n", " #sites handle surnames/nicknames differently. We will remove them and have verified this is ok at the time of writing\n", " return name.replace(' Jr.', '').replace(\"'\",\"\").replace(\" Sr.\",\"\")\n", "id_table['player_name']=id_table['player_name'].apply(cleanName)\n", "id_table.head(3)" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
QBRBRBWRWRWRTEFLEXDST
0935878793592359359384935999393590059359688935925193586129358762
1935878793592359358968935881493591279359122935861293589109358762
2935878793592359359150935877393589109359688935861293585769358762
3935878793592359360142935912793587739359545935861293593319358762
4935878793592359358631935893693591279358874935861293587739358762
5935878793592359360065935957293595149359331935924993586129358762
6935878793592359360065935881493590039359310935924993586129358762
7935878793592359358968935900593589149359310935861293585769358762
8935878793592359359150935999393591279359514935890093586129358762
9935878793592359358631935869693593109359545935924993586129358762
\n", "
" ], "text/plain": [ " QB RB RB WR WR WR TE FLEX \\\n", "0 9358787 9359235 9359384 9359993 9359005 9359688 9359251 9358612 \n", "1 9358787 9359235 9358968 9358814 9359127 9359122 9358612 9358910 \n", "2 9358787 9359235 9359150 9358773 9358910 9359688 9358612 9358576 \n", "3 9358787 9359235 9360142 9359127 9358773 9359545 9358612 9359331 \n", "4 9358787 9359235 9358631 9358936 9359127 9358874 9358612 9358773 \n", "5 9358787 9359235 9360065 9359572 9359514 9359331 9359249 9358612 \n", "6 9358787 9359235 9360065 9358814 9359003 9359310 9359249 9358612 \n", "7 9358787 9359235 9358968 9359005 9358914 9359310 9358612 9358576 \n", "8 9358787 9359235 9359150 9359993 9359127 9359514 9358900 9358612 \n", "9 9358787 9359235 9358631 9358696 9359310 9359545 9359249 9358612 \n", "\n", " DST \n", "0 9358762 \n", "1 9358762 \n", "2 9358762 \n", "3 9358762 \n", "4 9358762 \n", "5 9358762 \n", "6 9358762 \n", "7 9358762 \n", "8 9358762 \n", "9 9358762 " ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rows=[]\n", "POS_START={\"QB\":0,\"RB\":1,\"WR\":3,\"TE\":6,\"FLEX\":7,\"DST\":8}\n", "for l in new_lineups:\n", " row=[0]*9\n", " for p in l.players[:]:\n", " idx=POS_START[p['position']]\n", " if(idx==8):\n", " name=p[\"player_name\"].split(\" \")[-1]+\" \"#Draft kings DST's have a space after them for some reason.\n", " else:\n", " name=p[\"player_name\"]\n", " player=id_table[(id_table['player_name']==name)&(id_table['team_name']==p['team_name'])].iloc[0]\n", " if row[idx]<1:\n", " row[idx]=player['ID']\n", " else:\n", " idx+=1\n", " if row[idx]<1:\n", " row[idx]=player['ID']\n", " else:\n", " idx+=1\n", " row[idx]=player['ID']\n", "\n", " rows.append(row)\n", "output_lineups=pd.DataFrame(rows, columns=[\"QB\",\"RB\",\"RB\",\"WR\",\"WR\",\"WR\",\"TE\",\"FLEX\",\"DST\"])\n", "output_lineups" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": true }, "outputs": [], "source": [ "output_lineups.to_csv(\"data/lineupsweek1-example.csv\",index=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There you have it. All you have to do now is go to the lineups tab on draft kings and upload this sheet. \n", "I hope this served as a good example. The code needs serious refactoring, probably should just be scrapped, but this should give you a great starting point for your own lineup optimizer" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "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.6.1" } }, "nbformat": 4, "nbformat_minor": 2 }