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.
- Features
- Installation
- Usage
- Examples
- Data Sources
- Web Application
- Contributing
- License
- Contact
- Acknowledgements
-
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
BaseSelector
class 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!
The released version
pip install lionel
Latest development version
pip install git+/~https://github.com/jth500/lionel.git
git clone /~https://github.com/jth500/lionel.git
cd lionel
pip install -r requirements.txt
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, ...])
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.
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])
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.
We provide a set of example scripts (located in examples/
) to demonstrate various use cases:
-
example_xv_selection.py
Demonstrates how to useXVSelector
to pick a 15-player squad from a larger candidate pool. -
example_xi_selection.py
Shows usingXISelector
to choose an 11-player lineup from a 15-player squad. -
example_update_xv.py
Demonstrates howUpdateXVSelector
can modify an existing 15-player squad, making a limited number of transfers. -
example_custom_constraints.py
Illustrates creating custom constraints withBaseSelector
for specialized optimization scenarios (e.g., ensuring at least one player from a specific team). -
model/example_fpl_points_model.py
A simple script using theFPLPointsModel
to 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.
- Fantasy Premier League (Pre-2024/25): Vaastav/Fantasy-Premier-League
- Betting Odds: The Odds API
A simple web application built with Streamlit offers a GUI to explore model predictions and recommended teams:
We welcome contributions of all kinds—whether it’s new selection strategies, improved data pipelines, or expanded analytics.
-
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.
Please adhere to our Code of Conduct to foster an inclusive environment.
This project is licensed under the MIT License.
- Email: jtobyh@gmail.com
- GitHub Issues: Issues Page
- 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