Changelog
===========
Version Numbering
###################
``penaltyblog`` follows the SemVer versioning guidelines. For more information,
see `semver.org `_
v1.9.0 (2026-02-28)
^^^^^^^^^^^^^^^^^^^^
* **New Features**
* Added ``create_dixon_coles_grid()`` function to create a ``FootballProbabilityGrid`` directly from expected goals (lambdas) and optional Dixon-Coles rho parameter. Useful when expected goals come from external ML models rather than fitted goal models.
* Added ``goal_expectancy_extended()`` function to infer implied goal expectancies AND the Dixon-Coles correlation parameter (rho) simultaneously from 1X2 and Over/Under 2.5 probabilities.
* **Bug Fixes**
* Fixed ``FootballProbabilityGrid.totals()`` to correctly handle quarter lines (e.g., 2.25, 2.75) with split-stake logic. Previously, push probability was incorrectly 0 for quarter lines.
* Fixed ``FootballProbabilityGrid.asian_handicap_probs()`` where handicap signs were inverted. Negative lines (e.g., -0.5) and positive lines (e.g., +0.5) could produce swapped win/lose probabilities.
* **Performance**
* Precomputed total goals grid in ``FootballProbabilityGrid.__post_init__`` to avoid redundant calculation in repeated ``totals()`` calls.
* Removed redundant negative fraction handling code in ``totals()`` and ``asian_handicap_probs()`` methods.
* **Documentation**
* Updated documentation to reflect quarter line support in the ``totals()`` method.
v1.8.0 (2026-01-08)
^^^^^^^^^^^^^^^^^^^^
* **Goal Models**
* Added new ``BayesianGoalModel`` and ``HierarchicalBayesianGoalModel`` models
* Added Cythonized MCMC sampler for Bayesian Modelling
* **Scraping**
* Fixed Understat scraper to use new API endpoints (getLeagueData, getMatchData, getPlayerData) instead of parsing embedded JavaScript from HTML pages
* Fixed FBRef scraper by using wrapper-tls-requests to bypass Cloudflare TLS fingerprinting protection
v1.7.1 (2025-12-24)
^^^^^^^^^^^^^^^^^^^^
* **Goal Models**
* Added add public `params_array` and `param_indices` functions to all goal models. This makes it easier to work with a model's parameters without having to rely on its internal implementation details. Thank you to Sebastian Velandia for this contribution.
v1.7.0 (2025-11-30)
^^^^^^^^^^^^^^^^^^^^
* **Opta API Integration** (``penaltyblog.matchflow.contrib.opta``):
* Added built-in integration with Stats Perform (Opta) API, allowing for lazy loading of data streams (data is fetched only on ``.collect()`` or ``.to_pandas()``).
* Added support for major endpoints including ``events``, ``matches``, ``season_stats``, ``referees``, ``standings``, and ``pass_matrix``.
* Added ``opta_helpers`` module for human-readable filtering (e.g., ``where_opta_event("Shot")``) to avoid manual ID lookups.
* Added ``get_opta_mappings()`` to explore available event types and qualifiers[cite: 23].
* Added support for authenticated access via environment variables or credential dictionaries, including proxy configuration support.
* Added documentation and examples for using the Opta API integration.
v1.6.2 (2025-10-22)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- Fixed bug in ``PoissonGoalsModel`` where weights parameter was not being handled correctly in the gradient function.
v1.6.1 (2025-10-17)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- Updated goals models loss functions to work with ``scipy 1.16+``
- Improved numerical stability of the loss function for the Negative Binomial model to improve convergence
- Added colab notebook for implied probabilities examples
- Python 3.14 support
v1.6.0 (2025-09-23)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- ``Matchflow``
- can now read / write data from cloud storage (e.g. S3, GCS, Azure Blob Storage) using ``fsspec``
- Now supports multiple join strategies:
- left, right, outer, inner and anti joins
- Automatic type inference and conversion for join keys
- Customizable type coercion functions for complex join key scenarios
- Fixed bug where where executor did not recognise ``.concat()`` function
- Updated ``implied`` submodule to add logarithmic overround removal method and return structured results
- ``Betting``
- Renamed ``kelly`` submodule to ``betting``
- Added ``multiple_criterion`` function for calculating Kelly Criterion for multiple outcomes
- Added ``arbitrage_hedge`` function to calculate hedge bet sizes
- Added ``arbitrage_opportunities`` function to identify arbitrage opportunities across bookmakers
- Added ``value_bets`` function to identify value bets based on model probabilities
- Added ``odds_conversion`` function to convert between different odds formats (decimal, fractional, American)
- Updated all betting utility functions to return structured output
Documentation Improvements
----------------------------
- Updated ``Matchflow`` documentation
- Updated ``implied`` documentation
- Updated ``betting`` documentation
- Started adding Colab notebooks for interactive examples, more to come!
v1.5.1 (2025-08-20)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- Restricted ``scipy`` to version ``<=1.15.3`` due to breaking changes in the ``minimize`` function introduced in ``1.16+``, which affect model compatibility.
v1.5.0 (2025-08-15)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- ``Pitch``
- Initial release of interactive ``Pitch`` plotting library
- ``MatchFlow``
- ``Flow`` now has it's own query language, with support for boolean expressions and field comparisons via ``.query``
- ``Goals Models``
- All Goals Model's ``.fit`` functions now take an optional dictionary of arguments to pass to scipy's optimiser
- All GoalsModels now fit using an optional gradient (defaults to True), which improves the fit time by approx 5-10x
- ``FootballProbabilityGrid``
- Updated class to include more betting markets
- Now supports fractional Asian handicaps and totals
- Optionally normalizes probabilities to sum to 1 (default: True)
- Calculations now use vectorized numpy operations for improved performance
- Caching of results for repeated queries to improve efficiency
- ``Goal Expectancy``
- Added support for removing overrounding from input probabilities
- Improved handling of edge cases in probability distributions
- Altered to using probabilities rather than odds
- Added more diagnostic output for debugging
- Optionally normalizes probabilities to sum to 1
Documentation Improvements
----------------------------
- Added Pitch documentation
- Updated Flow documentation with ``.query`` examples
- Completely rewritten documentation for Goals Models and goal expectancy
- Removed obsolete examples
v1.4.1 (2025-06-24)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- Fixed bug in `Flow.cache` executor logic
v1.4.0 (2025-06-19)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- Introduced optional ``FlowOptimizer`` for smart plan rewrites
- New ``optimize=True`` flag on all flows (off by default)
- Safe, conservative rewrites: pushdown, fusion, and simplification
- Enhanced ``.explain(compare=True)`` for before/after plan introspection
- Optimizer is backwards-compatible and fully opt-in
- Added ``.plot_plan()`` on ``Flow`` and ``FlowGroup`` to visualize pipeline structure
- ``.explain()`` now works on ``FlowGroup``, and supports ``compare=True``
- New ``.with_schema({...})`` method to cast and validate fields
- Example: ``Flow.with_schema({"x": int, "ts": parse_datetime})``
- Added ``.rolling_summary()`` to ``FlowGroup`` for windowed group summaries
(e.g. rolling 5-minute aggregates per player or team)
- Added ``.time_bucket()`` to ``FlowGroup`` for time-based binning summaries
- Added ``.show()`` method to pretty-print results using tabulate
- ``Flow.collect()`` now supports optional progress bars during execution
Documentation Improvements
--------------------------
- Refreshed documentation to include:
- ``FlowOptimizer`` and ``.optimize=True``
- ``.with_schema``, ``.rolling_summary``, ``.show()``
- Plan introspection via ``.explain(compare=True)`` and ``.plot_plan()``
- Enhanced type hints throughout the package for improved compatibility with `mypy`.
v1.3.0 (2025-05-20)
^^^^^^^^^^^^^^^^^^^^
Package Updates
-----------------
- Initial release of MatchFlow
Documentation Improvements
----------------------------
- Added MatchFlow documentation
- Added MatchFlow recipes documentation
- Added API references for all of ``penaltyblog``
- Added stub file for metric Cython code
- Added stub file for model Cython code
v1.2.0 (2025-04-10)
^^^^^^^^^^^^^^^^^^^^
Package Updates
-----------------
- Updated Elo Ratings model to be more football-specific so that it now includes home field advantage and can predict draw probabilities
- Added new Cythonised Ignorance Score metric
- Added new Cythonised Multiclass Briar Score metric
- RPS functions now raise a ValueError exception if outcome is out of bounds
Documentation Improvements
----------------------------
- Updated Elo documentation
- Added Pi Ratings documentation
- Added examples for ignorance score
- Added examples for multiclass briar score
- Updated examples for RPS
---
v1.1.0 (2025-03-15)
^^^^^^^^^^^^^^^^^^^^
Performance Enhancements
------------------------
- Rewrote Dixon-Coles model using Cython, achieving approximately 250x speed improvement.
- Rewrote Poisson model using Cython, achieving approximately 250x speed improvement.
- Implemented Negative Binomial Goals Model in Cython for enhanced performance.
- Added high-performance Cython implementation of the Bivariate Poisson Goals Model based on Karlis & Ntzoufras.
- Introduced Cython implementation of the Bivariate Weibull Count Copula Goals Model (`Boshnakov et al. paper `_).
- Added Pi Ratings System (`Constantinou paper `_).
- Migrated ranked probability score functions to Cython for improved speed.
Package Updates
---------------
- Temporarily removed Stan-based models due to dependency management challenges. Investigating improved packaging strategies for future reintegration.
- Temporarily removed Rue and Salvesen model pending revision to accurately reflect its intended methodology (previously implemented as a hybrid Dixon-Coles variant).
Documentation Improvements
--------------------------
- Updated and expanded model examples in the documentation.
- Enhanced type hints throughout the package for improved compatibility with `mypy`.
- Updated documentation to `pydata` Sphinx theme.
CI/CD and Testing
-----------------
- Expanded GitHub Actions workflows to perform unit tests across all supported Python versions.
- Extended GitHub Actions workflows to perform unit tests on Windows, macOS, and Linux.
- Configured GitHub Actions to automatically build wheels for all supported Python versions across Windows, macOS, and Linux.
---
v1.0.4 (2025-01-10)
^^^^^^^^^^^^^^^^^^^^
Package Updates
---------------
- Moved Stan code to separate files to prevent access denied issues on Windows.
---
v1.0.3 (2024-12-19)
^^^^^^^^^^^^^^^^^^^^
Bug Fixes
---------
- Fixed bug in how the Bayesian models indexed teams in the `predict` function.
- Goals models now only predict individual team names rather than iterables of team names, fixing compatibility issues between different sequence objects.
---
v1.0.2 (2024-12-18)
^^^^^^^^^^^^^^^^^^^^
Bug Fixes
---------
- Updated how the Bayesian models handle the Stan files to prevent access denied issues on Windows.
---
v1.0.1 (2024-12-13)
^^^^^^^^^^^^^^^^^^^^
Improvements
------------
- Updated `install_stan` to install the C++ toolchain on Windows if required.
---
v1.0.0 (2024-12-12)
^^^^^^^^^^^^^^^^^^^^
Performance Enhancements
------------------------
- Removed `pymc` as a dependency.
- Optimized `RPS` calculation.
- Optimized `ELO` code.
- Optimized `Kelly Criterion` code.
- Updated `FootballProbabilityGrid` to store its internal matrix as a NumPy array.
Model Updates
-------------
- Rewrote `BayesianHierarchicalGoalModel` in Stan instead of `pymc`, updating the prediction method to integrate over the posterior rather than sampling the mid-point.
- Rewrote `BayesianRandomInterceptGoalModel` in Stan, improved the random intercept, and updated the prediction method.
- Rewrote `BayesianBivariateGoalModel` in Stan for better convergence and updated the prediction method.
- Added `BayesianSkellamGoalModel` for predicting football match outcomes using the Skellam distribution.
Package Updates
---------------
- Added support for Python 3.13.
- Removed obsolete **SoFifa** and **ESPN** scrapers.
- Updated all example notebooks.
- Increased unit test coverage.
- Added CI/CD workflows.
- Removed `Poetry` from the build step.
- Updated documentation.
- Added type hinting to `Colley` and `Massey` classes.
---
v0.8.1 (2023-09-31)
^^^^^^^^^^^^^^^^^^^^
Bug Fixes
---------
- Changed FBRef `born` column to `Int64` dtype to allow `NULL` values.
---
v0.8.0 (2023-08-31)
^^^^^^^^^^^^^^^^^^^^
New Features
------------
- Added initial **Backtest framework** for backtesting betting strategies.
- Added function to calculate the **Kelly Criterion**.
- Added class for calculating **Elo ratings**.
Bug Fixes
---------
- Fixed bug in FBRef scraper for player age and year of birth.
- All goal models can now accept iterables as team inputs.
- Fixed mapping of Belgium leagues in the **FootballData** scraper.
---
v0.7.0 (2023-03-13)
^^^^^^^^^^^^^^^^^^^^
New Features
------------
- Added **FBRef scraper**.
Package Updates
---------------
- Minimum Python version supported is now **Python 3.8**.
---
v0.6.1 (2023-01-06)
^^^^^^^^^^^^^^^^^^^^
Bug Fixes
---------
- Tweaked **Understat scraper** to avoid bot detection.
---
v0.6.0 (2022-12-02)
^^^^^^^^^^^^^^^^^^^^
New Features
------------
- Added `goal_expectancy` function.
- Added **Bayesian Random Intercept Model**.
Performance Enhancements
------------------------
- Tweaked `pymc` settings for Bayesian goal models to improve speed.
Bug Fixes
---------
- Fixed bug in **Bayesian Bivariate Goals Model**.
- Fixed bug in **FootballData scraper** where a null value was breaking the index column.
---
v0.5.1 (2022-11-03)
^^^^^^^^^^^^^^^^^^^^
Bug Fixes
---------
- Fixed bug in goal models when printing an instance before fitting it.
- Fixed bug in Bayesian goal models' weighted decay.
- Fixed default value of `xi` in `dixon_coles_weights` to `0.0018`.
---
v0.5.0 (2022-10-11)
^^^^^^^^^^^^^^^^^^^^
New Features
------------
- Added `get_player_season` and `get_player_shots` to **Understat scraper**.
- Added **Bayesian Hierarchical Goal Model**.
- Added **Bayesian Bivariate Poisson Goal Model**.
- Added **Bayesian Random Intercept Poisson Goal Model**.
Bug Fixes
---------
- `get_fixtures` in **Understat scraper** now only returns completed fixtures (consistent with FootballData scraper).
- Fixed bug in **FootballData scraper** for older seasons missing the `Time` column.
Package Updates
---------------
- Added **SoFifa scraper**.
- Added compatibility for **Python 3.7**.
---
v0.4.0 (2022-08-08)
^^^^^^^^^^^^^^^^^^^^
General Improvements
--------------------
- General bug fixes.
- Reorganized internal package structure.
- Added unit tests.
- Added documentation and uploaded to **ReadTheDocs**.
New Features
------------
- Added **FPL scraper**.
- Added **FPL optimizer**.
- Added **ESPN scraper**.
- Added **Understat scraper**.
- Added **pre-commit checks** to repository.
- Added both-teams-to-score probability to football goals models.
- Refactored **FootballData scraper** for consistency with other scrapers.
- Refactored **Club Elo scraper** for consistency with other scrapers.
Performance Enhancements
------------------------
- Refactored **Colley ratings** and **Massey ratings** for consistency.
- Updated example notebooks and included them in documentation.