Skip to content

Commit

Permalink
Add utils module to read data from DraftKings csv exports (#1)
Browse files Browse the repository at this point in the history
* position info for draftkings

* Revert "position info for draftkings"

This reverts commit ded1898.

* Revert "Revert "position info for draftkings""

This reverts commit ea7f132.

* import utils and constants

* add site arg, use dict to display names

* fix id indexing

* add utils to add positions from draftkings format csv

* remove salary val

* run lint

* change method name

* change method name

* return players as np.array

* update readme
  • Loading branch information
KengoA authored Feb 27, 2023
1 parent 02252dd commit ccd168f
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 172 deletions.
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,50 @@
**fantasy-ga** is a Python module and a command line tool that uses genetic algorithm to automate the generation of fantasy sports linesups. Currently supports DraftKings basketball rules.
## Installation
- Dependency
- Python >= 3.9
- `numpy`
```bash
pip install fantasy-ga
```

## Usage
Provide a `numpy.ndarray` where the columns correspond to player ID, salary, fantasy points (FPTS) and position information i.e. `player_id,salary,fpts,PG,SG,SF,PF,C,G,F,Util`.

Export a csv file from your daily fantasy basketball platform for a given contest, and read the file with `fantasy_ga.read_csv`. Currently DraftKings is supported.

Alternatively, you can provide a `numpy.array` where the columns correspond to player ID, salary, fantasy points (FPTS) and position information i.e. `id,salary,fpts,PG,SG,SF,PF,C,G,F,UTIL`.

### Python
```python
import numpy as np
from fantasy_ga import LineupGenerator
from fantasy_ga import LineupGenerator, read_csv

# load data from DraftKings salary csv
id_to_name, m = read_csv("examples/DraftKings/DKSalaries.csv", site="DraftKings")

m = np.loadtxt('examples/mat.csv', delimiter=',', skiprows=1)
# initial population of random lineups
n_pop = 1000
# number of evolutions to itererate breeding and mutation for
n_gen = 16
# number of children lineups to choose from two best lineups
n_breed = 30
# number of random mutations for each evolution
n_mutate = 30
n_gen = 16
# number of compound evolutions with additional random lineups
n_compound = 5

model = LineupGenerator(m, n_pop, n_gen, n_breed, n_mutate, n_compound)
lineups, fit = model.compound()
optimal_lineups, top_n_scores = model.get_top_n_lineups(lineups, fit, 1)
lineups, scores = model.fit()
optimal_lineups, top_n_scores = model.get_top_n_lineups(lineups, scores, 1)
```

### CLI

As a module
```
$ python -m fantasy_ga --filepath=examples/mat.csv --n_pop=100 --n_gen=5 --n_breed=100 --n_mutate=100 --n_compound=10 --top_n_lineups=1
$ python -m fantasy_ga --filepath=examples/DraftKings/DKSalarie.csv --site=DraftKings --n_pop=100 --n_gen=5 --n_breed=100 --n_mutate=100 --n_compound=10 --top_n_lineups=1
> PlayerIDs: [ 17. 106. 70. 0. 63. 33. 1. 108.], FPTS: 308.62082
```
or a command
```
$ fantasy-ga --filepath=examples/mat.csv --n_pop=100 --n_gen=5 --n_breed=100 --n_mutate=100 --n_compound=10 --top_n_lineups=1
$ fantasy-ga --filepath=examples/DraftKings/DKSalarie.csv --site=DraftKings --n_pop=100 --n_gen=5 --n_breed=100 --n_mutate=100 --n_compound=10 --top_n_lineups=1
> PlayerIDs: [ 17. 106. 70. 0. 63. 33. 1. 108.], FPTS: 308.62082
```
67 changes: 67 additions & 0 deletions examples/DraftKings/DKSalaries.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
Position,Name + ID,Name,ID,Roster Position,Salary,Game Info,TeamAbbrev,AvgPointsPerGame
C,Nikola Jokic (26802940),Nikola Jokic,26802940,C/UTIL,11800,LAC@DEN 02/26/2023 10:00PM ET,DEN,59.03
PG,Damian Lillard (26802894),Damian Lillard,26802894,PG/G/UTIL,11400,HOU@POR 02/26/2023 09:00PM ET,POR,50.91
SF/PF,Kawhi Leonard (26802907),Kawhi Leonard,26802907,SF/PF/F/UTIL,9300,LAC@DEN 02/26/2023 10:00PM ET,LAC,40.65
SG/SF,Paul George (26802900),Paul George,26802900,SG/SF/F/G/UTIL,8300,LAC@DEN 02/26/2023 10:00PM ET,LAC,42.82
PG,Jamal Murray (26802961),Jamal Murray,26802961,PG/G/UTIL,8200,LAC@DEN 02/26/2023 10:00PM ET,DEN,36.33
C,Alperen Sengun (26803068),Alperen Sengun,26803068,C/UTIL,7800,HOU@POR 02/26/2023 09:00PM ET,HOU,34.54
PG,Kevin Porter Jr. (26803006),Kevin Porter Jr.,26803006,PG/G/UTIL,7600,HOU@POR 02/26/2023 09:00PM ET,HOU,37.41
PF,Aaron Gordon (26802935),Aaron Gordon,26802935,PF/F/UTIL,7500,LAC@DEN 02/26/2023 10:00PM ET,DEN,33.40
PG/SG,Anfernee Simons (26802997),Anfernee Simons,26802997,PG/SG/G/UTIL,7200,HOU@POR 02/26/2023 09:00PM ET,POR,33.56
PG,Russell Westbrook (26802873),Russell Westbrook,26802873,PG/G/UTIL,7100,LAC@DEN 02/26/2023 10:00PM ET,LAC,37.52
PF,Jerami Grant (26802932),Jerami Grant,26802932,PF/F/UTIL,7000,HOU@POR 02/26/2023 09:00PM ET,POR,33.14
PG/SG,Jalen Green (26803059),Jalen Green,26803059,PG/SG/G/UTIL,6500,HOU@POR 02/26/2023 09:00PM ET,HOU,34.04
C,Jusuf Nurkic (26802938),Jusuf Nurkic,26802938,C/UTIL,6300,HOU@POR 02/26/2023 09:00PM ET,POR,33.11
SF,Michael Porter Jr. (26802984),Michael Porter Jr.,26802984,SF/F/UTIL,6000,LAC@DEN 02/26/2023 10:00PM ET,DEN,28.17
PF,Jabari Smith Jr. (26803082),Jabari Smith Jr.,26803082,PF/F/UTIL,5800,HOU@POR 02/26/2023 09:00PM ET,HOU,25.80
SG/SF,Norman Powell (26802924),Norman Powell,26802924,SG/SF/F/G/UTIL,5600,LAC@DEN 02/26/2023 10:00PM ET,LAC,26.06
C,Ivica Zubac (26802966),Ivica Zubac,26802966,C/UTIL,5500,LAC@DEN 02/26/2023 10:00PM ET,LAC,27.52
SF/PF,KJ Martin (26803055),KJ Martin,26803055,SF/PF/F/UTIL,5500,HOU@POR 02/26/2023 09:00PM ET,HOU,22.78
C,Mason Plumlee (26802905),Mason Plumlee,26802905,C/UTIL,5100,LAC@DEN 02/26/2023 10:00PM ET,LAC,31.69
PG/SG,Terance Mann (26802950),Terance Mann,26802950,PG/SG/G/UTIL,4600,LAC@DEN 02/26/2023 10:00PM ET,LAC,18.88
C,Drew Eubanks (26802954),Drew Eubanks,26802954,C/UTIL,4600,HOU@POR 02/26/2023 09:00PM ET,POR,16.96
SG,Kentavious Caldwell-Pope (26802917),Kentavious Caldwell-Pope,26802917,SG/G/UTIL,4500,LAC@DEN 02/26/2023 10:00PM ET,DEN,22.81
SG/SF,Bruce Brown (26802971),Bruce Brown,26802971,SG/SF/F/G/UTIL,4500,LAC@DEN 02/26/2023 10:00PM ET,DEN,24.53
PG/SG,Reggie Jackson (26802890),Reggie Jackson,26802890,PG/SG/G/UTIL,4400,LAC@DEN 02/26/2023 10:00PM ET,DEN,20.30
SG/SF,Eric Gordon (26802881),Eric Gordon,26802881,SG/SF/F/G/UTIL,4300,LAC@DEN 02/26/2023 10:00PM ET,LAC,21.95
SG/SF,Jae'Sean Tate (26802945),Jae'Sean Tate,26802945,SG/SF/F/G/UTIL,4200,HOU@POR 02/26/2023 09:00PM ET,HOU,17.81
SG/SF,Cam Reddish (26803001),Cam Reddish,26803001,SG/SF/F/G/UTIL,4100,HOU@POR 02/26/2023 09:00PM ET,POR,15.91
SF/PF,Tari Eason (26803047),Tari Eason,26803047,SF/PF/F/UTIL,4100,HOU@POR 02/26/2023 09:00PM ET,HOU,20.16
SF/PF,Nassir Little (26803015),Nassir Little,26803015,SF/PF/F/UTIL,4000,HOU@POR 02/26/2023 09:00PM ET,POR,12.72
PG/SG,Shaedon Sharpe (26803087),Shaedon Sharpe,26803087,PG/SG/G/UTIL,4000,HOU@POR 02/26/2023 09:00PM ET,POR,13.51
PG,TyTy Washington Jr. (26803079),TyTy Washington Jr.,26803079,PG/G/UTIL,3700,HOU@POR 02/26/2023 09:00PM ET,HOU,9.66
PF,Marcus Morris Sr. (26802897),Marcus Morris Sr.,26802897,PF/F/UTIL,3600,LAC@DEN 02/26/2023 10:00PM ET,LAC,22.84
SF/PF,Vlatko Cancar (26802980),Vlatko Cancar,26802980,SF/PF/F/UTIL,3600,LAC@DEN 02/26/2023 10:00PM ET,DEN,12.29
SG/SF,Matisse Thybulle (26802956),Matisse Thybulle,26802956,SG/SF/F/G/UTIL,3600,HOU@POR 02/26/2023 09:00PM ET,POR,8.29
PF/C,Nicolas Batum (26802886),Nicolas Batum,26802886,PF/C/F/UTIL,3500,LAC@DEN 02/26/2023 10:00PM ET,LAC,16.75
SG/SF,Keon Johnson (26803038),Keon Johnson,26803038,SG/SF/F/G/UTIL,3500,HOU@POR 02/26/2023 09:00PM ET,POR,8.63
C,Trendon Watford (26803024),Trendon Watford,26803024,C/UTIL,3400,HOU@POR 02/26/2023 09:00PM ET,POR,13.17
SG/SF,Josh Christopher (26803033),Josh Christopher,26803033,SG/SF/F/G/UTIL,3400,HOU@POR 02/26/2023 09:00PM ET,HOU,8.48
PF,Jeff Green (26802870),Jeff Green,26802870,PF/F/UTIL,3200,LAC@DEN 02/26/2023 10:00PM ET,DEN,14.11
PG,Ryan Arcidiacono (26802929),Ryan Arcidiacono,26802929,PG/G/UTIL,3200,HOU@POR 02/26/2023 09:00PM ET,POR,2.93
SG/SF,Christian Braun (26803019),Christian Braun,26803019,SG/SF/F/G/UTIL,3100,LAC@DEN 02/26/2023 10:00PM ET,DEN,9.93
PF/C,Jabari Walker (26803043),Jabari Walker,26803043,PF/C/F/UTIL,3100,HOU@POR 02/26/2023 09:00PM ET,POR,6.67
SG,Daishen Nix (26803063),Daishen Nix,26803063,SG/G/UTIL,3100,HOU@POR 02/26/2023 09:00PM ET,HOU,10.99
PG,Ish Smith (26802876),Ish Smith,26802876,PG/G/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,DEN,8.38
C,DeAndre Jordan (26802879),DeAndre Jordan,26802879,C/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,DEN,13.62
PF/C,Robert Covington (26802911),Robert Covington,26802911,PF/C/F/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,LAC,15.15
C,Thomas Bryant (26802964),Thomas Bryant,26802964,C/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,DEN,22.24
PF,Jack White (26802968),Jack White,26802968,PF/F/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,DEN,2.6
SF/PF,Amir Coffey (26802976),Amir Coffey,26802976,SF/PF/F/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,LAC,7.87
PG,Keaton Wallace (26802987),Keaton Wallace,26802987,PG/G/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,LAC,0
PG,Collin Gillespie (26802994),Collin Gillespie,26802994,PG/G/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,DEN,0
PG,Jason Preston (26803009),Jason Preston,26803009,PG/G/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,LAC,8.5
PG,Bones Hyland (26803026),Bones Hyland,26803026,PG/G/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,LAC,21.14
PF/C,Zeke Nnaji (26803029),Zeke Nnaji,26803029,PF/C/F/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,DEN,9.84
PG/SG,Brandon Boston Jr. (26803051),Brandon Boston Jr.,26803051,PG/SG/G/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,LAC,10.75
PF/C,Moussa Diabate (26803070),Moussa Diabate,26803070,PF/C/F/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,LAC,7.75
SG,Peyton Watson (26803074),Peyton Watson,26803074,SG/G/UTIL,3000,LAC@DEN 02/26/2023 10:00PM ET,DEN,2.73
C,Boban Marjanovic (26802915),Boban Marjanovic,26802915,C/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,HOU,5.25
PF/C,Frank Kaminsky III (26802920),Frank Kaminsky III,26802920,PF/C/F/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,HOU,6.43
SF,Justise Winslow (26802942),Justise Winslow,26802942,SF/F/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,POR,20.46
SF/PF,Kevin Knox II (26802990),Kevin Knox II,26802990,SF/PF/F/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,POR,10.24
PF,Darius Days (26803012),Darius Days,26803012,PF/F/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,HOU,6.88
C,Usman Garuba (26803066),Usman Garuba,26803066,C/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,HOU,12.35
C,John Butler (26803077),John Butler,26803077,C/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,POR,1.56
C,Ibou Badji (26803085),Ibou Badji,26803085,C/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,POR,0
PG,Trevor Hudgins (26803091),Trevor Hudgins,26803091,PG/G/UTIL,3000,HOU@POR 02/26/2023 09:00PM ET,HOU,2.8
15 changes: 6 additions & 9 deletions examples/generate_lineups.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
#!/usr/bin/env python3

import numpy as np
from fantasy_ga import LineupGenerator
from fantasy_ga import LineupGenerator, read_csv

if __name__ == "__main__":
# load data
m = np.loadtxt("examples/mat.csv", delimiter=",", skiprows=1)
# load data from DraftKings salary csv
id_to_name, m = read_csv("examples/DraftKings/DKSalaries.csv", site="DraftKings")
n_pop = 1000
n_breed = 30
n_mutate = 30
Expand All @@ -14,9 +11,9 @@
pos_start_idx = 3

model = LineupGenerator(m, n_pop, n_gen, n_breed, n_mutate, n_compound)
lineups, fit = model.compound()
optimal_lineups, top_n_scores = model.get_top_n_lineups(lineups, fit, 1)
lineups, scores = model.fit()
optimal_lineups, top_n_scores = model.get_top_n_lineups(lineups, scores, 1)

print(
f"[Optimal Lineup]\nPlayer IDs: {optimal_lineups[0]}\nFPTS: {top_n_scores[0]}"
f"Players: {[id_to_name[id] for id in optimal_lineups[0]]}\nFPTS: {top_n_scores[0]}"
)
117 changes: 0 additions & 117 deletions examples/mat.csv

This file was deleted.

6 changes: 3 additions & 3 deletions fantasy_ga/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3

from .lineup_generator import LineupGenerator
from fantasy_ga.lineup_generator import LineupGenerator
from fantasy_ga.utils import read_csv
from fantasy_ga.constants import *

__version__ = "0.1.0"
15 changes: 7 additions & 8 deletions fantasy_ga/__main__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#!/usr/bin/env python3

import argparse
import numpy as np
from .lineup_generator import LineupGenerator
from fantasy_ga.lineup_generator import LineupGenerator
from fantasy_ga.utils import read_csv


def main():
parser = argparse.ArgumentParser()
parser.add_argument("--filepath", help="filepath")
parser.add_argument("--site", help="site")
parser.add_argument("--top_n_lineups", help="filepath")
parser.add_argument("--n_pop", help="Do the bar option")
parser.add_argument("--n_gen", help="Foo the program")
Expand All @@ -18,7 +17,7 @@ def main():

args = parser.parse_args()

m = np.loadtxt(args.filepath, delimiter=",", skiprows=1)
id_to_name, m = read_csv(args.filepath, args.site)
model = LineupGenerator(
m=m,
n_pop=int(args.n_pop),
Expand All @@ -28,11 +27,11 @@ def main():
n_compound=int(args.n_compound),
)

lineups, fit = model.compound()
lineups, scores = model.get_top_n_lineups(lineups, fit, int(args.top_n_lineups))
lineups, scores = model.fit()
lineups, scores = model.get_top_n_lineups(lineups, scores, int(args.top_n_lineups))
print(f"generated top {args.top_n_lineups} lineups")
for lineup, score in zip(lineups, scores):
print(f"PlayerIDs: {lineup}, FPTS: {score}")
print(f"Players: {[id_to_name[id] for id in lineup]}, FPTS: {score}")


if __name__ == "__main__":
Expand Down
1 change: 1 addition & 0 deletions fantasy_ga/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DK_POSITIONS = ["PG", "SG", "SF", "PF", "C", "G", "F", "UTIL"]
Loading

0 comments on commit ccd168f

Please sign in to comment.