Skip to main content

Lionel

Lionel is a Fantasy Premier League (FPL) team optimization tool that serves two primary goals:

  1. Predict fantasy player points with 1) a library-agnostic framework, and 2) a concrete Bayesian hierarchical implementation.
  2. 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

  • 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.
  • 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:

  1. example_xv_selection.py
    Demonstrates how to use XVSelector to pick a 15-player squad from a larger candidate pool.

  2. example_xi_selection.py
    Shows using XISelector to choose an 11-player lineup from a 15-player squad.

  3. example_update_xv.py
    Demonstrates how UpdateXVSelector can modify an existing 15-player squad, making a limited number of transfers.

  4. example_custom_constraints.py
    Illustrates creating custom constraints with BaseSelector for specialized optimization scenarios (e.g., ensuring at least one player from a specific team).

  5. model/example_fpl_points_model.py
    A simple script using the FPLPointsModel to fit and predict on a tiny dataset.

  6. 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


Web Application

A simple web application built with Streamlit offers a GUI to explore model predictions and recommended teams:

https://lionel.streamlit.app/


Contributing

We welcome contributions of all kinds—whether it’s new selection strategies, improved data pipelines, or expanded analytics.

How to Contribute

  1. Fork the Repository
    Click the Fork button on the repository page.

  2. Clone Your Fork

    git clone https://github.com/your-username/lionel.git
    cd lionel
    
  3. Create a New Branch

    git checkout -b feature/your-feature-name
    
  4. Implement Your Feature
    Add or modify code in a clear, maintainable way.

  5. Commit Changes

    git commit -m "Add feature: your description"
    
  6. Push to Your Fork

    git push origin feature/your-feature-name
    
  7. 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


Acknowledgements

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)

Source distribution for lionel 0.1.1
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)

Table of built distributions (wheels) for lionel 0.1.1
File Interpreter ABI Platform Actions
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.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page