Learn › EAs and automated trading

Monte Carlo Strategy Testing: Reshuffle Trades to See the Drawdown to Plan For

A backtest gives one path. Monte Carlo reshuffles and resamples the trade list thousands of times to show the range of drawdown, streaks, net profit and risk of ruin.

Intermediate 9 min read 21 October 2026

What you will learn
  • A backtest is one path out of thousands the same trade list could produce. Its drawdown may simply be a lucky ordering
  • Reshuffling shows the range of max drawdown and losing streaks. The bootstrap also shows the range of net profit and average trade
  • Size your risk from the 95th-percentile drawdown, not from the drawdown in the backtest report
  • A confidence interval for the average trade that spans zero means you can't yet tell the system apart from luck
  • Monte Carlo assumes trades are independent, so it can't capture a change in market regime

Monte Carlo in trading means taking the trade list from a backtest and reshuffling it, or resampling it, thousands of times to see how widely drawdown, losing streaks and net profit spread out. The backtest in your report is just one path out of many possible ones. If the losers happened to be well spread out, the drawdown in the report looks shallower than you should expect. This article works through it step by step with an example list of 150 trades.

Why one backtest path isn’t enough

Say a system took 150 trades, won 60 and lost 90. The total profit is one fixed number. But the max drawdown (the deepest fall of the account from a peak) depends on how the losers are ordered. Eight losses in a row dig a deeper hole than losses scattered between wins, even though it is the same set of trades.

The future doesn’t have to order trades the way the past did. So the right question isn’t “what drawdown did the backtest have?” but “if these trades came in a different order, how deep could the drawdown get, and how often?” If reading drawdown is still new to you, start with How to read drawdown.

Three common kinds of Monte Carlo

  1. Reshuffle. Randomly reorder all 150 trades. Every trade is still there, so the total is the same in every run. What changes is the max drawdown and the longest losing streak.
  2. Bootstrap (resample with replacement). Draw 150 trades at random from the list, putting each one back after drawing. One trade may be drawn twice and another not at all, so the number of winners differs from run to run, and the total and average trade vary too. This is closer to reality, because the future doesn’t promise exactly 60 winners again.
  3. Skip trades and add costs. Randomly drop some trades (signals missed because of a dropped connection, or a spread too wide to enter) and subtract an extra cost from every trade (slippage, spread wider than in the backtest) to see whether the system survives when live conditions are worse than the test.

All three work on the trade list only. You don’t need to rerun the backtest. A spreadsheet or a short script is enough.

Example: 150 trades, 40% win rate at RR 1:2

An illustrative trade list (not results from a real market): 60 winners of +2R each and 90 losers of −1R each. R is the amount risked per trade. If you risk a fixed 1% of the starting balance per trade, 1R = 1% of the starting balance.

  1. Average trade (expectancy) = 0.4 × 2 − 0.6 × 1 = 0.8 − 0.6 = +0.2R
  2. Total = 60 × 2 − 90 × 1 = 120 − 90 = +30R
  3. In the backtest’s original order, max drawdown = 9R, longest losing streak 5 trades

A 9R drawdown looks comfortable: at 1% per trade that’s only about 9% of the account. Now reshuffle it 10,000 times.

Simulation (10,000 runs)Median max DD95th-percentile max DDTotal
Backtest, original order9R (one path)–+30R
Reshuffle11R18R+30R in every run
Bootstrap11R21R0R to +60R (5th–95th percentile)
Bootstrap + skip 10% + 0.1R cost per trade13.8R27.6R−14.3R to +42.4R (median +13.5R)

The 95th percentile is the value that 95% of runs don’t exceed. With reshuffling, 95% of runs have a max drawdown of 18R or less, twice what the backtest showed, and about 72% of reshuffles hurt more than the backtest did. Losing streaks tell the same story: the median longest streak is 8 trades and the 95th percentile is 13, while the backtest showed only 5.

Backtest order: 9R Median 11R 95th percentile: 18R 72% of reshuffles had a deeper drawdown than the backtest Runs (out of 10,000) 500 1,000 0 5 10 15 20 25 Max drawdown (R) of each reshuffle
Reshuffling an illustrative list of 150 trades (40% winners at +2R, losers at −1R, not a real market) 10,000 times. Every run totals the same +30R and only the order differs, yet max drawdown ranges from 5R to 29R. The red line is the drawdown of the backtest order.

