Skip to content

Commit e9b46f6

Browse files
dimakudoshdimakudosh
dimakudosh
authored and
dimakudosh
committed
Update docs
1 parent 5cad6f1 commit e9b46f6

File tree

5 files changed

+88
-70
lines changed

5 files changed

+88
-70
lines changed

docs/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pydfs-lineup-optimizer
99
======================
1010

1111
**pydfs-lineup-optimizer** is a tool for creating optimal lineups for daily fantasy sport.
12-
Currently it supports following dfs sites:
12+
Currently it supports the following dfs sites:
1313

1414
+--------+------------+---------+--------------+-------+---------+-------------------------+---------------------+------------------+
1515
| League | DraftKings | FanDuel | FantasyDraft | Yahoo | FanBall | DraftKings Captain Mode | FanDuel Single Game | DraftKings Tiers |
@@ -51,3 +51,4 @@ Contents
5151
usage
5252
rules
5353
performance-and-optimization
54+
custom-settings

docs/performance-and-optimization.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Performance and Optimization
77
Solvers
88
-------
99

10-
By default, the optimizer uses `pulp <https://coin-or.github.io/pulp/index.html>`_ library under the hood with a default solver that free but slow.
10+
By default, the optimizer uses `pulp <https://coin-or.github.io/pulp/index.html>`_ library under the hood with a default solver that is free but slow.
1111
You can change it to another solver that pulp supports.
1212
Here is an example of how to change the default solver for GLPK solver:
1313

@@ -37,16 +37,19 @@ Decrease solving complexity
3737
---------------------------
3838

3939
Sometimes optimization process takes a lot of time to generate a single lineup.
40-
It usually happens in mlb and nfl because all teams play on the same day and each team has a lot of players and a total
40+
It usually happens in mlb and nfl because all teams play on the same day and each team has a lot of players and the total
4141
number of players used in optimization is >100. In this case, a good approach is to remove from optimization players with
42-
small fppg value and big salary.
42+
small fppg value and a big salary.
4343

4444
.. code-block:: python
4545
4646
optimizer = get_optimizer(Site.DRAFTKINGS, Sport.BASEBALL)
4747
optimizer.load_players_from_csv('dk_mlb.csv')
48-
for player in optimizer.players:
49-
if player.efficiency < 1: # efficiency = fppg / salary
50-
optimizer.remove_player(player)
48+
optimizer.player_pool.add_filters(
49+
PlayerFilter(from_value=5), # use only players with points >= 5
50+
PlayerFilter(from_value=2, filter_by='efficiency'), # and efficiency(points/salary) >= 2
51+
PlayerFilter(from_value=2000, filter_by='salary'), # and salary >= 3000
52+
)
53+
optimizer.player_pool.exclude_teams(['Seattle Mariners'])
5154
for lineup in optimizer.optimize(100):
5255
print(lineup)

docs/rules.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ and `max_projected_ownership` that are max/min percent of average ownership in g
7272
.. code-block:: python
7373
7474
for player in optimizer.players:
75-
player.projected_ownership = get_projected_ownership(player) # User defined function for getting ownership percent
75+
player.projected_ownership = 0.1
7676
optimizer.set_projected_ownership(max_projected_ownership=0.6)
7777
7878
If you don't specify `projected_ownership` for some players this players will not used in calculating lineup average
@@ -225,8 +225,8 @@ create lineups with Rodgers/Adams or Brees/Thomas duos with 0.5 exposure:
225225

226226
.. code-block:: python
227227
228-
rodgers_adams_group = PlayersGroup([optimizer.get_player_by_name(name) for name in ('Aaron Rodgers', 'Davante Adams')], max_exposure=0.5)
229-
brees_thomas_group = PlayersGroup([optimizer.get_player_by_name(name) for name in ('Drew Brees', 'Michael Thomas')], max_exposure=0.5)
228+
rodgers_adams_group = PlayersGroup(optimizer.player_pool.get_players('Aaron Rodgers', 'Davante Adams'), max_exposure=0.5)
229+
brees_thomas_group = PlayersGroup(optimizer.player_pool.get_players('Drew Brees', 'Michael Thomas'), max_exposure=0.5)
230230
optimizer.add_stack(Stack([rodgers_adams_group, brees_thomas_group]))
231231
232232
Group players
@@ -236,14 +236,14 @@ Here is an example:
236236

