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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
384252be0ff2678c9203d7468ecb7c045afcea3f54443c224a1bccb87c6e9d5f
|
|
| MD5 |
e9a68d88a0b75993ef946e548878d884
|
|
| BLAKE2b-256 |
630075dfc2ded03da00de3dae7bff2cab65fb2d769ca83b3ce8b4967d028bd24
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1604f2cd0df1bff444b4b57e662f9952516bedf19630a4ab63f3743a6fcb9233
|
|
| MD5 |
c7b5d6774b709138c254e6497c270b09
|
|
| BLAKE2b-256 |
69ebbee27fecf3655324e48894e0ffde7c98cc934aeee5dc0e99a5cedb735686
|