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. The question then 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: 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.

The path compounds each trade's Trade.returnPct() (return on the capital committed at entry): wealth W_k = Π_{j≤k}(1 + r_j) from 1. Reshuffling currency P&L instead would be wrong for an all-in compounding book, where a trade's currency P&L depends on the equity at the time it was taken. Drawdowns are fractions of the running peak, terminal values are total returns. Percentiles come from Stats.quantile. Deterministic given the seed.

  • Method Details

    • analyze

      public static MonteCarloTradeShuffle.Result analyze(List<Trade> trades, int shuffles, long seed)
      Shuffles the trade order and records the drawdown distribution.
      Parameters:
      trades - the strategy's completed trades, at least 2
      shuffles - number of shuffles, at least 100
      seed - random seed