237237
.. code-block:: python
238238
239-
group = PlayersGroup([optimizer.get_player_by_name(name) for name in ('LeBron James', 'Anthony Davis')])
239+
group = PlayersGroup(optimizer.player_pool.get_players('LeBron James', 'Anthony Davis'))
240240
optimizer.add_players_group(group)
241241
242242
You can use this method for ungrouping players as well. In this example maximum of one player will be in the lineup.
243243

244244
.. code-block:: python
245245
246-
group = PlayersGroup([optimizer.get_player_by_name(name) for name in ('LeBron James', 'Anthony Davis')], max_from_group=1)
246+
group = PlayersGroup(optimizer.player_pool.get_players('LeBron James', 'Anthony Davis'), max_from_group=1)
247247
optimizer.add_players_group(group)
248248
249249
Also you can apply these groups conditionally based on another player selection.

docs/usage.rst

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ Usage
77
Base Usage
88
----------
99
Creating optimal lineups with **pydfs-lineup-optimizer** is very simple.
10-
Firstly you should create optimizer. You can do this using
11-
shortcut get_optimizer. You must provide daily fantasy site for it and kind of sport.
12-
If site doesn't support specified sport you will get NotImplementedError.
10+
Firstly you should create an optimizer. You can do this using
11+
shortcut get_optimizer. You must provide a daily fantasy site for it and the kind of sport.
12+
If the site doesn't support the specified sport you will get NotImplementedError.
1313

1414
.. code-block:: python
1515
@@ -18,26 +18,26 @@ If site doesn't support specified sport you will get NotImplementedError.
1818
1919
optimizer = get_optimizer(Site.FANDUEL, Sport.BASKETBALL)
2020
21-
After that you need to load players into your optimizer. You have 2 options:
22-
First is to load players from CSV file like this:
21+
After that, you need to load players into your optimizer. You have 2 options:
22+
The first is to load players from CSV file like this:
2323

2424
.. code-block:: python
2525
2626
optimizer.load_players_from_csv("path_to_csv")
2727
2828
.. note::
2929

30-
CSV file must have the same format as export file in specified dfs site, if you have custom CSV file this method will not work.
31-
Also this method raises `NotImplementedError` for FanBall site because it hasn't export csv feature.
30+
CSV file must have the same format as an export file in a specified dfs site, if you have a custom CSV file this method will not work.
31+
Also, this method raises `NotImplementedError` for FanBall site because it hasn't export csv feature.
3232

3333
Or you can load players using load_players method and pass list with players.
3434

3535
.. code-block:: python
3636
3737
from pydfs_lineup_optimizer import Player
38-
optimizer.load_players(players) # players is list of Player objects
38+
optimizer.player_pool.load_players(players) # players is list of Player objects
3939
40-
After player loading you can create your optimal lineups with following code:
40+
After player loading you can create your optimal lineups with the following code:
4141

4242
.. code-block:: python
4343
@@ -64,31 +64,52 @@ Below is a full example of how **pydfs-lineup-optimizer** can be used to generat
6464
print(lineup.fantasy_points_projection)
6565
print(lineup.salary_costs)
6666
67-
Advanced Usage
68-
--------------
67+
Player Pool
68+
-----------
6969

70-
For generating optimal lineups you may need to lock some players that you want to see in your lineup.
71-
You can do this using following code:
70+
After importing players to the optimizer you may need to change parameters for some players.
71+
You can retrieve player using following methods:
7272

