About this project

MMA Fight Prediction is a Python research and serving project that forecasts UFC fight winners, method of victory and finish round. It combines an Elo rating system, a gradient-boosted (XGBoost) ensemble, a multi-task neural-network ensemble, and an equal-weight blend of the two that is the deployed scorer. Every candidate is judged by expanding-window walk-forward evaluation across 2018-2026, and the winning scorer is calibrated with a temperature fitted on held-out data after the blend average. Reproducible pipeline The quickstart creates a virtual environment, installs the package with dev extras, then runs four scripts in order: download_data.py (Kaggle UFC dataset into data/raw/), make_dataset.py (clean parquet into data/processed/), build_ratings.py (tune and build Elo ratings), followed by pytest. A Streamlit app (streamlit run app.py) lets a user pick any two fighters and returns win probability with uncertainty, method and finish-round tendencies, and a breakdown of the top contributing factors. A documented aim is byte-for-byte reproducibility of the whole pipeline. Feature engineering and leak control Features are assembled from named blocks (base, external, trajectory, notice, context, opponent_adjusted) in src/mma/feature_blocks.py, producing a table of roughly 11 thousand fights by 87 columns. Features are built inside chronological accumulators so each value is strictly pre-fight, and a truncation-invariance test is used to check that no feature can see the future. Blocks were measured against a pre-registered accuracy bar: one (external, covering pre-UFC career data) cleared it on its own, while others ship only as part of the table the blend was scored on, or do not ship at all. The project documents a selection leak found in per-corner missingness flags, which was removed from both model matrices while staying in the table for evaluation slices. Several columns are explicitly excluded from the model inputs as leak guards, and a provenance sidecar file records, per row, whether it came from the primary or secondary source. Data sources Records are assembled as a union of a maintained Kaggle mirror (the primary, reconciled source) and the Greco1899/scrape_ufc_stats CSV publication (used strictly as data, fetched over HTTPS, with no GPL-licensed code vendored). On overlapping fights the primary row wins; the merge is gated on winner agreement between sources and is fail-soft, degrading to a primary-only build with a warning. The repository reports provenance, integrity checks and regression guards around this merge. Self-updating and prospective evaluation A weekly GitHub Action refreshes the dataset and rebuilds artifacts, committing them automatically. Upcoming UFC events are predicted and committed to git before they happen and graded afterwards, giving a prospective track record rather than retrospective-only reporting. Harness reports for rejected feature blocks and pre-registered experiment decision files are committed under models/walkforward/, so negative results are retained. The project is written in Python (3.10+) and released under the MIT license. Design and phase-plan documents live under docs/.