Projects / CS2 Match Predictor
Applied ML · live web app · 2026

CS2 Match Predictor

Do recent-form stats predict Counter-Strike matches any better than raw skill rating? I built the pipeline to answer that properly. The answer is no, and showing how I know is the point.

The CS2 Match Predictor web app with two teams of five FACEIT nicknames and a prediction

The live app: ten FACEIT nicknames in, a calibrated win probability out, next to the Elo baseline.

The finding

FACEIT Elo is already a near-complete predictor. Recent form adds no statistically significant ranking value on top of it.

PredictorAccuracyAUCECE
My model (stats + Elo, isotonic-calibrated)69%0.7530.032
FACEIT Elo formula (baseline)70%0.7450.072

The AUC gain is +0.007, 95% CI [−0.001, +0.016], DeLong p = 0.09: not significant. That held even after testing four more orthogonal features, including a leakage-safe teammate "stacking" signal that tells a coordinated 5-stack from five strangers at the same rating.

Where the model does win is calibration: when it says 70%, the team wins about 70% of the time, which the raw Elo formula can't claim. A walk-forward backtest (8 expanding folds, 4,440 out-of-sample predictions) shows the same picture.

Reliability diagram comparing predicted probability to observed win rate
Reliability diagram on held-out matches: closer to the diagonal is better.

How the number is kept honest

  • No feature sees the future

    A match's stat features use only each player's matches that finished before it started.

  • Always scored on newer matches

    A chronological split: the model is only tested on matches newer than everything it trained on.

  • A real baseline

    Measured against FACEIT's own Elo win-probability formula, which turns out to be very hard to beat.

  • "Better" means statistically better

    AUC differences go through a paired bootstrap confidence interval and DeLong's test.

  • Cross-checked against a replayed Elo

    FACEIT only exposes current Elo, so the comparison is re-run against an Elo rebuilt from scratch, in order, with no look-ahead.

Architecture

FACEIT APIcheckpointed crawler
→
Featuresleakage-safe
→
Trainlogreg vs XGBoost + isotonic
→
predict_from_stats()shared by CLI and web
→
Django appcached, ~100× faster warm

The ML library knows nothing about the web, so a feature vector means the same thing at training time and serving time, by construction.