How this system is built

A solo-built, end-to-end CS2 match prediction system — and an honest account of the time its backtest lied by 3.5x, what got torn down because of it, and how ideas earn their way into the model now. By hyper.

Simulation only. Everything on this site is a paper record — flat 1-unit stakes graded at recorded prices, no real money. Where sample sizes are under the floors (100 settled bets for ROI, 150 pairs for CLV), the pages say so instead of drawing conclusions.

What this is

One person, one pipeline, every layer: data ingestion, feature engineering, model training, evaluation, and live serving — for predicting Counter-Strike 2 match outcomes.

11k+
matches ingested
1.5M+
demo kill events parsed
12
model versions gated in
hourly
odds tape (Pinnacle, Kalshi)

Case study — my backtest was lying to me by 3.5x

Early versions of this project produced backtests with great ROI. The numbers were exciting, repeatable, and wrong.

The bugs

An audit of every historical profitability harness found that none of them could be trusted:

The fix was not patching the backtest. It was accepting that the historical answer was unknowable with the data at hand, and rebuilding on forward-only evidence.

The rebuild

What the honest numbers say right now

As of 2026-07-17, the forward ledger (simulation, flat 1u, flag-time entry) reads:

MetricValueVerdict gate
Flagged candidates (all)213 (177 settled)
In-band [3–11% edge] settled77  (32W–45L, −8.1u, −10.6% ROI)below the 100-settled floor — no ROI verdict
95% CI on in-band ROI−35.5% … +16.2%spans zero
Median CLV, in-band (79 pairs)+0.00ppbelow the 150-pair gate — pending

A separate walk-forward historical backtest (per-fold models trained strictly before their test windows, ~4,300 out-of-sample series, the ~280 joinable to usable historical odds) lands at roughly −5% ROI with a confidence interval spanning zero — clearly labeled as resting on proxy odds.

The current scoreboard is negative and under-sampled, and it is published anyway.
That is the whole point of the rebuild: a system whose numbers I can no longer fool myself with. When it does show an edge, that number will mean something.

How ideas earn their way in

Every feature idea goes through a measure-before-build protocol: before writing pipeline code, run a cheap diagnostic asking whether the current model's out-of-sample residuals contain the proposed signal at all. If the live model already prices it, the idea dies in an afternoon instead of costing a feature cycle. Three real outcomes:

Schedule strength shippedpassed diagnostic

Hypothesis: recent-form ratings don't ask who the form was earned against. The diagnostic found the effect in the live model's residuals at 4.6–5.4 standard errors, stable across all four chronological folds, and it survived six adversarial refutation attempts (placebo permutations, kitchen-sink controls, block bootstraps). Interestingly, the original interaction hypothesis was wrong — the data said the fix was a simple additive feature. Built, selected by the trainer on its own merit, shipped in model v12.

Editorial star ratings killed before buildscrape never paid for

Match-importance stars would have cost a scraping fight to collect. The diagnostic went first: importance is a property of the match, identical for both teams, so by symmetry it can't carry a winner signal directly — and all twelve interaction probes plus the recalibration channel came back null (≤0.0005 log-loss ceiling). The scrape was never built. Cost of the answer: one afternoon, zero code in production.

Lineup-continuity features built, then killed with evidence

Assumption: the model must be miscalibrated on teams with roster churn, since their ratings were earned by a different five. Tested on 3,588 out-of-sample predictions: the lowest-continuity bucket was the best calibrated, and the correlation between residuals and continuity was ≈0. The modeling thread was closed with three independent nulls. The real value lived at a different layer — a serve-time guardrail that flags when tonight's announced lineup differs from the roster the ratings were earned by — and that part stayed.

Stack