This repository is a collection of optimization tutorials and recipes for Fantasy Premier League (FPL).
Python code mainly use pandas for data management and sasoptpy for optimization modeling.
It is being actively developed. The content and the structure of the repository might change.
If you are interested in using optimization for FPL, see my YouTube tutorials on the subject.
Link: https://youtube.com/playlist?list=PLrIyJJU8_viOags1yudB_wyafRuTNs1Ed
Python tutorials include following topics
- Goalkeeper selection problem
- Single-period expected value maximization (squad, lineup, captain)
- Multi-period expected value maximization (squad, lineup, captain)
- Alternative solution generation
- Multi-objective optimization (2-Step and Weight methods)
- Bench decisions
- Auto-bench weights and iterative solution for nonlinear case
- Noise in expected values
- Sensitivity analysis
- Data collection from FPL API with login
- Wildcard (chip) optimization
Link: https://youtube.com/playlist?list=PLrIyJJU8_viOLw3BovPDx5QLKkCb8XOTp
My Excel tutorials are rather short but might give you an idea what optimization is capable of doing. Reach out to me if you need the raw data to give it a try.
- Goalkeeper selection problem
- Single-period expected value maximization (squad, lineup, captain)
- Multi-period expected value maximization (squad, lineup, captain)
You will need to follow steps below to install required platform and also optimization solver (CBC).
-
Download and install Python and Git to your machine
-
Download CBC optimization solver binary and add it to your environment path (example: https://youtu.be/DFXCXoR6Dvw?t=1642)
-
Clone the repository
git clone https://github.com/sertalpbilal/FPL-Optimization-Tools.git fpl-optimization -
Install required packages
cd fpl-optimization python -m pip install -r requirements.txt -
Download FPLReview projections and save it under
dataand rename it tofplreview.csv -
Edit values inside
login.jsonfile:{ "email": "[email protected]", "password": "mypassword" }Note that logging in for Allsvenskan Fantasy does not yet work correctly, so you will have to manually get your team info and save it in a
team.jsonfile -
Navigate to
rundirectorycd ..\runAnd run either
solve_regular.py(for regular GW solve) orsolve_wildcard.py(for wildcard optimization) See instructions below. -
Log in FPL from your browser and open https://fantasy.premierleague.com/api/my-team/MY_TEAM_ID/ after replacing
MY_TEAM_IDwith your team id. Copy the content of the page intodata\team.jsonfile, by creating one.A sample team.json file is provided for your reference:
team.json.sample
-
Edit content of
data/regular_settings.jsonfile{ "api_base": "https://fantasy.allsvenskan.se", "xPts_file_path": "../data/allsvenskan_xpts.csv", "team_json": "../data/allsvenskanteam.json", "login_json": "../data/allsvenskanlogin.json", "login_url": "https://fantasy.allsvenskan.se/api/player/login/", "horizon": 5, "ft_value": 1.5, "itb_value": 0.2, "decay_base": 0.84, "no_future_transfer": true, "no_transfer_last_gws": 0, "randomized": false, "xmin_lb": 2, "ev_per_price_cutoff": 20, "bench_weights": {"0": 0.03, "1": 0.21, "2": 0.06, "3": 0.003}, "banned": [], "locked": [], "delete_tmp": true, "secs": 300, "use_cmd": false, "use_wc": null, "use_bb": null, "use_fh": null, "use_lr": null, "use_2c": null, "use_ptb": null, "chip_limits": {"bb": 0, "wc": 0, "fh": 0, "tc": 0, "lr":0, "2c":0, "ptb":0}, "future_transfer_limit": null, "no_transfer_gws": [], "booked_transfers": [], "no_chip_gws": [], "allowed_chip_gws": {"bb": [], "wc": [], "fh": [], "tc": []}, "num_transfers": null, "hit_limit": null, "preseason": false, "cbc_path": "", "no_opposing_play": false, "pick_prices": {"G": "", "D": "", "M": "", "F": ""}, "no_gk_rotation_after": null, "iteration": 1, "iteration_criteria": "this_gw_transfer_in", "datasource" : "review", "data_weights": {"review": 50, "review-odds": 25, "mikkel": 15, "kiwi": 10}, "export_data": "final.csv" }-
api_base: base url of the API. defaults tohttps://fantasy.premierleague.com -
xPts_file_path: relative path to your xPts file. defaults to../data/fplreview.csv -
team_json: relative path to your team.json file. defaults to../data/team.json -
login_json: relative path to your team.json file. defaults to../data/login.json -
login_url: url to the login endpoint. defaults tohttps://users.premierleague.com/accounts/login/ -
horizon: length of planning horizon -
ft_value: value assigned to the extra free transfer -
itb_value: value assigned to having 1.0 extra budget -
decay_base: value assigned to decay rate of expected points -
no_future_transfer:trueorfalsewhether you want to plan future transfers or not -
no_transfer_last_gws: the number of gws at the end of the period you want to ban transfers -
randomized:trueorfalsewhether you would like to add random noise to EV -
xmin_lb: cut-off for dropping players below this many minutes expectation -
ev_per_price_cutoff: cut-off percentile for dropping players based on total EV per price (e.g.20means drop players below 20% percentile) -
bench_weights: percentage weights in objective for bench players (gk and 3 outfield) -
banned: list of banned player IDs -
locked: list of player IDs to always have during the horizon (e.g.233for Salah) -
delete_tmp:trueorfalsewhether to delete generated temporary files after solve -
secs: time limit for the solve (in seconds) -
use_cmd: whether to useos.systemorsubprocessfor running solver, default isfalse -
use_wc: specify a gameweek where the solver has to use Wildcard (requires chip_limit for wc > 0) -
use_bb: specify a gameweek where the solver has to use Bench Boost (requires chip_limit for bb > 0) -
use_fh: specify a gameweek where the solver has to use Free Hit (requires chip_limit for fh > 0) -
use_tc: specify a gameweek where the solver has to use Triple Captain (requires chip_limit for tc > 0) -
use_lr: specify a gameweek where the solver has to use Loan Rangers (requires chip_limit for lr > 0) -
use_2c: specify a gameweek where the solver has to use Two Captains (requires chip_limit for 2c > 0) -
use_ptb: specify a gameweek where the solver has to use Park The Bus (requires chip_limit for ptb > 0) -
chip_limits: sets the maximum limit for chip usage. (if you're optimizing from GW1 you will need to add +1 to wc) -
booked_transfers: list of booked transfers for future gameweeks. needs to have agwkey and at least one oftransfer_inortransfer_outwith the player ID (e.g.233for Salah) -
future_transfer_limit: upper bound how many transfers are allowed in future GWs -
no_transfer_gws: list of GW numbers where transfers are not allowed -
booked_transfers: list of booked transfers for future gameweeks, needs to have agwkey and at least one oftransfer_inortransfer_outwith the player ID. For example, to book a transfer of buying Kane (427) on GW5 and selling him on GW7, use"booked_transfers": [{"gw": 5, "transfer_in": 427}, {"gw": 7, "transfer_out": 427}] -
chip_limits: how many chips of each kind can be used by solver (you need to set it to at least 1 when force using a chip) -
no_chip_gws: list of GWs to ban solver from using a chip -
allowed_chip_gws: dictionary of list of GWs to allow chips to be used. For example
"allowed_chip_gws": {"wc": [27,31]}
will allow solver to use WC in GW27 and GW31, but not in another GW -
num_transfers: fixed number of transfers for this GW -
hit_limit: limit on total hits can be taken by the solver for entire horizon -
preseason: solve flag for GW1 where team data is not important -
cbc_path: binary location of the cbc solver (binfolder) -
no_opposing_play:trueif you do not want to have players in your lineup playing against each other in a GW -
pick_prices: price points of players you want to force in a comma separated string For example, to force two 11.5M forwards, and one 8M midfielder, use"pick_prices": {"G": "", "D": "", "M": "8", "F": "11.5,11.5"} -
no_gk_rotation_after: use same lineup GK after given GW, e.g. setting this value to26means all GWs after 26 will use same lineup GK -
iteration: number of different solutions to be generated, the criteria is controlled byiteration_criteria -
iteration_criteria: rule on separating what a different solution mean, such asthis_gw_transfer_inwill force to replace player to buy current GW in each solution, whilethis_gw_transfer_in_outcan find an alternative move with either bought or sold players to be different. -
datasource:review,kiwi,mikkeloravgspecifies the data to be used.reviewrequiresfplreview.csvfilereview-oddsrequiresfplreview-odds.csvfilekiwirequireskiwi.csvfilemikkelrequiresTransferAlgorithm.csv, filemixedrequires an additional parameterdata_weights, and any corresponding files mentioned above
under
datafolder to be present -
data_weights: weight percentage for each data source, given as a dictionary, where keys should be one of valid data sources -
export_data: option for exporting final data as a CSV file (when usingmixeddata)
-
-
Run the multi-period optimization
python solve_regular.py
-
Find the optimal plans under
data\resultsdirectory with timestamp> cd ../data/results > ls regular_2021-11-04_10-00-00.csv
A Dockerised version of the solver is included in this repo which includes all dependencies required to run the program and save results. Docker must be installed on the host machine.
In order to run the solver via Docker, you'll firstly need to follow the instructions in the Installation Steps section to add the following files to the /data folder:
team.jsonregular_settings.jsonfplreview.csv
Then, to pull the Docker image, build it, and then run the solver, simply run the following command:
> docker-compose upAfter the initial setup, re-running this command will skip the pull and build steps and simply run the solver.