Lionel
Lionel is a Fantasy Premier League (FPL) team optimization tool that serves two primary goals:
- Predict fantasy player points with 1) a library-agnostic framework, and 2) a concrete Bayesian hierarchical implementation.
- Offer an extendable selection/optimization framework for building squads under FPL-style constraints (budget, positions, transfers, etc.).
You can use the existing selection classes (e.g., for picking a 15-player squad or 11-player lineup) or adapt the underlying selection logic to build new team selection strategies. The Lionel models package can be extended to build custom Bayesian (or other) models for player points, which you can then pair with the selection framework to optimize squads based on your own custom predictions.
Table of Contents
- Features
- Installation
- Usage
- Examples
- Data Sources
- Web Application
- Contributing
- License
- Contact
- Acknowledgements
Features
-
Bayesian Hierarchical Modeling
Predict player performance using PyMC’s No-U-Turn Sampler (or bring your own modeling approach). -
Linear Programming Optimization
Optimize team selection within budget, positional, and transfer constraints using PuLP. -
Modular & Extendable
- Selectors: A core
BaseSelectorclass plus specialized selectors (XV, XI, Update XV, etc.) let you add custom constraints/objectives for new or unanticipated use cases. - Models: Base Model classes (
LionelBaseModel,BaseBayesianModel) that you can subclass to create new modeling approaches for predicting fantasy points.
- Selectors: A core
-
Web Interface
Access team selections and model details via a web application. -
Open Source
Contributions are welcomed!
Installation
Using pip
pip install git+https://github.com/jth500/lionel.git
Cloning the Repository
git clone https://github.com/jth500/lionel.git
cd lionel
pip install -r requirements.txt
Usage
Predicting Expected Points
One core functionality is predicting FPL points using a Bayesian hierarchical model. You can use the provided classes—like HierarchicalPointsModel—which implements a Bayesian approach for modelling player contributions.
import pandas as pd
import numpy as np
from lionel.model.bayesian.hierachical import HierarchicalPointsModel
# Example data (12 rows for 2 gameweeks)
player = ["player_1", "player_2", "player_3", "player_4", "player_5", "player_6"]
gameweek = [1]*6 + [2]*6
season = [25]*12
home_team = ["team_1"]*6 + ["team_2"]*6
away_team = ["team_2"]*6 + ["team_1"]*6
home_goals = [1]*6 + [2]*6
away_goals = [0]*6 + [1]*6
position = ["FWD","MID","DEF","GK","FWD","MID"]*2
minutes = [90]*12
goals_scored = [1,0,0,0,0,0,0,0,1,1,0,1]
assists = [0,1,0,0,0,0,1,0,0,0,1,1]
is_home = [True,True,True,False,False,False,False,False,False,True,True,True]
points = [10,6,2,2,2,2,6,2,10,10,2,10]
df = pd.DataFrame({
'player': player+player,
'gameweek': gameweek,
'season': season,
'home_team': home_team,
'away_team': away_team,
'home_goals': home_goals,
'away_goals': away_goals,
'position': position,
'minutes': minutes,
'goals_scored': goals_scored,
'assists': assists,
'is_home': is_home
})
# Initialize and fit the model
model = HierarchicalPointsModel()
model.fit(df, np.array(points), progressbar=True)
# Generate posterior predictive samples
preds = model.predict(df, predictions=True)
print(preds)
# np.array([5, 4, 1, ...])
Selecting an Optimal Team
Another main feature is team selection. The project provides several specialized selectors, each inheriting from a base optimization class:
XVSelector: Pick a 15-player squad (budget, max from each team, positional constraints, plus 1 captain).XISelector: From an existing 15-player squad, select the best 11.UpdateXVSelector: Make a limited number of transfers to an existing 15-player squad.
Example (Selecting XV)
import pandas as pd
from lionel.selector.fpl.xv_selector import XVSelector
data = [
{"player_id": 1, "name": "Player A1", "team": "Arsenal", "position": "GK", "price": 5.0, "predicted_points": 50},
# ... more players ...
]
candidate_df = pd.DataFrame(data)
# Instantiate XVSelector
selector = XVSelector(candidate_df, pred_var="predicted_points", budget=1000)
optimal_squad = selector.select()
print("Selected 15-player squad:")
print(optimal_squad[optimal_squad["xv"] == 1])
print("\nCaptain chosen:")
print(optimal_squad[optimal_squad["captain"] == 1])
Extensibility for Custom Optimization
Under the hood, these selectors use a BaseSelector that:
- Defines binary decision variables for each player
- Sets an objective function (e.g., maximize total predicted points)
- Applies constraints (budget, positions, etc.)
- Solves the optimization with PuLP or another solver
You can create your own selectors or custom constraints by subclassing BaseSelector. For instance, you might:
- Set an entirely different objective (e.g., risk-adjusted points).
- Enforce different constraints (e.g., “must include at least 2 defenders from Team X”).
This modular design makes it straightforward to plug in new logic without rewriting the entire optimization code.
Examples
We provide a set of example scripts (located in examples/) to demonstrate various use cases:
-
example_xv_selection.py
Demonstrates how to useXVSelectorto pick a 15-player squad from a larger candidate pool. -
example_xi_selection.py
Shows usingXISelectorto choose an 11-player lineup from a 15-player squad. -
example_update_xv.py
Demonstrates howUpdateXVSelectorcan modify an existing 15-player squad, making a limited number of transfers. -
example_custom_constraints.py
Illustrates creating custom constraints withBaseSelectorfor specialized optimization scenarios (e.g., ensuring at least one player from a specific team). -
model/example_fpl_points_model.py
A simple script using theFPLPointsModelto fit and predict on a tiny dataset. -
model/example_extend_base_model.py
Shows how to extend the base Bayesian model (BaseBayesianModel) to create a brand-new custom points model for your own use case—then fit and predict with it.
By following these examples, you can see how Lionel’s modular architecture supports everything from standard FPL squad selection to completely new modeling or selection strategies.
Data Sources
- Fantasy Premier League (Pre-2024/25): Vaastav/Fantasy-Premier-League
- Betting Odds: The Odds API
Web Application
A simple web application built with Streamlit offers a GUI to explore model predictions and recommended teams:
Contributing
We welcome contributions of all kinds—whether it’s new selection strategies, improved data pipelines, or expanded analytics.
How to Contribute
-
Fork the Repository
Click the Fork button on the repository page. -
Clone Your Fork
git clone https://github.com/your-username/lionel.git cd lionel
-
Create a New Branch
git checkout -b feature/your-feature-name
-
Implement Your Feature
Add or modify code in a clear, maintainable way. -
Commit Changes
git commit -m "Add feature: your description"
-
Push to Your Fork
git push origin feature/your-feature-name
-
Create a Pull Request
Open a PR from your fork to the main repository.
Code of Conduct
Please adhere to our Code of Conduct to foster an inclusive environment.
License
This project is licensed under the MIT License.
Contact
- Email: jtobyh@gmail.com
- GitHub Issues: Issues Page
Acknowledgements
- PyMC for Bayesian modeling
- Baio, Blangiardo (2010) and Alan Turing Institute for model choice.
- PuLP for linear programming
- Luigi for pipeline orchestration
- Vaastav/Fantasy-Premier-League for historical FPL data
- The Odds API for betting odds data
Metadata
Release files for lionel 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| lionel-0.1.1.tar.gz | 19.1 kB | Without provenance | Details for lionel-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| lionel-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for lionel-0.1.1-py3-none-any.whl |
Total release size: 38.4 kB
Release files / lionel-0.1.1.tar.gz
| Download URL | lionel-0.1.1.tar.gz |
|---|---|
| Size | 19.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
48923a3e603b6f9707d434d0fa85a0c541d0b0c36582c48c6907f5e01cd3b342
|
|
BLAKE2b-256 checksum How to use checksums |
cfa813206b132587b4d0a5a38f75e59cdd80a12d8becbdfb9d4ed22437e28372
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.11.5 Darwin/22.3.0
|
Release files / lionel-0.1.1-py3-none-any.whl
| Download URL | lionel-0.1.1-py3-none-any.whl |
|---|---|
| Size | 19.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ff12e8aa5aa9f9c44a0ffd0455cdbb6f268b588ee5bb2dfc48f0a90f0f6dbf3e
|
|
BLAKE2b-256 checksum How to use checksums |
f91cf6757f491e38562221ab4a30868d20120f04bcbf4d1450b2b24d0f44d124
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.3 CPython/3.11.5 Darwin/22.3.0
|
Security for lionel 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.