Simulation

The Ruin Lab

One person playing for an evening can win. But when thousands of people play by the same rules, the result stops being a matter of luck. Here you can set thousands playing at once and watch what happens to their money.

Read in

Plain mode explains the ideas without jargon. Technical mode adds formulas, methods and code.

How to use it. Pick a scenario or change the rules on the left: the game, how much money each person starts with and how many times they bet. The result appears instantly. In the first chart each thin line is a person and the gold area is where most of them are. If that area goes down, people are losing.

Simulating…

Three things the lab teaches

1. The house charges a little on every bet

Roulette pays as if it had 36 pockets, but it has 37: the zero. That difference means that, on average, the house keeps about 3 cents of every euro that is bet. It sounds small, but it is charged on every spin, win or lose. So what you lose in the long run does not depend on luck but on how much money goes across the table. The more you play, the more you pay. In the first chart you can see it in the dashed line that keeps going down.

Technical Expected loss = edge × total wagered

Each bet is a random variable X with expectation E[X] = −h·s, where s is the stake and h the house edge. In European roulette, betting on red: E = (18/37)·s − (19/37)·s = −s/37, so h = 1/37 ≈ 2.70%. By linearity of expectation, after n bets the expected loss is h·Σsi, whatever the order or size of the bets.

The “Average loss” tile compares the simulated mean with that theoretical value: they match up to sampling error, which shrinks as 1/√N with the number of players N.

2. Winning one day is not being ahead

In the short run luck matters far more than the house edge, which is why there are always people who win. They are the ones we hear about, the ones posting screenshots. But look at everyone at once and most are losing, and the longer the session, the fewer remain ahead. With “high-volatility” slots it is even clearer: almost everyone loses quickly while a few take huge prizes. Those few prizes make the average look less bad than it is for the typical person.

Technical Variance, median and mean

The standard deviation of the outcome grows like √n while the expected loss grows like n, so the probability of being ahead tends to zero. With highly skewed prize distributions (high volatility) the mean sits far above the median: the percentile bands tell the story better than the mean, which is sensitive to a few extreme values.

Slots are modelled as a discrete paytable scaled to an exact 96% RTP; the high-volatility version puts part of the return into 500× and 5,000× prizes with very low probabilities.

3. No system beats the house

The Martingale means doubling your bet every time you lose, so the next win recovers everything. It works many times in a row, which is why it is so tempting, until a bad streak comes along and the bet you need is more than you have or than the table allows. Then you lose everything at once. You can see it in the chart: many lines creep up and a few collapse. No system changes the underlying fact: every spin is independent of the last and the house charges on all of them.

Technical Gambler’s ruin and why systems fail

If you start with a units, bet one unit with win probability p (q = 1 − p) and stop when you reach b, the probability of going broke first is:

P(ruin) = ((q/p)^a − (q/p)^b) / (1 − (q/p)^b)

With €20 at European roulette and a target of €40, that is almost 75%. The project’s tests check that the simulation reproduces this exact value. Progression systems (Martingale, D’Alembert) cannot change the expectation, by the optional stopping theorem: with negative-expectation bets and finite limits (bankroll and table maximum), any betting rule is still a supermartingale. They only reshape the outcome: many small wins in exchange for rare, large losses.

Technical How it is built

Each game is a discrete prize distribution (what each euro pays back and with what probability). The simulation uses a seeded pseudo-random generator (mulberry32), so every result is reproducible, and runs in a Web Worker so the page stays responsive. For each player we record when they go broke or walk away; from that we estimate the Kaplan–Meier survival curve, treating players who stop after reaching their target as censored. The code is in src/lib, with Vitest tests. More in Methods.

Questions this page answers

All questions →