{"id":49857586,"url":"https://github.com/jotohow/lionel","last_synced_at":"2026-05-14T20:34:55.707Z","repository":{"id":176278638,"uuid":"589033063","full_name":"jotohow/lionel","owner":"jotohow","description":"A Fantasy Premier League team optimiser that uses Bayesian hierarchical modelling and linear programming.","archived":false,"fork":false,"pushed_at":"2025-07-04T12:48:29.000Z","size":5451,"stargazers_count":4,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-14T11:09:13.592Z","etag":null,"topics":["bayesian-inference","fantasy-football","linear-optimization","machine-learning"],"latest_commit_sha":null,"homepage":"https://lionel.streamlit.app/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jotohow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-14T20:54:17.000Z","updated_at":"2025-12-17T04:22:42.000Z","dependencies_parsed_at":"2023-10-20T16:47:10.401Z","dependency_job_id":"89453df8-a297-4175-87a8-74ae592047ee","html_url":"https://github.com/jotohow/lionel","commit_stats":null,"previous_names":["jth500/lionel","jotohow/lionel"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jotohow/lionel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jotohow%2Flionel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jotohow%2Flionel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jotohow%2Flionel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jotohow%2Flionel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jotohow","download_url":"https://codeload.github.com/jotohow/lionel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jotohow%2Flionel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33042367,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-14T02:00:06.663Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bayesian-inference","fantasy-football","linear-optimization","machine-learning"],"created_at":"2026-05-14T20:34:55.385Z","updated_at":"2026-05-14T20:34:55.692Z","avatar_url":"https://github.com/jotohow.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lionel\n\n**Lionel** is a Fantasy Premier League (FPL) team optimization tool that serves **two primary goals**:\n\n1. **Predict fantasy player points** with 1) a library-agnostic framework, and 2) a concrete Bayesian hierarchical implementation.\n2. **Offer an extendable selection/optimization framework** for building squads under FPL-style constraints (budget, positions, transfers, etc.).\n\nYou 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.\n\n---\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n  - [Using pip](#using-pip)\n  - [Cloning the Repository](#cloning-the-repository)\n- [Usage](#usage)\n  - [Predicting Expected Points](#predicting-expected-points)\n  - [Selecting an Optimal Team](#selecting-an-optimal-team)\n  - [Extensibility for Custom Optimization](#extensibility-for-custom-optimization)\n- [Examples](#examples)\n- [Data Sources](#data-sources)\n- [Web Application](#web-application)\n- [Contributing](#contributing)\n  - [How to Contribute](#how-to-contribute)\n  - [Code of Conduct](#code-of-conduct)\n- [License](#license)\n- [Contact](#contact)\n- [Acknowledgements](#acknowledgements)\n\n---\n\n## Features\n\n- **Bayesian Hierarchical Modeling**  \n  Predict player performance using PyMC’s No-U-Turn Sampler (or bring your own modeling approach).\n\n- **Linear Programming Optimization**  \n  Optimize team selection within budget, positional, and transfer constraints using PuLP.\n\n- **Modular \u0026 Extendable**  \n  - **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.  \n  - **Models**: Base Model classes (`LionelBaseModel`, `BaseBayesianModel`) that you can subclass to create new modeling approaches for predicting fantasy points.  \n\n- **Web Interface**  \n  Access team selections and model details via a web application.\n\n- **Open Source**  \n  Contributions are welcomed!\n\n---\n\n## Installation\n\n### Using pip\n\nThe released version\n```bash\npip install lionel\n```\n\nLatest development version\n```bash\npip install git+https://github.com/jth500/lionel.git\n```\n\n### Cloning the Repository\n\n```bash\ngit clone https://github.com/jth500/lionel.git\ncd lionel\npip install -r requirements.txt\n```\n\n---\n\n## Usage\n\n### Predicting Expected Points\n\nOne 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.\n\n```python\nimport pandas as pd\nimport numpy as np\nfrom lionel.model.bayesian.hierachical import HierarchicalPointsModel\n\n# Example data (12 rows for 2 gameweeks)\nplayer = [\"player_1\", \"player_2\", \"player_3\", \"player_4\", \"player_5\", \"player_6\"] \ngameweek = [1]*6 + [2]*6\nseason = [25]*12\nhome_team = [\"team_1\"]*6 + [\"team_2\"]*6\naway_team = [\"team_2\"]*6 + [\"team_1\"]*6\nhome_goals = [1]*6 + [2]*6\naway_goals = [0]*6 + [1]*6\nposition = [\"FWD\",\"MID\",\"DEF\",\"GK\",\"FWD\",\"MID\"]*2\nminutes = [90]*12\ngoals_scored = [1,0,0,0,0,0,0,0,1,1,0,1]\nassists = [0,1,0,0,0,0,1,0,0,0,1,1]\nis_home = [True,True,True,False,False,False,False,False,False,True,True,True]\npoints = [10,6,2,2,2,2,6,2,10,10,2,10]\n\ndf = pd.DataFrame({\n    'player': player+player,\n    'gameweek': gameweek,\n    'season': season,\n    'home_team': home_team,\n    'away_team': away_team,\n    'home_goals': home_goals,\n    'away_goals': away_goals,\n    'position': position,\n    'minutes': minutes,\n    'goals_scored': goals_scored,\n    'assists': assists,\n    'is_home': is_home\n})\n\n# Initialize and fit the model\nmodel = HierarchicalPointsModel()\nmodel.fit(df, np.array(points), progressbar=True)\n\n# Generate posterior predictive samples\npreds = model.predict(df, predictions=True)\nprint(preds)\n# np.array([5, 4, 1, ...])\n```\n\n### Selecting an Optimal Team\n\nAnother main feature is **team selection**. The project provides several specialized selectors, each inheriting from a base optimization class:\n\n- **`XVSelector`**: Pick a 15-player squad (budget, max from each team, positional constraints, plus 1 captain).  \n- **`XISelector`**: From an existing 15-player squad, select the best 11.  \n- **`UpdateXVSelector`**: Make a limited number of transfers to an existing 15-player squad.\n\n#### Example (Selecting XV)\n\n```python\nimport pandas as pd\nfrom lionel.selector.fpl.xv_selector import XVSelector \n\ndata = [\n    {\"player_id\": 1, \"name\": \"Player A1\", \"team\": \"Arsenal\", \"position\": \"GK\", \"price\": 5.0, \"predicted_points\": 50},\n    # ... more players ...\n]\ncandidate_df = pd.DataFrame(data)\n\n# Instantiate XVSelector\nselector = XVSelector(candidate_df, pred_var=\"predicted_points\", budget=1000)\noptimal_squad = selector.select()\n\nprint(\"Selected 15-player squad:\")\nprint(optimal_squad[optimal_squad[\"xv\"] == 1])\nprint(\"\\nCaptain chosen:\")\nprint(optimal_squad[optimal_squad[\"captain\"] == 1])\n```\n\n### Extensibility for Custom Optimization\n\nUnder the hood, these selectors use a **`BaseSelector`** that:\n\n- Defines binary decision variables for each player  \n- Sets an objective function (e.g., maximize total predicted points)  \n- Applies constraints (budget, positions, etc.)  \n- Solves the optimization with PuLP or another solver\n\nYou can **create your own selectors** or **custom constraints** by subclassing `BaseSelector`. For instance, you might:\n\n- Set an entirely different objective (e.g., risk-adjusted points).  \n- Enforce different constraints (e.g., “must include at least 2 defenders from Team X”).  \n\nThis modular design makes it straightforward to plug in new logic without rewriting the entire optimization code.\n\n---\n\n## Examples\n\nWe provide a set of **example scripts** (located in `examples/`) to demonstrate various use cases:\n\n1. **`example_xv_selection.py`**  \n   Demonstrates how to use `XVSelector` to pick a 15-player squad from a larger candidate pool.\n\n2. **`example_xi_selection.py`**  \n   Shows using `XISelector` to choose an 11-player lineup from a 15-player squad.\n\n3. **`example_update_xv.py`**  \n   Demonstrates how `UpdateXVSelector` can modify an existing 15-player squad, making a limited number of transfers.\n\n4. **`example_custom_constraints.py`**  \n   Illustrates creating **custom constraints** with `BaseSelector` for specialized optimization scenarios (e.g., ensuring at least one player from a specific team).\n\n5. **`model/example_fpl_points_model.py`**  \n   A simple script using the `FPLPointsModel` to fit and predict on a tiny dataset.\n\n6. **`model/example_extend_base_model.py`**  \n   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.\n\nBy 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.\n\n---\n\n## Data Sources\n\n- **Fantasy Premier League (Pre-2024/25):** [Vaastav/Fantasy-Premier-League](https://github.com/vaastav/Fantasy-Premier-League)  \n- **Betting Odds:** [The Odds API](https://the-odds-api.com)\n\n---\n\n## Web Application\n\nA simple **web application** built with Streamlit offers a GUI to explore model predictions and recommended teams:\n\n[https://lionel.streamlit.app/](https://lionel.streamlit.app/)\n\n---\n\n## Contributing\n\nWe welcome contributions of all kinds—whether it’s new selection strategies, improved data pipelines, or expanded analytics.\n\n### How to Contribute\n\n1. **Fork the Repository**  \n   Click the **Fork** button on the repository page.\n\n2. **Clone Your Fork**\n   ```bash\n   git clone https://github.com/your-username/lionel.git\n   cd lionel\n   ```\n\n3. **Create a New Branch**\n   ```bash\n   git checkout -b feature/your-feature-name\n   ```\n\n4. **Implement Your Feature**  \n   Add or modify code in a clear, maintainable way.\n\n5. **Commit Changes**\n   ```bash\n   git commit -m \"Add feature: your description\"\n   ```\n\n6. **Push to Your Fork**\n   ```bash\n   git push origin feature/your-feature-name\n   ```\n\n7. **Create a Pull Request**  \n   Open a PR from your fork to the main repository.\n\n### Code of Conduct\n\nPlease adhere to our [Code of Conduct](CODE_OF_CONDUCT.md) to foster an inclusive environment.\n\n---\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE).\n\n---\n\n## Contact\n\n- **Email:** [jtobyh@gmail.com](mailto:jtobyh@gmail.com)\n- **GitHub Issues:** [Issues Page](https://github.com/jth500/lionel/issues)\n\n---\n\n## Acknowledgements\n\n\n- **[PyMC](https://www.pymc.io/welcome.html)** for Bayesian modeling \n   - [Baio, Blangiardo (2010)](https://discovery.ucl.ac.uk/id/eprint/16040/) and [Alan Turing Institute](https://github.com/alan-turing-institute/AIrsenal) for model choice.\n- **[PuLP](https://coin-or.github.io/pulp/)** for linear programming  \n- **[Luigi](https://github.com/spotify/luigi)** for pipeline orchestration  \n- **[Vaastav/Fantasy-Premier-League](https://github.com/vaastav/Fantasy-Premier-League)** for historical FPL data  \n- **[The Odds API](https://the-odds-api.com)** for betting odds data  \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjotohow%2Flionel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjotohow%2Flionel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjotohow%2Flionel/lists"}