← all projects
Case study · ML analytics

ChessIQ
my own games, treated as an ML problem.

Over five years I accidentally built a dataset: 4,635 Chess.com games. ChessIQ turns that history into an analytics platform — Stockfish-evaluated moves, an outcome predictor built on pre-game features only, and recommendations that actually moved my rating.

Repository ↗ Previous case study →
4,635
GAMES
328,258
MOVES (STOCKFISH d15)
72.49%
HONEST ACCURACY
0.827
AUC-ROC
597→1,423
RATING, 5 YRS
ChessIQ dashboard KPIs: 4,635 games, 49.1% win rate, 91.93% average accuracy, peak rating 1,423
The live dashboard — five years of play distilled into KPIs: 4,635 games, 91.93% avg accuracy, peak rating 1,423.

01 · The question

I improved my chess rating not by playing more, but by analyzing what I'd already played. Five years on Chess.com left me with 4,635 games — a real, messy, personal dataset. The question: "What if I treated my chess history like an ML problem?" Could a model predict outcomes before a game starts, and could the data tell me exactly what to fix?

Every move was evaluated with Stockfish at depth 15 — 328,258 evaluations — then aggregated into game-level and player-level features for analysis and modeling.

02 · The mistake that became the headline

The first model hit 78.21% accuracy — and it was a lie. It used post-game metrics (accuracy %, centipawn loss) as features: numbers you can't know before a game. Classic data leakage. The model was "predicting" outcomes using information from the outcome itself.

The rebuild allowed only pre-game features: my rating, opponent rating, rating difference, cumulative win rate, opponent-rating history, recent streak (last 10 games), time control, and color — 8 features total.

78.21%
WITH LEAKAGE — FLATTERING, USELESS
  • ✗ accuracy % (post-game)
  • ✗ centipawn loss (post-game)
  • ✗ accuracy×CPL interaction
72.49%
PRE-GAME ONLY — HONEST, DEPLOYABLE
  • ✓ ratings & rating difference
  • ✓ historical win rate & streak
  • ✓ time control & color

A 5.72-point drop, taken deliberately. Honest > Impressive — the smaller number is the one that works on games that haven't happened yet.

03 · Architecture

Chess.com game history4,635 games · 2021–2026
Stockfish enginedepth-15 · 328,258 move evals
EDA · 24 time-series windows · correlation analysis
Feature engineering8 pre-game features · StandardScaler · leakage audit
TRAINING · 5-FOLD CV · GRIDSEARCH · McNEMAR'S TEST
5 models comparedXGBoost · RF · GB · Voting · Stacking
Voting ensemble + SHAP72.49% · AUC 0.827
SERVING
FastAPI backendPostgreSQL on Railway
Streamlit dashboard8 pages · Plotly · win predictor

04 · What 4,635 games actually said

SHAP put rating difference at 59.63% of predictive importance — I beat weaker opponents 88.4% of the time and stronger ones almost never (6.6%). Performance was surprisingly format-agnostic: only 1.8% win-rate variance across blitz, rapid and classical. The biggest lever was openings:

WIN RATE BY OPENING (ECO CODE)
D31
60.26%
D20
54.26%
A40
53.99%
B20
40.77%
A04
39.19%

Acting on this — focusing on 2 openings instead of 15 — was worth +150 rating in 6 months, part of the 597 → 1,423 climb. The data also said uncomfortable things: I lose to stronger players by being outplayed positionally, not by blundering. You can't fix what you don't measure.

Rating progression chart from 597 to 1,423 over five years, win rate trending from 44.5% to 57.1%
Progress page — 597 → 1,423 (+826) over ~24 game windows; win rate trend 44.5% → 57.1%.
AI Tips page showing strengths, weaknesses, and a weekly/monthly/quarterly action plan
AI Tips — data-driven strengths, weaknesses and a week/month/quarter action plan. This is the page that moved the rating.

05 · Model comparison — no cherry-picking

MODELACCURACYNOTES
Voting Ensemble72.49% ★selected — best accuracy, stable across folds
XGBoost72.17%tuned via GridSearchCV
Random Forest72.17%tied with XGBoost
Gradient Boosting72.06%
Stacking Ensemble71.84%more complexity, less accuracy

Validation: 80/20 split, 5-fold cross-validation (74–76% range), McNemar's statistical test between candidates, confusion matrices and ROC analysis. The stacking result is on the page for a reason — fancier isn't better, and showing the losers is what makes the winner credible.

SHAP feature importance chart: rating difference at 59.6%, win rate history 11.9%, average opponent rating 10.8%
ML Insights — SHAP feature importance. Rating difference dominates at 59.6%; all 8 features are pre-game only (3,708 / 927 train-test split).

06 · Lessons & where it goes next

Integrity > vanity metrics.

The 72.49% model ships; the 78.21% one doesn't. Fixing leakage taught me more than any accuracy gain would have.

Feature engineering > fancy models.

Five model families landed within 0.65 points of each other. The features — not the algorithm — decided the ceiling.

Data reveals uncomfortable truths.

The dashboard told me exactly where I'm weak. Acting on it beat playing a thousand more unexamined games.

The vision: right now ChessIQ analyzes my games. The plan is to let any player upload theirs — personalized analysis, predictions and an improvement plan, for anyone. Next steps on the roadmap: 50K+ multi-player games, move-sequence models (LSTM), and live Chess.com API integration.