How Sybil reads a profile
Raw win rates lie in two directions at once: they treat a game from 2016 as seriously as one from this morning, and they treat 3–0 as better than 60–40. Everything below is an attempt to stop doing both.
Recency weighting
Every match carries a weight that decays exponentially with age. The control on the Heroes tab sets the half-life: at 30 days, a match from a month ago counts half as much as one played today, a match from two months ago a quarter, and so on.
w(match) = 2-age / halfLife - ε
The small ε subtracted at the end truncates the tail, so genuinely ancient games drop out entirely instead of contributing a permanent rounding error.
Adjusted win rate (AWR)
The weighted record is then blended with a prior worth k pseudo-games — ten by default:
AWR = (prior x k + Σ w·win) / (k + Σ w)
A hero with two recent wins sits barely above the prior. A hero with two hundred games sits almost exactly on its own record. ThePrior slider chooses what that prior is:
- Self — a flat 50%. This ranks your heroes against each other: which of your heroes do you win most on?
- Field — each hero's global win rate in your bracket. This ranks you against everyone else: on which heroes do you beat the average player of your rank?
Adjusted pick rate (APR)
The same treatment applied to how often you pick a hero: the recency-weighted share of your games, shrunk toward a uniform prior over the whole hero pool. It answers "what is in your pool right now", not "what have you ever played".
Position
Dota itself records no position, so Sybil takes it from the best source available for each match, in this order:
- 1. Stratz's classification. Stratz assigns a position from the replay, with all ten players in view. Where it has one, that is what you see — no estimating. Roughly 90% of a recent history is covered.
- 2. Your history on that hero. For matches Stratz has not classified, Sybil uses the positions you have actually been given on that same hero.
- 3. Lane and farm priority. Last resort, for a hero with no classified games at all. This tier is genuinely unreliable — summary numbers cannot tell a kill-funded support from a farming core, so a Techies with 600 GPM reads as an offlaner when they were a position 4 all along. That is exactly why it sits last.
The profile reports what share of the games behind the estimate came from tier 1, and on the match list anything not classified outright is marked with an asterisk. The result is always a distribution, never a single label — a player who genuinely splits between position 4 and 5 reads as exactly that.
The position shown against a hero follows two extra rules. If enough of that hero's games are classified, the label comes from those alone — estimates for the rest are discarded rather than diluting ground truth. And recency is weighted gently: the oldest game still counts about a third as much as today's, so the label describes the body of play instead of flipping to whatever you happened to pick last. A ? next to a position means there were not enough classified games and it is a guess.
Game advantage
Shown on every match and on a live lobby. It answers one narrow question: based on the ten people in this game and the heroes they are on, which side is on more familiar ground?
It is called game advantage rather than draft advantage on purpose. Nothing about the draft as players normally mean it is in here — no lane matchups, no counter-picks, no composition, no bans. Two teams of identical players on identical heroes score identically no matter how the picks line up against each other.
How it is calculated
- 1. Take each player's adjusted win rate on the hero they picked, computed from their games before this match started so the game being described is never part of its own evidence.
- 2. Clamp each one to 30–70%, so a single hero record cannot run away with a number that is only ever one fifth of a side.
- 3. Average across all five players on each side.
- 4. Combine the two averages with Bradley–Terry: convert each to log-odds, take the difference, convert back — plus a fixed term for Radiant's advantage.
P(radiant) = σ( logit(avg_radiant) − logit(avg_dire) + 0.13 )
That last term is the only fitted number in the model, and it is not about the players at all. Radiant wins a bit over half of all Dota games — easier Roshan, better warding angles, a friendlier jungle — so two evenly matched sides read as roughly 53% Radiant, not 50%. That is not a bug in the display; it is what an even game is actually worth.
It sits at the match level rather than inside anyone's adjusted win rate, because a player's history is split roughly evenly between the two sides and is therefore already side-neutral. The advantage belongs to the game being played, not to the people playing it.
Priors: the hero, not a coin flip
Each player's record is shrunk toward the hero's own win rate in the bracket this match was played at, not toward 50%. That matters most where it is needed most: a random lobby is mostly people with a handful of games on what they picked, and shrinking those toward a coin flip claims an unfamiliar hero is an even proposition whether the hero wins 44% or 53%.
A player we cannot read at all — private profile, anonymous slot, or simply no games on that hero — counts at the hero's bracket rate too. We still know which hero they locked in, and that is a great deal more than nothing. Leaving them out of the average entirely, which this used to do, is badly wrong: a side with four private profiles and one visible player on 60% became a 60% side, and then "outdrafted" a fully readable team of ordinary players. A flat 50% fixed that but threw the hero away. Those rows show an uncoloured figure — it is the hero's number, not a reading of the person.
The bracket is taken from the medals on the scoreboard, so all ten players are measured against one field. Using each player's own bracket would compare an Archon's Lion to Archon Lions and an Immortal's to Immortal ones, inside a single game where they are on the same map against each other.
What it is worth
Backtested over 1,340 ranked matches drawn from thirteen accounts, with every player's record recomputed from games before each match started:
Those first two rows are the trap. 53.7% looks like a win over a coin flip — until you notice Radiant won 53.4% of the same matches. Radiant has a real side advantage in Dota, so always guess Radiant scores 53.4% while knowing nothing at all. Measured against that baseline rather than against 50%, the model's accuracy adds 0.3 points: nothing.
The AUC is the honest measure, because it does not care about the base rate — it asks whether a match Radiant won scores higher than one they lost. At 0.567 across 1,340 matches it is more than four standard errors above chance, and it holds at 0.568 on the subset where at least eight of ten players are readable. So there is real signal here. It is weak — 0.567 means the ranking is right about 57% of the time instead of 50% — but it is not noise.
Those figures are from before the side term existed, and they are exactly why it now does. Without it the model treated 50% as neutral when the true neutral is Radiant's base rate, so every prediction leaned a couple of points toward Dire — visible in the old calibration, where matches rated 45–50% were in fact won by Radiant 51.9% of the time.
Both fixes were tested out of sample rather than trusted: the side term was measured on half the matches and every variant scored on the other half, which it had never seen.
The last row is what ships. Every variant is scored on the same matches, so the comparisons are paired and firmer than the individual intervals suggest. Over the full 1,338 matches that configuration runs at 56.4% against a 53.4% baseline, with AUC 0.570 and Brier 0.2458 — the ranking signal the AUC always showed is now actually reaching the prediction.
Caveats that remain: every account came from one bracket and one player's peer group, matchmaking already balances teams by rating, and adjusted win rates are shrunk hard toward the middle. The figure on a match page is still best read as a description of the two rosters — but "it predicts nothing" would now be the wrong conclusion.
Hero pool
Counting the heroes someone has ever played is close to useless — almost every long-time player has touched nearly the whole roster at least once. The figure on the profile is the number of heroes that make up 80% of your recency-weighted picks: the set you would actually expect to see on the draft screen.
What Sybil cannot see
- Accounts with "Expose Public Match Data" turned off in Dota 2. Nothing third-party can read those, Sybil included.
- Anything about your teammates' or opponents' contribution to a given win. A win rate is a team statistic wearing an individual's name.
- Draft context. Sybil knows you win on a hero; it does not know whether that is because you are good at it or because you only pick it into favourable matchups.
I am blind, yet I see. I know not, yet I know thee.