All work

2025–2026 · Live

Predictorous

Football analytics and match predictor: data pipeline, probability model and 3D dashboard for the top five European leagues

A system that turns raw football data into calibrated match-outcome probabilities, publishes them before kickoff, and grades itself afterwards. It ingests fixtures, results, xG and event data for the top five European leagues, rates teams, predicts every match, and shows the reasoning on a dashboard with a 3D pitch. The rule throughout: nothing ships unless it beats the baseline on a frozen out-of-sample season.

Role

Solo developer — data engineering, statistical model, backtesting, API, dashboard, deployment.

Outcome

Model validated on a frozen out-of-sample season; predictions published daily; live at predictorous.com.

Links

What I built

  • Ingestion pipeline in Python: fixtures and results from fbref, per-match xG from Understat, and shot and pass event streams, for five leagues across multiple seasons. Incremental scrapes with rate-limit handling, date-stamped snapshots, everything as parquet and JSON on disk with no database.
  • Model: decay-weighted xG strength ratings feed a Poisson score grid with per-league home advantage; a logistic draw classifier trained on eleven seasons and about 17,000 matches unifies the probabilities. A nine-zone territory layer built from shot events explains each prediction.
  • Validation discipline: walk-forward backtests on frozen seasons, calibration reports, and a rejected-experiments log. Several plausible upgrades were tested and dropped because they did not improve out-of-sample results. Top-ranked draw predictions hit 28.9% against a 24.8% base rate; high-confidence favorites land at 65 to 67% across three samples.
  • Append-only ledger: every prediction is written before kickoff and graded automatically against the final score and real xG. A scheduled daily run scrapes, rates, predicts and grades end to end.
  • FastAPI backend exposing leagues, players, fixtures, predictions and plots; Jinja admin pages restricted to localhost.
  • Next.js dashboard exported statically and deployed to Cloudflare Pages: predictor table, team pages with pass networks and shot maps, head-to-head view, ratings, history, and a React Three Fiber 3D pitch with formation and territory views.

Architecture

Sources

  • fbref

    fixtures · results · squads

  • Understat

    per-match xG

  • Event streams

    shots · passes

Pipeline

  • Incremental scrapers

    rate-limited · snapshot archive

  • Ratings builders

    xG strength · Elo · zones

  • Daily run

    scrape → rate → predict → grade

Model

  • Poisson score grid

    per-league home advantage

  • Draw classifier

    logistic · 11 seasons

  • Walk-forward backtests

    frozen seasons · calibration

Output

  • Prediction ledger

    append-only · auto-graded

  • FastAPI

    JSON export for the web

  • Static dashboard

    Next.js · 3D pitch · Cloudflare

  • →Every prediction is committed to the ledger before kickoff; the next daily run grades it. Nothing is edited after the fact.
  • →The dashboard is a static export of the ledger and derived metrics, so the scrapers, raw data and credentials never leave the machine.

Stack

Data & model
Python · pandas · numpy · scipy · soccerdata · matplotlib / mplsoccer
Backend
FastAPI · Pydantic · Jinja · scheduled daily run
Frontend
Next.js (static export) · TypeScript · React Three Fiber · Tailwind CSS
Hosting
Cloudflare Pages · Docker

Screens

hover to scroll · click to enlarge