A strategy's observed maximum drawdown describes one realized path. It does not show every path that could arise under a proposed model. A Monte Carlo trading drawdown exercise generates hypothetical sequences, measures each one, and makes the model's assumptions visible alongside its results.
The example here resamples an existing return sample with replacement. It is a reproducible stress exploration, not a probability guarantee for a live account. It extends the drawdown calculation guide by asking how the statistic changes across simulated paths rather than simply recalculating the original history.
Sequence changes the drawdown
Take four synthetic sequential returns: +10%, −10%, −10% and +10%, each applied to the equity then available. Starting from 1.0, the equity path is 1.10, 0.99, 0.891 and 0.9801. Its largest fall from a running peak is 19%, from 1.10 to 0.891.
Reordering the same returns to −10%, +10%, −10%, +10% produces 0.90, 0.99, 0.891 and 0.9801. The starting 1.0 remains the high-water mark, so maximum drawdown is 10.9%. The ending value is the same because the same growth factors were multiplied, but the path risk differs.
This example assumes sequential, nonoverlapping returns and proportional reinvestment. Dollar trade outcomes under a fixed-lot strategy follow another sizing model. Do not shuffle dollar P&L and claim that the result automatically models fixed-fraction risk or account-level margin.
Shuffling and bootstrap answer different questions
A shuffle changes the order while retaining each observed return exactly once. A bootstrap draws observations with replacement, so some sampled paths repeat a loss or omit a win. It can therefore change both the final result and drawdown, not only their ordering.
SciPy's bootstrap documentation describes resampling with replacement for statistical calculations. The simple simulator below uses that sampling idea for a specified drawdown experiment; it does not implement SciPy's confidence-interval procedures or establish confidence coverage for a future trading path.
Independent draws remove time dependence from the original sample. If losses cluster, that can materially change the modeled paths. A block-based model can retain some local order, but block length and its assumptions need validation; it is not a universal repair. Neither approach invents a market regime or rare loss that is absent from the source sample.
A bounded, seeded example
Inputs are decimal equity returns such as 0.01 for +1%, not percentages written as 1. The generator is deterministic for repeatable examples and is not intended for security or high-precision simulation research. The work cap prevents accidental unbounded browser or script workloads.
function simulateDrawdowns(returns, { paths = 1000, horizon = 100, seed = 7 } = {}) {
if (!Array.isArray(returns) || returns.length < 2 ||
!returns.every(r => Number.isFinite(r) && r > -1) ||
![paths, horizon].every(n => Number.isSafeInteger(n) && n > 0) ||
paths * horizon > 1000000 ||
!Number.isSafeInteger(seed) || seed < 0 || seed > 0xffffffff) {
throw new Error("Invalid returns or simulation budget");
}
let state = seed >>> 0;
const random = () => {
state = (Math.imul(1664525, state) + 1013904223) >>> 0;
return state / 4294967296;
};
const drawdowns = [];
for (let path = 0; path < paths; path++) {
let equity = 1, peak = 1, worst = 0;
for (let step = 0; step < horizon; step++) {
const r = returns[Math.floor(random() * returns.length)];
equity *= 1 + r;
if (!Number.isFinite(equity) || equity <= 0) {
throw new Error("Unsupported numerical equity range");
}
peak = Math.max(peak, equity);
worst = Math.max(worst, (peak - equity) / peak);
}
drawdowns.push(worst);
}
drawdowns.sort((a, b) => a - b);
return { drawdowns, p95: drawdowns[Math.ceil(0.95 * paths) - 1] };
}The reported p95 is the nearest-rank 95th percentile of simulated maximum drawdowns under this model, sample, horizon and seed. It is not “the account's maximum possible loss,” nor a statement that real future drawdown stays below it with 95% probability. A different sample, sizing rule or dependence model can change the output substantially.
Tests used synthetic inputs to check seed reproducibility, all-positive paths, all-negative paths, invalid returns and the work budget. The two four-return paths above were also calculated independently. No reported simulation result is based on a live trading account.
Prepare a return series that matches the question
If trades overlap, treating each trade's percentage result as a separate sequential account return can invent a portfolio path that never existed. Use a consistently sampled account-equity return series, or implement an explicit strategy and exposure model. Define whether returns include commissions, swap, fees and floating P&L.
Deposits and withdrawals are not investment returns. The cash-flow-adjusted return guide explains the required distinction. Also document missing periods and the calendar used. Removing quiet periods or including partial observations changes what the sample represents.
MetaKit supplies deal history through /v1/accounts/{id}/deals and account/performance data through its documented reads. The current API does not expose a Monte Carlo endpoint. Raw deals can support reconstruction, but their existence does not supply historical marked-to-market equity at every observation time automatically.
Preserve source records and a dataset version, then calculate the chosen returns in your own research workflow. The deal-history sync guide is useful for reliable raw collection; it is not an account-equity simulator.
Keep scenario risk separate from sampling risk
Resampling a pleasant period cannot establish behavior during a regime it never contained. Use explicit stress scenarios for larger costs, changed liquidity, position constraints or losses beyond the historical sample. Keep those scenarios labeled separately from empirical bootstrap paths so readers can see which assumptions generated each result.
Trade-close or periodic-equity drawdown also misses losses between observations. A prop-firm threshold can be breached intraday even when the period closes above it. The drawdown-rules guide covers the need to measure the rule's actual equity basis and reset convention; this simulator does not model those rules.
Report the source period, sample size, return definition, sampling method, horizon, number of paths, seed and percentile convention. Repeat the calculation under defensible alternative assumptions and explain differences instead of selecting the most attractive result. More simulated paths reduce sampling noise inside the chosen experiment; they do not repair an inappropriate model.
Use the MetaKit API documentation to identify the available inputs. The useful outcome of this exercise is a clearer view of sensitivity and missing assumptions, not a certified safe position size or a forecast of investment performance.
Sources and verification
Verified 20 October 2026 against MetaKit's data routes and analytics implementation. All numerical examples and test inputs are synthetic.
- SciPy bootstrap documentation, resampling-with-replacement concept.
- SciPy resampling and Monte Carlo tutorial, computational sampling context.
- MetaKit API reference, available account, deal and performance interfaces.