7373
.. code-block:: python
7474
75-
player = optimizer.get_player_by_name('Rodney Hood') # find player with specified name in your optimizer
76-
second_player = optimizer.get_player_by_id('ID00001') # find player with player id
77-
optimizer.add_player_to_lineup(player) # lock this player in lineup
78-
optimizer.add_player_to_lineup(second_player)
75+
pool = optimizer.player_pool
76+
player = pool.get_player_by_name('Tom Brady') # using player name
77+
player = pool.get_player_by_id('00000001') # using player id
78+
player = pool.get_player_by_name('Tom Brady', 'CPT') # using player name and position
7979
80-
Locked players can be unlocked as well:
80+
For player grouping, you may need to get several players at the same time, for this you can use `get_players` method:
8181

8282
.. code-block:: python
8383
84-
optimizer.remove_player_from_lineup(player)
84+
from pydfs_lineup_optimizer import PlayerFilter
85+
86+
pool = optimizer.player_pool
87+
players = pool.get_players('Tom Brady', 'Rob Gronkowski', 'Chris Godwin') # get players by name
88+
players = pool.get_players('Tom Brady', '00001', pool.get_player_by_name('Rob Gronkowski', 'CPT')) # get players using name, id and player object
89+
players = pool.get_players(PlayerFilter(positions=['QB'])) # get all QB
90+
players = pool.get_players(PlayerFilter(teams=['Tampa Bay'])) # get all players from team Tampa Bay
91+
players = pool.get_players(PlayerFilter(from_value=10, filter_by='fppg')) # get all players with points >= 10
92+
players = pool.get_players(PlayerFilter(teams=['Tampa Bay'], positions=['WR'], from_value=10)) # combined
8593
86-
Also you can exclude some players from optimization process and restore players as well:
94+
For generating optimal lineups you may need to lock some players that you want to see in your lineup.
95+
You can do this using the following code:
8796

8897
.. code-block:: python
8998
90-
optimizer.remove_player(player)
91-
optimizer.restore_player(player)
99+
optimizer.player_pool.lock_player('Tom Brady') # using player name
100+
optimizer.player_pool.lock_player('ID00001') # using player id
101+
tom_brady_captain = optimizer.player_pool.get_player_by_name('Tom Brady', position='CPT')
102+
optimizer.player_pool.lock_player(tom_brady_captain) # using player
103+
# Locked players can be unlocked as well
104+
optimizer.player_pool.unlock_player('Tom Brady')
105+
106+
Also you can exclude some players and teams from optimization process:
107+
108+
.. code-block:: python
109+
110+
optimizer.player_pool.remove_player('Tom Brady')
111+
optimizer.player_pool.restore_player('Tom Brady')
112+
optimizer.player_pool.exclude_teams(['Jets'])
92113
93114
You can specify maximum and minimum exposures for some players or max exposure for all players, you have several ways how to do this.
94115
You can add "Max Exposure" and "Min Exposure" columns with exposure percentage for some players to csv that will be parsed while players loading.
@@ -97,21 +118,20 @@ pass max_exposure parameter to optimize method
97118

98119
.. code-block:: python
99120
100-
player = optimizer.players[0] # get random player from optimizer players
121+
player = optimizer.player_pool.get_player_by_name('Tom Brady')
101122
player.max_exposure = 0.5 # set 50% max exposure
102123
player.min_exposure = 0.3 # set 30% min exposure
103-
104124
lineups = optimizer.optimize(n=10, max_exposure=0.3) # set 30% exposure for all players
105125
106126
.. note::
107127

108128
Exposure working with locked players, so if you lock some player and set max exposure to 50% percentage
109-
this player will appears only in 50% lineups.
129+
this player will appear only in 50% of lineups.
110130
Player max exposure has higher priority than max_exposure passed in optimize method.
111131
Exposure percentage rounds to ceil.
112132

113133
By default, the optimizer generates lineups based on the total number of lineups. It means if you have a player with a
114-
huge projection it will be selected only in first n lineups.
134+
huge projection it will be selected only in the first n lineups.
115135
You can change this behavior to another algorithm where exposure calculates
116136
after each generated lineup. For example, if you have a player with a huge projection and
117137
set his max_exposure to 0.5 optimizer will select him in the first lineup then skip 2 lineups with this player
@@ -133,32 +153,32 @@ After optimization you can print to console list with statistic about players us
133153
Example of advanced usage
134154
-------------------------
135155

