Skip to main content

Open-source RAPM + VAEP rating framework for football. Math-grounded, reproducible, pre-registered.

Project description

onside

A regularized adjusted plus-minus framework for football. Open source. Mathematically grounded. One number per player.

pip install onside

Every action counted.


What this is

A Python library and accompanying dataset that produces a single rating for every player in a covered league, decomposed into offensive and defensive components, calibrated against actual match outcomes.

onside answers a question football fans argue about constantly: how much does this player actually contribute? Goals and assists tell you about the last action of a sequence. They don't tell you about the switch of play that created the chance, the press that forced the turnover, the goal-line clearance that prevented the opponent's chance. onside credits every action by how much it changed the probability of a goal — for or against.

The framework integrates three established techniques from the sports analytics literature into a single open-source pipeline:

  • VAEP (Valuing Actions by Estimating Probabilities) for outfield action value
  • PSxG − Goals for goalkeeper shot-stopping
  • Regularized Adjusted Plus-Minus (RAPM) for context-controlled player ratings

Each of these is well-known in the literature. None of them, as far as we are aware, has been published as a clean, free, public Python package for football. onside is that package.

What it isn't

  • Not a betting product
  • Not a fantasy football optimizer
  • Not a replacement for watching matches
  • Not the final word on player quality
  • Not a model of off-ball contribution — this is an open problem in the literature, and we are explicit about it

How it works

For every action in every match — every pass, dribble, tackle, interception, save — the library computes the change in goal probability that action produced.

A pass that moves the ball from a low-threat zone to a high-threat zone gets positive credit. A turnover gets negative credit. A goal-line clearance gets large positive defensive credit. Sum these per-action values across a season, control for teammate and opponent quality using regularized regression (the same technique used to compute NBA RAPM), and you get one offensive and one defensive rating per player, with confidence intervals.

Goalkeepers are handled separately using post-shot expected goals (PSxG) because their critical actions — saves — aren't well-encoded in standard event data.

For the math, see docs/PAPER.md. For data sources, see docs/DATA_SOURCES.md.

Quickstart

import onside

# Load a season's worth of data (downloads + caches if not local)
data = onside.load("statsbomb-open", competition="laliga", season="2023-24")

# Compute action values for every event
values = onside.value(data)

# Compute season ratings with cross-validated ridge regression
ratings = onside.rate(values, regularization="cv")

# Top 20 players by total rating
print(ratings.top(20))

# Decompose by offense / defense, filter by position
print(ratings.by("defensive", position="CB"))

What gets shipped

Artifact What it is
pip install onside The library — load data, compute action values, fit ratings
Pre-trained models (GitHub releases) Score and concede probability functions, PSxG model, all version-tagged
Public dataset (Hugging Face / Kaggle) Cleaned event data and computed ratings, ready to use
onside.fc Companion site — leaderboards, per-player pages, methodology explainer

Why this exists

Football analytics has terrific public infrastructure for shot-quality (xG via Understat, FBref) and event-data parsing (socceraction, kloppy, mplsoccer). What is missing is a single, principled, cross-position, context-controlled player rating — the football equivalent of NBA RAPM.

Several research papers describe how to build one. None ship a turn-key package. The closest analogs are paywalled (Twenty First Group, StatsBomb's internal models, PFF's grades) or single-paper releases that don't keep up with new seasons.

onside is the open implementation. Methodology is public. Code is public. Models are versioned and reproducible. Predictions come with confidence intervals. The bad ones aren't hidden.

Status

Pre-release. Working toward v0.1.0. The first stable release will cover the StatsBomb open-data scope (men's and women's World Cups, La Liga, FA WSL, Champions League finals, and a small set of historical matches). Subsequent releases extend coverage to FBref-derived data for the Big 5 European leagues, MLS, and Liga MX.

Acknowledging what came before

onside builds on:

  • Decroos, T., Bransen, L., Van Haaren, J., & Davis, J. (2019). Actions Speak Louder than Goals: Valuing Player Actions in Soccer. KDD.
  • Sicilia, A., Pelechrinis, K., & Goldsberry, K. (2019). DeepHoops: Evaluating Micro-Actions in Basketball Using Deep Feature Representations of Spatio-Temporal Data. KDD.
  • Sill, J. (2010). Improved NBA Adjusted +/- Using Regularization and Out-of-Sample Testing. MIT Sloan Sports Analytics Conference.

Full citations and discussion in docs/PAPER.md.

License

Code: MIT. Methodology and writeups: CC BY 4.0. Data is sourced from public providers; their licenses apply to the underlying data.

Citation

Dondisch, L. (2026). onside: A regularized adjusted plus-minus framework for football.
https://github.com/dondischl12/onside

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

onside-1.0.0.tar.gz (24.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

onside-1.0.0-py3-none-any.whl (41.7 kB view details)

Uploaded Python 3

File details

Details for the file onside-1.0.0.tar.gz.

File metadata

  • Download URL: onside-1.0.0.tar.gz
  • Upload date:
  • Size: 24.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for onside-1.0.0.tar.gz
Algorithm Hash digest
SHA256 384252be0ff2678c9203d7468ecb7c045afcea3f54443c224a1bccb87c6e9d5f
MD5 e9a68d88a0b75993ef946e548878d884
BLAKE2b-256 630075dfc2ded03da00de3dae7bff2cab65fb2d769ca83b3ce8b4967d028bd24

See more details on using hashes here.

File details

Details for the file onside-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: onside-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 41.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for onside-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1604f2cd0df1bff444b4b57e662f9952516bedf19630a4ab63f3743a6fcb9233
MD5 c7b5d6774b709138c254e6497c270b09
BLAKE2b-256 69ebbee27fecf3655324e48894e0ffde7c98cc934aeee5dc0e99a5cedb735686

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page