Class MonteCarloTradeShuffle

java.lang.Object
com.quantfinlib.backtest.validation.MonteCarloTradeShuffle

public final class MonteCarloTradeShuffle extends Object
MONTE CARLO trade reshuffling — the answer to "was my equity curve's SHAPE luck?". A backtest reports one path: this strategy's trades in the order they happened, producing one max drawdown and one terminal equity. But the ORDER is itself a sample. Reshuffle the same trade P&Ls into thousands of random sequences and you get the distribution of drawdowns and terminal wealth the strategy's OWN trades imply — and the honest question stops being "the backtest drew down 18%" and becomes "the 95th-percentile drawdown of my trade set is 31%, so plan for 31, not 18".

What reshuffling holds fixed and what it breaks: it preserves the MULTISET of trade outcomes (win rate, average win/loss, profit factor are invariant) and destroys their ORDER — so it isolates "path/sequencing risk" from "edge". Its blind spot, stated plainly: it assumes trades are exchangeable, so it UNDERSTATES risk for a strategy whose losses cluster (serial correlation, regime dependence) — a martingale that wins small and loses catastrophically looks tamer reshuffled than it is. For serially-correlated PATHS use BlockBootstrap on the return series; this class is the per-trade complement, and the two disagreeing is itself the signal that your trades are not independent.

Drawdown is computed on the cumulative P&L path (additive, so no starting-capital assumption); the percentiles come from MathUtils.percentile. Deterministic given the seed. Research lane.

  • Method Details

    • analyze

      public static MonteCarloTradeShuffle.Result analyze(List<Trade> trades, int shuffles, long seed)
      Parameters:
      trades - the strategy's completed trades, ≥ 2; @param shuffles ≥ 100