The drawdown in a backtest is what happened to one ordering of trades. It is not a ceiling. Plan from the 95th percentile of the simulation, then add a margin for live trading.

Bootstrap: the total moves too

Reshuffling still assumes all 60 winners show up. The bootstrap lets the number of winners vary with luck, and the equity paths spread out into a fan.

Backtest pathMedian 25–75%5–95% 95%: +60R Median +30R 5%: 0R 0 20 40 60 Trades 0 to 150 Cumulative result (R)
Cumulative result from 10,000 bootstrap runs of the same illustrative trade list, with percentiles computed trade by trade. The bands widen as trades accumulate. The thin dark line is the backtest in its original order, just one path inside the fan.

The backtest path ends at +30R, exactly on the median. But 5% of runs end at 0R or below, and about 4% end in a loss after 150 trades, even though this system has a real edge by construction. A good system can have a 150-trade stretch that earns nothing.

Confidence interval for the average trade

Across 10,000 bootstrap runs, 95% of the average-trade values fall between −0.04R and +0.44R, an interval that spans zero. A formula gives nearly the same answer:

  1. Spread per trade (SD) = (2 − (−1)) × √(0.4 × 0.6) = 3 × 0.49 ≈ 1.47R
  2. Standard error (SE) of the mean = 1.47 ÷ √150 = 1.47 ÷ 12.25 ≈ 0.12R
  3. 95% interval ≈ 0.2 ± 1.96 × 0.12 = 0.2 ± 0.24 = −0.04R to +0.44R

So 150 trades can’t confidently separate this system from one with no edge. For the lower bound to clear zero you need n trades where 1.96 × 1.47 ÷ √n < 0.2, which gives √n > 14.4, or roughly 208 trades or more. And that still assumes future trades come from the same system.

Skipping trades and subtracting 0.1R per trade cuts expectancy from 0.2R to about 0.1R. The confidence interval widens to −0.15R to +0.35R and about 21% of runs end in a loss. A small cost per trade eats half the edge. For the costs a backtest tends to miss, see Why live results are worse than the backtest.

Which percentile to plan for

There is no required number, but many traders plan with the 95th percentile and use the 99th as a stress test. In this example the 99th percentile of the reshuffle is 21R.

Turning it into risk per trade:

  1. Choose the largest drawdown you can live with, financially and emotionally, for example 10% of the account
  2. Divide by the bootstrap’s 95th-percentile drawdown, which is more cautious than the reshuffle: 10% ÷ 21R ≈ 0.48% per trade
  3. Round down further for costs and market conditions the backtest didn’t see, for example to about 0.4%

If you risk 1% per trade out of habit, this plan has to be ready for a drawdown of about 21% within one 150-trade stretch, which happens roughly 1 time in 20 even when nothing is wrong with the system. Compare with Risk 1% per trade and Losing streaks are normal.

Risk of ruin from the simulation

In practice, risk of ruin is the chance that drawdown reaches the level where you would stop, or where the account is badly damaged. You can count it directly from the runs. In the 150-trade bootstrap of this example:

Drawdown counted as “ruin”Chance
15R or more25%
20R or more8%
30R or more0.6%
20R or more, with 0.1R cost and 10% skipped19%

At 1% per trade with a rule to stop at a 20% drawdown, there is about an 8% chance of having to stop within the first 150 trades. At 0.5% per trade the same level is 40R, which happened in 6 of 10,000 runs. Risk per trade is the biggest lever you control. These numbers cover 150 trades only. The longer you trade, the higher the chance of meeting a deep drawdown.

In our own backtests

  • How much luck moves results: we tested opening one gold (XAUUSD) trade a day at 06:30 Thai time (UTC+7), 0.10 lot, a 10,000-dollar account, a 50-dollar Stop loss and a 300-dollar target (RR 1:6). 2022–2025 used 1-minute price data, January to September 2026 used real ticks, about 250 trades a year. Pure luck alone moves a year’s result by about ±2,000 dollars (1 SE), and for all 9 direction rules we tried, the 5-year total was within ±2 SE of zero, so none could be told apart from luck. It is the same principle as the confidence interval above. Details are in Losing streaks are normal.
  • Drawdown from reshuffling: in early research we reshuffled the trade order 1,000 times for a Fibonacci pullback system on gold H4 (H4 bar data, not ticks) that won about 20% at roughly RR 1:5. The 90th-percentile drawdown came out at about 82% of the whole period’s net profit. A system that wins this rarely has to risk very little per trade.