136-
Below is an full example of how **pydfs-lineup-optimizer** can be used to generate optimal lineups with user constraints.
156+
Below is a full example of how **pydfs-lineup-optimizer** can be used to generate optimal lineups with user constraints.
137157

138158
.. code-block:: python
139159
140160
optimizer = get_optimizer(Site.YAHOO, Sport.BASKETBALL)
141161
optimizer.load_players_from_csv("yahoo-NBA.csv")
142-
nets_centers = filter(lambda p: p.team == 'Nets' and 'C' in p.positions, optimizer.players)
143-
for player in nets_centers:
144-
optimizer.remove_player(player) # Remove all Nets centers from optimizer
145-
harden = optimizer.get_player_by_name('Harden')
146-
westbrook = optimizer.get_player_by_name('Westbrook') # Get Harden and Westbrook
162+
pool = optimizer.player_pool
163+
for player in pool.get_players(PlayerFilter(positions=['C'], teams=['Nets'])):
164+
pool.remove_player(player) # Remove all Nets centers from optimizer
165+
harden = pool.get_player_by_name('Harden')
166+
westbrook = pool.get_player_by_name('Westbrook') # Get Harden and Westbrook
147167
harden.max_exposure = 0.6
148168
westbrook.max_exposure = 0.4 # Set exposures for Harden and Westbrook
149-
optimizer.add_player_to_lineup(harden)
150-
optimizer.add_player_to_lineup(westbrook) # Lock Harden and Westbrook
169+
optimizer.lock_player(harden)
170+
optimizer.lock_player(westbrook) # Lock Harden and Westbrook
151171
for lineup in optimizer.optimize(n=10, max_exposure=0.3):
152172
print(lineup)
153173
154174
Late-Swap
155175
--------------------
156176

157177
Optimizer provides additional functionality that allows to re-optimize existed lineups.
158-
Currently this feature implemented for DK and FanDuel.
159-
For this you should load lineups, you can do it from csv file generated for specific contest.
178+
Currently, this feature is implemented for DK and FanDuel.
179+
For this you should load lineups, you can do it from csv file generated for a specific contest.
160180
Then you should pass loaded lineups to `optimize_lineups` method.
161-
Players with started game will be locked on specific positions and optimizer will change only players with upcoming game.
181+
Players with the started game will be locked on specific positions and the optimizer will change only players with the upcoming game.
162182

163183
.. code-block:: python
164184
@@ -169,7 +189,7 @@ Players with started game will be locked on specific positions and optimizer wil
169189
for lineup in optimizer.optimize_lineups(lineups):
170190
print(lineup)
171191
172-
Because FanDuel doesn't provide information about locked player and games start time you should manually add information about started games like in example below:
192+
Because FanDuel doesn't provide information about locked player and games start time you should manually add information about started games like in the example below:
173193

174194
.. code-block:: python
175195
@@ -196,7 +216,7 @@ You can change it using `set_timezone` function:
196216
Export lineups
197217
==============
198218

199-
You can export lineups into a csv file. For this you should call export method of the optimizer after you generate all lineups.
219+
You can export lineups into a csv file. For this, you should call the export method of the optimizer after you generate all lineups.
200220

201221
.. code-block:: python
202222
@@ -226,22 +246,22 @@ There are several strategies already implemented in this package:
226246

227247
RandomFantasyPointsStrategy adds some deviation for players projection for creating less optimized but more randomized lineups.
228248
You can set this deviation when creating strategy by default min deviation is 0 and max deviation is 12%.
229-
You also can specify player specific deviation using `min_deviation` and `max_deviation` attributes for player,
249+
You also can specify player-specific deviation using `min_deviation` and `max_deviation` attributes for a player
230250
or using additional columns `Min Deviation` and `Max Deviation` in import csv.
231-
Also you can randomize players fppg by specifying projection range using `fppg_floor` and `fppg_ceil` attributes for player or
232-
`Projection Floor` and `Projection Ceil` csv columns. In this case this method has priority over deviation.
251+
Also, you can randomize players fppg by specifying projection range using `fppg_floor` and `fppg_ceil` attributes for player or
252+
`Projection Floor` and `Projection Ceil` csv columns. In this case, this method has priority over deviation.
233253
It works only if both fields are specified.
234254

