penaltyblog: Football Data & Modelling

repository·master·Indexed 41 days ago

https://github.com/martineastwood/penaltyblog

A high-performance Python package optimized with Cython for football (soccer) analytics. Version 1.12.2 provides tools for data scraping (Understat, Club Elo, FPL), streaming JSON processing via MatchFlow, and statistical modelling including Poisson, Bivariate Poisson, and Dixon-Coles models. It includes capabilities for team ratings (Elo, Massey, Colley, Pi), betting probability estimation, arbitrage hedging, and publication-ready pitch visualizations.

Tokens
58.4K
Snippets
233
Records
291
Agent score
54%

What's inside penaltyblog

  1. Overview of MatchFlow workflows

    master

    MatchFlow is used to explore and analyze StatsBomb event data through end-to-end workflows. The typical pattern involves three stages:

    1. Loading data: Importing event data (e.g., via the StatsBomb API).
    2. Transforming data: Using the Flow object to filter, group, or aggregate events.
    3. Outputting data: Visualizing results (e.g., shot maps, pass maps) or exporting them for reporting and machine learning.
  2. Overview of penaltyblog features

    master

    penaltyblog is a high-performance Python package optimized with Cython for football (soccer) analytics. Key capabilities include:

    • MatchFlow: A lazy, streaming pipeline for processing large, nested JSON football datasets (filtering, selecting, flattening, joining, etc.).
    • API Connectivity: Direct streaming and filtering from professional providers like StatsBomb and Opta.
    • Statistical Modelling: High-performance implementations of Poisson, Bivariate Poisson, and Dixon-Coles models, as well as advanced Bayesian and Hierarchical Bayesian modelling using MCMC sampling.
    • Data Scraping: Tools to collect statistics from Understat, Club Elo, and Fantasy Premier League.
    • Betting & Odds: Estimation of probabilities for Asian handicaps, over/under totals, and match outcomes, plus tools to decode bookmaker odds by removing margins (overrounds).
    • Team Ratings: Calculation of Elo, Massey, Colley, and Pi ratings.
    • Optimization & Visualization: Fantasy football squad optimization and publication-ready pitch visualizations.
  3. Calculate football model performance metrics

    master

    The penaltyblog library provides utility functions to evaluate the performance of football (soccer) model predictions. Key metrics available include:

    • Ranked Probability Score (RPS): A standard metric for measuring the accuracy of probabilistic forecasts in football.
    • Brier Score: Used to measure the accuracy of probabilistic predictions.
    • Ignorance Score: A logarithmic scoring rule for evaluating probability forecasts.

    For a deep dive into selecting the right metrics for football analytics, refer to the external guide: https://pena.lt/y/2025/05/01/better-metrics-for-football-forecasts-moving-beyond-the-ranked-probability-score/

  4. Use Betting Utilities for bet sizing and portfolio management

    master

    The betting submodule in penaltyblog provides a suite of tools designed for professional betting workflows. It includes utilities for:

    • Arbitrage Hedging: Calculating hedges to lock in profits when multiple outcomes are available.
    • Arbitrage Detection: Identifying arbitrage opportunities across different markets.
    • Bet Sizing: Determining optimal stake amounts using the Kelly Criterion.
    • Value Betting: Identifying bets where the probability of an outcome is higher than the implied probability of the odds.
    • Odds Conversion: Converting between different odds formats (e.g., Decimal to Fractional or American).
  5. Explore the MatchFlow API modules

    master

    MatchFlow is a sub-package within penaltyblog designed for football data processing and modeling. The API is organized into several functional modules:

    • Core Logic: penaltyblog.matchflow.flow handles the execution flow, while penaltyblog.matchflow.executor manages how processes are run.
    • Data Transformation: penaltyblog.matchflow.steps contains specialized modules for different stages of a data pipeline:
      • steps.source: For ingesting data.
      • steps.transform: For modifying data.
      • steps.group: For grouping data.
      • steps.utils: Utility functions for steps.
    • Analysis & Logic: penaltyblog.matchflow.predicates and penaltyblog.matchflow.predicates_helpers provide logical conditions for data filtering or evaluation.
    • Data Management: penaltyblog.matchflow.group handles data grouping operations.
    • Optimization & Helpers: penaltyblog.matchflow.optimizer provides performance improvements, and penaltyblog.matchflow.helpers contains general utility functions.
    • Visualization: penaltyblog.matchflow.plotting is used for generating visual representations of data.
    • Integrations: penaltyblog.matchflow.contrib.statsbomb provides specific support/contributions for StatsBomb data formats.
  6. Use Goal Models for football match predictions

    master

    The penaltyblog library provides statistical models designed to predict football (soccer) match outcomes. These models generate probability estimates for several betting markets, including:

    • Match results (e.g., Home/Draw/Away)
    • Total goals
    • Asian handicaps
    • Over/under goals

    For deep theoretical understanding and foundational research papers related to these models, refer to the documentation available at http://www.pena.lt/y/blog.html.

  7. What is the Ranked Probability Score (RPS)?

    master

    The Ranked Probability Score (RPS) is a metric for evaluating probabilistic predictions of ordinal outcomes (where outcomes have a natural order, such as Win > Draw > Loss).

    Key Characteristics:

    • Distribution-based: Unlike simple accuracy, it accounts for the entire probability distribution.
    • Ordinal Sensitivity: It penalizes predictions based on how "wrong" they are relative to the order. For example, predicting a home win when the result is a draw incurs a smaller penalty than predicting a home win when the away team wins.
    • Mathematical Basis: It is calculated as the sum of squared differences between the cumulative probability distributions of the predicted and observed outcomes.
    • Use Case: Highly valuable in soccer analytics for evaluating betting models and prediction systems because it rewards models that assign high probabilities to outcomes "close" to the actual result.
  8. What is Flow and how does it differ from pandas?

    master

    Concept: Flow vs. DataFrames

    Flow is a stream-first, nested-data engine designed specifically for irregular, event-based JSON (like football event data). Unlike pandas, which requires data to be flattened into rigid tables (DataFrames) for processing, Flow treats nested JSON as a first-class citizen.

    Key Differences:

    • Structure: pandas requires premature normalization (flattening), which can lead to key collisions and loss of hierarchy. Flow embraces nesting, allowing you to work with the natural hierarchy of the data (e.g., a match containing events, which contain players).
    • Flexibility: pandas.json_normalize() can be brittle when dealing with inconsistent schemas, mixed types, or optional nesting (like variable-length freeze frames). Flow is schema-flexible and can handle different provider formats (Opta, StatsBomb, Wyscout) without overfitting.
    • Workflow: Instead of flattening first, Flow allows you to query, filter, and transform nested records directly, deferring flattening until the very end of your pipeline (e.g., when exporting to a BI tool or performing vectorized operations).

    When to use which:

    • Use Flow for exploring, querying, and transforming raw, nested event data.
    • Use Flattening/Pandas for building reports, BI tool exports, or when you need fast vectorized operations like model training.
  9. What is Flow?

    master

    Flow is a lightweight, lazy query engine designed for processing deeply nested football data (like event data, freeze frames, or tracking points) without requiring early normalization or flattening.

    Unlike a dataframe, Flow acts as a pipeline builder. It constructs an internal execution plan of transformations and only processes the data when an action is explicitly requested. This allows you to work with nested JSON structures using natural field access (e.g., "player.name") and chainable operations.

  10. Overview of the different goal models in penaltyblog

    master

    The penaltyblog package provides a suite of Cython-optimized statistical models for predicting football match scores. All models share a consistent API, allowing you to swap between them easily for benchmarking or fine-tuning.

    Available Models

    ModelBest Used For
    PoissonGeneral forecasting (simple, efficient baseline)
    Dixon & ColesLow-scoring leagues (corrects low-score bias)
    Bivariate PoissonHigh-scoring leagues (models score correlation)
    Zero-Inflated PoissonDefensive teams (improves accuracy for goalless matches)
    Negative BinomialHigh-scoring, volatile leagues (handles overdispersion)
    Weibull + CopulaComplex goal patterns (flexible distribution & correlation)
    BayesianSmall datasets, understanding uncertainty (captures parameter uncertainty)
    Hierarchical BayesianSparse data, multi-league (learns league-wide priors)
  11. What is MatchFlow?

    master

    MatchFlow is a stream-first query engine designed for irregular, event-based football data (such as nested JSON from StatsBomb or Opta). Unlike a DataFrame, MatchFlow is built to handle deeply nested structures without requiring early flattening.

    Key characteristics:

    • Lazy Execution: Transformations are only executed when you explicitly materialize the results using methods like .collect(), .to_pandas(), or .to_jsonl().
    • Chainable API: You can build complex pipelines by chaining methods like .filter(), .assign(), .select(), and .group_by().
    • Nested Data Support: It allows working directly with nested JSON fields and supports advanced operations like exploding lists, splitting arrays, and pivoting rows.
    • String Expressions: Supports filtering via string expressions (e.g., "age > 30 and team == @team_name").
  12. How the MatchFlow Optimizer safety model works

    master

    The optimizer is safe-by-default and uses a conservative approach to ensure that user-defined logic remains correct. It makes no assumptions about commutativity, determinism, or purity of user functions.

    Safe to optimize

    Structural plan steps that are generally safe to reorder include:

    • select()
    • drop()
    • limit()
    • filter() (when independent)
    • sort()
    • group_by()

    Not assumed safe to reorder

    The optimizer will not reorder these steps because they may contain side effects or depend on execution order:

    • map()
    • assign()
    • User-defined filter() with non-trivial predicates
    • Any lambdas or custom functions

    Syntactic Fusion

    While the optimizer avoids reordering unsafe steps, it performs syntactic fusion. This means consecutive map(), assign(), or filter() steps may be combined into a single step for efficiency, but their relative order is strictly preserved.