These are all backtest results. Past results do not predict future results, and they are not returns you should expect.

Limits to keep in mind

  • It assumes trades are independent. If a system really loses in clusters, such as a trend-following system that keeps losing while the market moves sideways, random reshuffling spreads those losers apart and gives a drawdown shallower than reality. A quick check: if the backtest’s own drawdown sits above the 95th percentile of the reshuffles, the losers probably come in clusters. Try a block shuffle instead (moving runs of 10–20 consecutive trades together).
  • It can’t see a regime change. Monte Carlo can only shake trades that already happened. If the market changes so the edge disappears, no simulated run will show it. Read more in When the market regime changes.
  • Garbage in, garbage out. If the trade list comes from settings tuned to fit the past, the simulation is over-optimistic too. Pair it with an out-of-sample test such as walk-forward testing and watch out for overfitting.
  • Overlapping trades. If the system holds several trades at once, the drawdown while they are open isn’t in a list of closed-trade profits and losses. What you get is a balance drawdown, which is shallower than equity drawdown.

Monte Carlo doesn’t make a system better. It only tells you how much this trade list could hurt. If the trade list is weak evidence, the simulation is just as weak.

Try it on your own trade list

  1. Export the profit and loss of each trade from your backtest report (in MT5, the Deals list of the report). Convert to R by dividing by the amount risked per trade, if the risk varied
  2. Reshuffle 1,000–10,000 times and record the max drawdown and longest losing streak of each run
  3. Run a separate bootstrap, recording max drawdown, total and average trade
  4. Repeat with an extra cost subtracted from every trade, for example one more spread
  5. Read the median, 95th and 99th percentiles, then set risk per trade from the bootstrap’s 95th percentile

The core of the reshuffle fits in a few lines (JavaScript):

function maxDD(trades) {            // trades = profit/loss per trade, in R
  let eq = 0, peak = 0, dd = 0;
  for (const r of trades) { eq += r; peak = Math.max(peak, eq); dd = Math.max(dd, peak - eq); }
  return dd;
}
function shuffled(a) {              // Fisher–Yates
  a = a.slice();
  for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; }
  return a;
}
const dds = Array.from({ length: 10000 }, () => maxDD(shuffled(trades))).sort((x, y) => x - y);
console.log('median', dds[5000], 'p95', dds[9500]);

For the bootstrap, replace shuffled with n random draws of trades[Math.floor(Math.random() * n)].

Common mistakes

  • Treating the backtest drawdown as a ceiling. In the example the backtest showed 9R, but 72% of other orderings hurt more, and 1 in 20 went to 18R or deeper
  • Only reshuffling. The total is the same in every run, which makes it easy to forget that the number of future winners varies too. The bootstrap gives a more cautious picture
  • Simulating from too few trades. With 30–50 trades, any number of runs gives a wide, unreliable range. A confidence interval that spans zero is the sign you don’t know enough yet
  • Forgetting costs. Subtracting 0.1R per trade in the example raised the chance of ending in a loss from about 4% to about 21%
  • Treating a good simulation as proof the system works. Monte Carlo measures how much the existing trades could swing. It doesn’t test whether the edge still exists in today’s market
Try it with your own numbers

Frequently asked questions

How many runs are enough?

For the median and the 95th percentile of drawdown, about 1,000 to 10,000 runs is already stable. More runs don't make the result more reliable than the trade list you feed in. With only 30 trades in the list, a million runs still tells you little.

Reshuffle or bootstrap, which should I use?

Both. Reshuffling answers "the total is the same, but how much could it hurt along the way?" The bootstrap adds "if luck changes the number of winners a little, how much do the total and the average trade move?" The bootstrap usually gives a deeper 95th-percentile drawdown, so it is the more cautious of the two.

The Monte Carlo results look good. Can I go live now?

Not yet. Monte Carlo can only shake the trades already in the list. If that list came from tuning settings to past data, or from one kind of market, the simulation is just as over-optimistic. Pass an out-of-sample test such as walk-forward first, then start with small money.

This is general education, not investment advice. Trading is risky and you may lose all of your capital.

Tools Chat on LINE