Status, September 2026: GitHub Actions are currently paused on this repo, so automated data refreshes and deploys are not running. The data and any live site reflect the last build.
Statistical modelling of professional tennis matches (ATP + WTA, singles and doubles), published as a static GitHub Pages site and rebuilt automatically every 3 hours.
The site mirrors the AFL/NRL modelling dashboards — Matches, Rankings, Analysis, Backtest, Model Lab and (soon) Compare odds. Every match is priced across a full market book: win probability and fair odds, set betting, per-set winners, total games and handicaps, tie-breaks, breaks of serve, aces and double faults, plus most-aces / most-DF props.
A reproducible Python pipeline built entirely from public data:
| Stage | Module | Output |
|---|---|---|
| Ingest | src/ingest.py |
Cache ATP + WTA match histories, players, rankings |
| Profiles | src/features.py |
Per-player surface serve/return profiles (recency-weighted, opponent-adjusted, shrunk) |
| Ratings | src/ratings.py |
Surface-weighted Elo (overall + hard / clay / grass) |
| Engine | src/sim.py |
Hierarchical point→game→set→match Markov + Monte-Carlo simulator |
| Fixtures | src/scrape_schedule.py, src/fixtures.py |
Upcoming matches mapped to player ids |
| Predict | src/predict.py |
Full projection per fixture |
| Backtest | src/evaluate.py |
Log-loss / Brier / calibration vs baselines |
| Site | src/build_site.py |
Render docs/ (HTML + JSON) |
src/run_daily.py chains these; .github/workflows/daily.yml runs it on a daily cron.
- Serve/return profiles. From each player's serve statistics we estimate, per surface, their service- and return-points-won rates, ace rate, double-fault rate and serve splits — recency-weighted (exponential decay), opponent-adjusted, and shrunk toward the tour mean for small samples.
- Surface-weighted Elo. Chronological Elo (overall and per-surface) gives a calibrated baseline win probability.
- Match engine. The two players' serve/return rates yield per-point serve-win probabilities, which roll up analytically (and via Monte-Carlo for derived markets) to game / set / match outcomes — anchored to the Elo blend so the headline number stays calibrated.
- tennis-data.co.uk — every tour-level match since 2013 (winner, surface, best-of, closing odds) for Elo, player records and the backtest's market baseline.
- Jeff Sackmann — Match Charting Project — per-match serve/return aggregates for the serve profiles (the only public per-match serve stats since the tour-level repos went private). Players with results but no charted serve data are priced Elo-only from a league-average profile.
- tennis.com — upcoming order of play / schedule.
- Methodology inspired by Tennis Abstract.
pip install -r requirements.txt
python -m src.run_daily # full pipeline -> docs/
python -m http.server -d docs # preview at http://localhost:8000For research and entertainment only. Model projections are not betting advice.