235255
.. code-block:: python
236256
237257
optimizer.set_fantasy_points_strategy(RandomFantasyPointsStrategy(max_deviation=0.2)) # set random strategy with custom max_deviation
238-
harden = optimizer.get_player_by_name('Harden')
258+
harden = optimizer.player_pool.get_player_by_name('Harden')
239259
harden.min_deviation = 0.3
240260
harden.max_deviation = 0.6 # Set different deviation for player
241-
westbrook = optimizer.get_player_by_name('Westbrook')
261+
westbrook = optimizer.player_pool.get_player_by_name('Westbrook')
242262
westbrook.min_deviation = 0 # Disable randomness for this player
243263
westbrook.max_deviation = 0
244-
doncic = optimizer.get_player_by_name('Doncic')
264+
doncic = optimizer.player_pool.get_player_by_name('Doncic')
245265
doncic.fppg_floor = 60 # Randomize using projection range
246266
doncic.fppg_ceil = 90
247267
lineups = optimizer.optimize(n=10)
@@ -250,22 +270,21 @@ It works only if both fields are specified.
250270

251271
With RandomFantasyPointsStrategy optimizer generate lineups without ordering by max points projection.
252272

253-
ProgressiveFantasyPointsStrategy is another method to randomize optimizer result.
273+
ProgressiveFantasyPointsStrategy is another method to randomize optimizer results.
254274
It increases fantasy points for each player that wasn't used in the previous lineup by some specified percent of original fantasy points.
255-
It works cumulatively so fantasy points will be greater if player didn't used in lineup multiple times.
256-
After player will be selected to lineup his points will be reset to the original value.
257-
You can change this value for specific player by setting `progressive_scale` property of Player or by adding `Progressive Scale` column to import csv.
258-
275+
It works cumulatively so fantasy points will be greater if the player wasn't used in the lineup multiple times.
276+
After the player will be selected to lineup his points will be reset to the original value.
277+
You can change this value for a specific player by setting `progressive_scale` property of Player or by adding `Progressive Scale` column to import csv.
259278
.. code-block:: python
260279
261280
optimizer.set_fantasy_points_strategy(ProgressiveFantasyPointsStrategy(0.01)) # Set progressive strategy that increase player points by 1%
262-
optimizer.get_player_by_name('Stephen Curry').progressive_scale = 0.02 # For curry points will be increased by 2%
281+
optimizer.player_pool.get_player_by_name('Stephen Curry').progressive_scale = 0.02 # For curry points will be increased by 2%
263282
264283
Exclude lineups
265284
===============
266285

267286
You can run the optimizer several times. In this case, you probably want to avoid duplicated lineups in the result.
268-
You can provide a list of excluded lineups to optimize method.
287+
You can provide a list of excluded lineups to the optimize method.
269288
All of these lineups will be excluded from optimization and newly generated lineups will count them in max repeating players rule.
270289

271290
.. code-block:: python

example.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
from pydfs_lineup_optimizer import Site, Sport, get_optimizer, ProjectionFilter
1+
from pydfs_lineup_optimizer import Site, Sport, get_optimizer
22

33

44
optimizer = get_optimizer(Site.YAHOO, Sport.BASKETBALL)
55
optimizer.load_players_from_csv("yahoo-NBA.csv")
6-
player_pool = optimizer.player_pool
7-
player_pool.add_filters(
8-
ProjectionFilter(from_projection=20, position='QB'),
9-
ProjectionFilter(from_projection=10, position='TE'),
10-
)
116
lineup_generator = optimizer.optimize(10)
127
for lineup in lineup_generator:
138
print(lineup)

0 commit comments

Comments
 (0)