Projects

Built alone.
Shipped in public.

Every one has a live link, a public repository, and a written record of what failed. The numbers here are reproducible — the code that produced them is one click away.

shanbhag003.github.io/player-scout Player Scout ranking the ten closest players to Rayan Cherki, each row carrying a match score, a shared trait and the two biggest differences.
A player profile: percentile radar against every attacking midfielder in the pool, with per-90 figures and percentiles for all fourteen metrics.
Every player is ranked against his own position, not the whole pool.

Player Scout

Python · Principal component analysis · GitHub Actions

Name a player you already have a view on and it finds who else plays the same way, then tells you where the two differ — or start from a need instead of a name. It now spans three sports: football across the big five leagues, men's and women's T20 cricket, and the Pro Kabaddi League. The figures below are the football pool.

3,245Players in the pool13,980 player-seasons, 2021/22 to 2025/26
98.6%Records matched across three sources that share no identifier99.9% above 900 minutes
18thWhere the tool ranks a player against his own later self, of 161Chance would be 81st
624Players who changed league, used to fit the league adjustmentThe same person measured before and after a move

The decision I'd defend

Pressing intensity is one number describing eleven people. Attach it to an individual and everyone at the same club starts to look alike. It's shown as context on the profile and kept out of the similarity model entirely — and the panel says so, rather than letting you assume otherwise.

What it cannot see, stated on the page itself

  • Goalkeeper rankings57th of 160 against a chance of 80 — close to random, so they aren't ranked at all
  • Defensive actionsNo tackles, interceptions or duels in the data, so defenders are compared going forward only
  • Keeping 80% of varianceCost real accuracy; right wingers went from 23rd to 34th. The threshold was set by testing, not convention

Every player is split into his early and later seasons and handed to the tool as two strangers. If it can't recognise a man as his own closest match, it can't recognise anything.

shanbhag003.github.io/pl-supercomputer The model's 2026-27 Premier League table, with expected points, title odds and relegation odds for all twenty clubs.
Seven-step diagram: learns from twelve seasons, rates every player, checks availability and manager, admits what it cannot know, plays the season 20,000 times, counts outcomes, then marks its own past predictions.
How it works, end to end. It republishes five hours after the last fixture of a gameweek.

Premier League
Supercomputer

Python · Dixon-Coles · Monte Carlo · GitHub Actions

Predicts the Premier League table, refits itself after every gameweek, and grades its own past predictions against the closing market. Nobody presses anything, and it costs nothing to run.

0.204Match accuracy, ranked probability scoreClosing bookmaker line: 0.202
9.2Season error, points per clubNaive baseline: 10.95
20,000Season simulations per run40 seconds, one CPU core
7 / 7Backtested seasons with the champion in the top threeWalk-forward, never seeing a result first

Switched off, and still in the repository

  • Market odds blendMarginal error gain, worse ranking and calibration
  • Manager effects, all changesWorse on every metric
  • Foreign-league manager valuesPlayer conversion already weak at n≈200
  • Fixture congestionEffect reverses sign between eras, fails out-of-sample

Version one penalised Liverpool for hiring Slot, who then won the league — it couldn't tell "worse manager" from "manager we have never seen". It ships only where both managers have a Premier League record. Congestion was the one I most wanted to be true: two datasets, seven seasons, net effect +0.00002.

cricket-ai-digest.onrender.com The Cricket Digest console during a Test match, showing an analyst briefing and a fan briefing side by side.
The same dismissal written twice: an analyst version citing strike rate, economy and dot balls, and a fan version explaining why the wicket mattered.
One live feed, then a reasoning layer, then two persona digests. Same ball, two commentaries.

Cricket AI Digest

Node · ESPN Cricket API · Claude · WebSocket

One live cricket feed in, two briefings out — the facts behind the moment for an analyst, why it matters for a fan. Both generated from the same raw match state.

14¢Cost of an entire T20Ungated it would be ~480 calls a day
2Gates before any model call firesOne saves bandwidth, one saves money
3Formats with their own thresholds50 runs is an hour in a Test, five overs in a T20

What I got wrong

Two traps in ESPN's schema, both caught by reading the raw payload rather than trusting the field names. A team that hasn't batted can appear as 0/0 (73 ov), because bowling overs are mirrored into the wrong side's linescore. A digest built from all-null fields still looks like a success in the logs — so a debug endpoint returns the exact object handed to the model.

Hosted on a free tier that sleeps when idle, so the first load can take a minute to wake, and digests appear once a live match updates.

shanbhag003.github.io/fpl-auto-manager The bot's Gameweek 1 team sheet, with its own projected points printed on every player it picked.
The full pipeline: deadline check, FPL API, frozen historical datasets and non-statistical inputs feeding player scoring, minutes model, transfer planner, squad optimiser, captaincy, chip intelligence and an explainability layer.
Nine decision engines in order, and the four inputs that feed them. Every stage degrades rather than failing.

FPL Auto Manager

Python · AWS Lambda · Linear programming · Gemini

Rates every player, plans transfers, picks the eleven and the captain, submits them, then publishes its projection before kickoff so it can be marked against a human. Unattended, every week.

0.368Out-of-sample R² on next-season outputPoints-per-90 alone: 0.302
874Player-seasons behind the model2009 onward, fitted old and tested new
300Minutes below which last season predicts worse than nothingFound by backtest, not by guess
Down
only
What the language model may do to a projectionA wrong call costs one player, not the team

The mistake that rebuilt the model

The first version ranked players on FPL's own projection field. Before a season it's a placeholder — about 24 distinct values across 570 players — so a backup goalkeeper and the best striker scored identically. It sold three of the squad's best players and bought a forward who had started three games all season.

The code ran perfectly. The thinking was wrong.

The short version

Every claim on this page has code behind it.

The detail lives in the repositories, where the backtest scripts sit next to the results and the rejected versions are still in the history. That's deliberate — a number you can't reproduce isn't evidence.