Monte Carlo Simulation Formula, and the Error in 1,000 Paths
The math inside a Monte Carlo simulation of a monthly plan: the balance recursion, percentiles and success rates, and how much 1,000 paths vary.
Updated
The math inside a Monte Carlo simulation of a monthly plan: the balance recursion, percentiles and success rates, and how much 1,000 paths vary.
Updated
A Monte Carlo simulation finds an answer by repeating a random trial many times and counting how the results are distributed.[1] For an investment plan, the trial walks a balance forward one month at a time with a formula that updates it (a recursion), each month's return drawn at random, through to the last month. In compoundsim, one path runs that monthly step 240 times for a 20-year plan, and the simulator runs 1,000 paths. A median taken from 1,000 paths moves by only a few percent when the random numbers change, and a share moves little too. What moves the results far more is how the monthly returns are drawn.
This article leaves the return model aside and writes out, in formulas, the arithmetic every model shares. For the same ground without the math, see how Monte Carlo simulation works.
Number the months , write for the balance at the end of month and for the monthly contribution. The fixed-rate compound interest calculator turns the annual rate , taken as an effective rate, into a monthly growth factor and applies the same one every month:
A Monte Carlo simulation swaps that for a growth factor drawn at random each month, where is the month's log return (next section):
The contribution arrives at the end of the month, after the month's return, in the same order as the fixed-rate calculation; take the randomness away and the two agree. A 20-year plan has , and one walk through all 240 months is one path. The simulator computes 1,000 of them.
The withdrawal simulator runs the other way round: the withdrawal comes out at the start of the month and the rest then grows. The withdrawal starts at a twelfth of the first year's amount and rises with inflation every month:
The first month a withdrawal takes the balance to zero or below, the path has run out of money, and it stays at zero.
The Monte Carlo simulator in real terms, and the withdrawal simulator always, divide the balance by the price level at the time. With an assumed annual inflation rate (2% by default), the real balance in month is . Prices rise at that constant rate; no random numbers go into them.
If is the month's simple return (0.05 for 5%), its log return is . The simulator's model is fitted to past monthly returns converted to logs. In logs, growth over many months becomes a sum. With a starting sum and no contributions,
The sum of the gets closer to a symmetric distribution as the months add up, so, writing for the expected value (the mean), its median is about and the balance's median is about . But curves upward, so the balance's mean comes out higher than that (). A few very good paths pull the mean up and barely move the median.
The median is the figure those few paths barely sway. The gap between a simple average return and the rate money actually grows at (volatility drag) is covered in the average return is not the rate your money grows at. With monthly contributions the formula no longer takes this shape, but the mean still lands above the median for the same reason.
Sort the 1,000 paths' balances in a given month from smallest to largest, with . The th percentile is the value at rank ; when is not a whole number, it is read off the straight line between the two paths on either side ( is rounded down to a whole number). Of the ways statistical packages compute percentiles, this is the one classified as definition 7.[2] In symbols:
The median is . On the chart the outer band runs from to and the inner band from to . Each month's band is computed on its own, so the edge of the band does not follow any one path.
A share is the number of paths that meet a condition, divided by . The withdrawal simulator's success rate is the share of paths whose money lasted to the end:
A drawdown is how far the balance sits below the highest value it had reached. The high starts at the starting sum, and the balance includes the contributions paid in (in real terms, it is measured on the real balance):
The deepest along a path is that path's max drawdown.
Every and here describes the 1,000 paths the model produced. No number of paths can tell whether the model fits the real world.
With a finite number of paths (trials), a different starting point for the random numbers (the seed) gives slightly different results. Formulas say how much.
A share counts how often something with probability happened in tries, so its standard deviation (the standard error) is
For a 90% success rate that is , a standard error of about 0.95 points. Within about twice that either way, roughly 88% to 92%, the rate can move by chance alone.
Percentiles have a similar formula. If is the density of the balance's distribution at that percentile (how closely the paths crowd around that amount),
Out in the tails, where paths are sparse, is small and the error is larger. Both formulas shrink as , so halving the error takes four times the paths.
To see the size of it, the same calculation as the Monte Carlo simulator was run 50 times, changing only the seed: the S&P 500 (SPY, dividends reinvested, the model fitted to its full history since 1993), in nominal US dollars, one dollar a month for 20 years ($240 paid in).
| Balance after 20 years | Mean of 50 runs (multiple of the money paid in) | Spread with 1,000 paths | Spread with 250 paths |
|---|---|---|---|
| 10th percentile | 1.7× | 3.0% | 4.1% |
| Median | 3.5× | 2.5% | 5.5% |
| 90th percentile | 7.6× | 3.1% | 6.5% |
The spread is the standard deviation of the 50 results divided by their mean. With 1,000 paths, the 20-year median moves by about 2.5% from run to run, so a 1,000-path median is best read as carrying that few percent of slack.
The same check on a share: the share of paths whose max drawdown reached −30% or worse averaged 21.3% over the 50 runs. The standard deviations in the next table are how far that share itself moves, in percentage points.
| Share with a max drawdown of −30% or worse | 1,000 paths | 250 paths |
|---|---|---|
| Standard deviation measured over 50 runs | 1.5% | 2.8% |
| The formula | 1.3% | 2.6% |
For the share, the measured spread and the formula nearly agree. A quarter of the paths roughly doubles the spread for most measures. But a standard deviation measured from 50 runs is itself uncertain by about a tenth, and the ratio of two of them more so, so some rows land well off double, as the 10th percentile row of the first table does.
Each path first redraws its own copy of the model's mean returns and its chances of switching regime, then draws its months. The paths are still independent of each other, so the rule holds as it is.
The simulator's seed is the date the page was opened (UTC) as an eight-digit number, . A small pseudo-random generator, mulberry32, turns it into uniform numbers in , used in order from the first path on. Open the page on the same day with the same settings and anyone gets the same 1,000 paths.
Open the page on another day and the seed changes, so the page draws 1,000 new paths (a page left open keeps its seed past midnight). The experiment above also changed only the seed across its 50 runs, so a median that moves by a few percent from one day to the next is within the spread measured there. Differences much larger than that come from changing the settings or the history the model is fitted to, or from a data update that refits the model.
For a single asset, the in the recursion comes from that asset's monthly log return . For a mix, with weight on asset (the weights summing to 1), rebalanced back to those weights every month, the growth factor is
The portfolio simulator (without margin) and the withdrawal simulator put this into the recursion in place of .
Seen in a currency other than the dollar with "Include FX swings" on (the default), the month's change in the dollar value of one unit of that currency is drawn from the model along with the assets. With its log change, the growth factor in that currency is , where is the exchange rate's long-run average change in the model fitted to the history. The long-run trend of an exchange rate need not continue, so it is taken out, leaving the swings and their timing.
How the and are drawn, switching between a calm regime and a wild regime, is explained in how Monte Carlo simulation works.
The spread above comes from running a finite number of paths from a given model, and more paths make it smaller. Two things stay the same however many paths run.
One is the return model. Which model the come from changes the distribution itself, and a model fitted to the history rarely produces markets unlike any in it.
The other is what the calculation leaves out. Taxes, trading fees and account charges are not deducted (the ETFs' own expense ratios are in their returns). Contributions stay the same throughout, and prices rise at a constant rate.
Those assumptions move the results far more than the few percent that 1,000 paths vary by. In the same setting as the experiment above, changing only the history the model is fitted to and running 1,000 paths once on the same seed, the 20-year median is 3.4× the money paid in with the full history and 4.1× with the last 5 years: a far wider gap than the spread from the number of paths (2.5%).