Monte Carlo Simulation for Tennis Totals
Football goals fit a tidy formula. Tennis does not: points nest inside games, games inside sets, sets inside a match, with tiebreaks and a server alternating every game. There is no clean closed-form distribution for "total games in a best-of-three match". When the maths gets structurally awkward, modellers reach for a different tool — Monte Carlo simulation: build a miniature copy of the match in code, play it thousands of times, and count what happens. This post shows how that prices the tennis totals market, works a full example, and then tells you honestly what happened when we measured our own simulator against reality.
Why simulation instead of a formula
An over/under market needs one number: the probability that the total (here: games played) finishes above the line. In football you can get there analytically because goals are a simple count. Tennis scoring is a state machine — the current score changes what happens next. A set can end 6-0 or 7-6; a 6-6 set forces a tiebreak; winning a set changes nothing about the next one except who serves first. Writing down the exact probability of "22 or fewer total games" as a formula means enumerating every path through that machine. Possible, but miserable — and every rule variation (best-of-five, final-set rules) breaks the formula.
Skip the hand-calculation.
Get real value bets flagged for you — 7-day free trialSimulation sidesteps all of it. If you can code the rules of tennis — and they are just rules — you can play the match. Randomly decide each service game, follow the scoring logic, record the total. Repeat 10,000 times. The fraction of simulated matches finishing over the line is your probability, to within simulation noise that shrinks as you add runs.
The engine: two hold percentages
The simplest useful tennis simulator runs at the level of service games. Each service game is a weighted coin flip: the server holds with probability h, or is broken with probability 1 − h. That single number per player absorbs everything about serve quality versus return quality. A leaner variant of the same idea simulates point-by-point from serve-points-won percentages; the game-level version is faster and captures most of the structure.
A single simulated match then looks like this:
- Alternate service games, flipping the weighted coin each time.
- Track the set score; a set ends at 6 games with a two-game lead, or 7-5, or via tiebreak at 6-6 (the tiebreak itself is another weighted flip, favouring the better server).
- Play sets until one player has two (best of three).
- Record the total games and move to the next simulated match.
Worked example: pricing Over 22.5 games
Illustrative numbers. Player A holds serve 78% of the time, Player B holds 72%. The line is 22.5 games. We run 10,000 simulated matches and tally the outcomes:
- Mean total: 22.1 games.
- The distribution is lumpy, not smooth — spikes at 6-4 6-4-shaped totals (20), 6-4 7-5 (22), 7-6 6-4 (23): set scores quantise the totals.
- Matches finishing over 22.5: 5,230 of 10,000 → P(over) ≈ 52.3%.
- Fair odds for the over: 1 / 0.523 ≈ 1.91.
Two structural features of tennis totals fall straight out of the simulation. First, totals are bimodal: straight-set matches cluster near 20 games, three-set matches near 30, with a valley in between — a single "expected total" number hides this. Second, the total is extremely sensitive to hold percentages: nudge both holds up two points and the break-less sets stretch toward tiebreaks, adding more than a full game to the mean. This is why serve-dominant matchups (grass, big servers) play to much higher lines.
Where the hold percentages come from
In practice you estimate holds from historical serve and return statistics: a player's service-points-won and return-points-won rates, blended over a recency window, adjusted for surface. The subtle part is opponent adjustment — a 78% career hold means less against an elite returner — and data hygiene: the stats you use must be strictly *point-in-time* (what was knowable before the match), or you quietly leak the future into your backtest and the model looks better than it is. We have been bitten by exactly this class of bug and now audit for it routinely.
The honest part: what our simulator could not do
Here is the part most modelling articles skip. We ran a serve-percentage-based Monte Carlo totals model in production, and when we audited its settled predictions against results, the verdict was blunt: the simulator's over/under probabilities had essentially zero discrimination — the correlation between its stated probability and what actually happened was indistinguishable from noise — and it carried a systematic over-bias. The scoring engine was flawless; the inputs were not sharp enough to beat a market that already prices tennis totals very efficiently.
What we did next matters more than the failure. We fitted a per-tour calibration layer on the model's own out-of-sample record. Calibration is a truth serum: when a model genuinely has no signal, calibrating it collapses its outputs toward the base rate — which pushes almost every candidate bet below our edge threshold. The model, in effect, learned to say "I don't know" and stopped betting the market rather than pretending to a signal it did not have. Its match-winner sibling, which does carry real signal, was left untouched.
Putting it all together
Monte Carlo is the right tool for tennis totals: the scoring structure is too knotty for formulas, and simulation handles it exactly. Two hold percentages in, a full distribution of total games out — bimodal, quantised by set scores, honest about tiebreak sensitivity. But the method is a probability *engine*, not an edge. Whether the resulting prices beat a bookmaker's depends entirely on input quality, and the only way to know is to measure discrimination and calibration on settled, out-of-sample results — and to accept the verdict, even when the verdict is abstention. That measurement discipline, not the simulator, is the actual craft; variance and sample size explains why the measuring takes patience.