How accurate is the ENSI.Score rating
64.7%
of the calls this site locked in before a match went the way it said
2,438 evaluated of 21,896 matches in the window
Measured on 2438 matches played between October 21, 2025 and October 20, 2026. Recomputed on October 20, 2026 from report #469.
The figures, against a coin
| Metric | ENSI.Score | A coin |
|---|---|---|
| Accuracy | 64.73% | 50.00% |
| Brier score lower is better | 0.2181 | 0.2500 |
| Log-loss lower is better | 0.6250 | 0.6931 |
Accuracy counts the matches whose favourite won. Brier and log-loss read the probability itself, and both are better the lower they are: a forecaster who says 90 % and is wrong is punished more than one who says 51 % and is wrong.
| Game | Matches | Accuracy | Brier score | Log-loss |
|---|---|---|---|---|
| CS2 | 1,717 | 64.42% | 0.2188 | 0.6270 |
A game appears here once it has 300 scored predictions of its own.
How much of the year this covers
21,896 matches of the window could be scored
- 2,438 scored: a probability locked before the start
- 38 stale: the probability stopped describing the match
- 19,420 never got a probability
Beside that sum as well: 18 matches no probability could have been locked for — this site first heard of them only after they had started.
Draws and matches decided by a forfeit stand beside that sum rather than inside it: 1197 of them, and no result any probability could be scored against.
Does 70 % mean seven times out of ten?
Every prediction of the year, sorted by the probability it gave and cut into ten equal groups. A group sitting on the diagonal was right as often as it said it would be; the bars are the range the group is still consistent with at 95 %, and they are wide because a year of matches is not many.
- The diagonal: right exactly as often as predicted
- A group: what it predicted against how often it won
- The range the group is consistent with at 95 %
| Group | Matches | Predicted | Actually won | Gap, pp | 95 % interval |
|---|---|---|---|---|---|
| 1 | 244 | 24.5% | 28.3% | +3.7 | 23.0% – 34.2% |
| 2 | 244 | 36.4% | 44.3% | +7.9 | 38.2% – 50.5% |
| 3 | 244 | 43.1% | 42.6% | -0.5 | 36.6% – 48.9% |
| 4 | 244 | 47.9% | 54.1% | +6.2 | 47.8% – 60.2% |
| 5 | 244 | 52.4% | 60.2% | +7.8 | 54.0% – 66.2% |
| 6 | 244 | 57.2% | 58.6% | +1.4 | 52.3% – 64.6% |
| 7 | 244 | 61.5% | 64.8% | +3.3 | 58.6% – 70.5% |
| 8 | 244 | 66.4% | 71.7% | +5.3 | 65.8% – 77.0% |
| 9 | 243 | 73.3% | 74.9% | +1.6 | 69.1% – 79.9% |
| 10 | 243 | 83.6% | 86.0% | +2.4 | 81.1% – 89.8% |
How the number is made
Within the two hours before a match's announced start, the probability that team 1 wins is computed from the two ENSI.Score ratings shown on the site at that moment and written down. It is computed again whenever the teams, a rating or the start time change, until five minutes before the announced start or until the match goes live. The last computation is the one the match page prints and the one measured here; the earlier ones are kept but not measured, and none is ever edited. If a match starts earlier than announced, the last computation may fall after the real start: it still uses only ratings from before the match, because a rating changes only when a series ends.
p1 = 1 / (1 + 10(r2 − r1 − 0) / 400)
r1 and r2 are the two ENSI.Score ratings at the moment the probability is locked. The published model is elo-v1: an offset of 0 and a scale of 400.
A match counts towards the figures above when all of this is true of it, inside the 365 days the window covers:
- The match was played and ended inside the window, and the score names a winner.
- Draws and matches decided by a forfeit are left out: there was nothing on the server to predict.
- The prediction still describes the match. If the start or a rating changes more than five minutes before the announced start, it is marked and a new computation replaces it; after that it stays as written. If the sides are swapped, it is marked at any time, since its number belongs to the other team 1, and a match left without a valid computation is not measured. A marked prediction stays readable as the record of what was claimed.
- Nothing is measured on a match that was already over. The accuracy of a model is what it said beforehand, and only that.
The calibration bars are wide on purpose. Telling a group that says 70 % apart from one that wins 75 % of the time needs some 16 500 matches — about a year of them — and until there are that many the honest thing to print is the interval rather than a verdict.
The queries this figure comes from
The published figure is recomputed from the rows the report froze, so it stays reproducible after the score has been corrected, the match moved or the series deleted:
php artisan e:elo-accuracy --report=469
select series_id, p1, y::int as y from elo_accuracy_report_rows where report_id = ?
Parameters: 469
The same arithmetic over the data as it stands right now. It reaches no page: if it disagrees with the report, the input changed after publication, which is a thing to know rather than to smooth over.
php artisan e:elo-accuracy --live --window-days=365 --window-end=2026-10-20
select sp.series_id, sp.p1,
(case when s.score_1 > s.score_2 then 1 else 0 end) as y
from series_predictions sp
join series s on s.id = sp.series_id
where sp.model = ? and sp.status = 'active'
and s.date_end is not null
and s.date_end >= (?::date - make_interval(days => ?::int - 1))
and s.date_end < (?::date + interval '1 day')
and s.score_1 is not null and s.score_2 is not null and s.score_1 <> s.score_2
and coalesce(s.forfeit_team_1, false) = false
and coalesce(s.forfeit_team_2, false) = false
and (?::int is null or s.game_id = ?)
Parameters: elo-v1, 2026-10-20, 365, 2026-10-20, null, null
Both selections are the input. The arithmetic over them — accuracy, Brier, log-loss and the ten groups with their intervals — is one block of SQL that the command runs over whichever of the two it is given, so a report and a rerun cannot disagree by having counted differently.
Digest of the frozen input: fcbb3014f308915703401b39acaf7c89