Trading Dev AcademyFree quant education

Free lesson · Risk

Monte Carlo: your backtest is one draw from a distribution

Open interactive lessonPractice calculationsExplore labs

Start with the idea

A simulation is a way to propagate assumptions into a distribution of outcomes. It cannot create information about events absent from the model. Distinguish shuffling, IID bootstrap, block bootstrap and parametric simulation before interpreting a confidence band.

Symbols, units & horizon
  • Rₜ: simulated decimal return in period t
  • V₀: initial capital
  • Vₜ: compounded wealth
  • n: observations or simulation count as specified
  • α: selected probability
  • q: empirical quantile
  • ceil: round up to the next integer
  • Seed: reproducible pseudorandom generator state

When and why to use this

Use Monte Carlo for sizing sensitivity and to compare possible wealth paths under clearly specified distributions. Use stress scenarios to cover risks the fitted sample may not contain.

A backtest gives one equity curve. Monte Carlo asks: given this strategy's per-trade distribution, what are the other equity curves that could have happened? Resample the trades with replacement (bootstrap), or shuffle their order, thousands of times; collect max drawdown, final equity, and Sharpe from each run; report the distribution.

  • The 95th-percentile max drawdown is your sizing constraint, not the backtest's drawdown.
  • The fraction of runs that hit −50% is your probability of ruin at this size.
  • The spread of final equity is a picture of how much luck is in one path.
Recursive arithmetic + simulation estimator

Build a simulated wealth path and empirical quantile

  1. Given sampled return Rₜ, update Et=Et−1(1+Rt). Apply the drawdown recursion to each path, storing one MDD per path.
  2. Sort B simulated MDDs. A specified quantile convention selects or interpolates the α fraction of this ordered list. Event frequency is p^=#{MDD≥d}B.
  3. For independent simulated paths, Monte Carlo sampling SE of an event frequency is approximately p^(1−p^)B. This is simulation noise, not uncertainty about whether the market model is correct.
Work it by hand

If 20 of 400 paths cross a 50% drawdown, estimated model frequency=.05 and Monte Carlo SE≈.0109, or 1.09 percentage points.

Python implementation

Self-contained teaching example. Python 3.10+; dependencies and input conventions are shown in the code and notation. Run in your own Python environment.

from random import Random
from math import ceil

def bootstrap_path(observed_returns, periods, starting_wealth=100, seed=7):
    """IID resampling demo, not a dependence-preserving block bootstrap."""
    rng, path = Random(seed), [starting_wealth]
    for _ in range(periods):
        path.append(path[-1]*(1+rng.choice(observed_returns)))
    return path

def empirical_quantile(values, probability):
    """Inverse empirical CDF: nearest-rank convention."""
    if not values or not 0 < probability <= 1:
        raise ValueError("Nonempty values and probability in (0,1] required")
    return sorted(values)[ceil(len(values)*probability)-1]

print(bootstrap_path([.02,-.01,.005], 5))

Continue learning

Risk Management — all lessons
  1. Start with gains, losses and an ordered sample
  2. Value at Risk and maximum drawdown: two views of the bad days
  3. Sharpe ratio: return per unit of risk
  4. Kelly criterion: the fraction that maximises growth
  5. Monte Carlo: your backtest is one draw from a distribution
  6. Expected shortfall and scenario risk

Quantitative finance and development glossary · Python resources and libraries · Research sources and limitations