DEV Community

Propfirmkey
Propfirmkey

Posted on

Monte Carlo Simulation for Trading Strategy Validation

Monte Carlo simulation is one of the most powerful tools for understanding the range of possible outcomes from your trading strategy. Here's how to implement it.

Why Monte Carlo?

Backtesting gives you one path through history. But that path won't repeat. Monte Carlo generates thousands of possible equity curves from your actual trade results, showing you the probability distribution of outcomes.

Implementation

import numpy as np
import matplotlib.pyplot as plt

def monte_carlo_trades(trade_results, num_simulations=1000, num_trades=500):
    """
    Simulate equity curves by randomly sampling from actual trade results.
    """
    simulations = np.zeros((num_simulations, num_trades))

    for i in range(num_simulations):
        # Random sampling with replacement
        sampled = np.random.choice(trade_results, size=num_trades, replace=True)
        simulations[i] = np.cumsum(sampled)

    return simulations

# Example: your last 200 trades in R-multiples
trade_results = np.array([1.5, -1, 2.0, -1, -1, 0.8, -1, 3.0, -1, 1.2] * 20)
sims = monte_carlo_trades(trade_results)
Enter fullscreen mode Exit fullscreen mode

Key Metrics from Simulation

def analyze_simulations(simulations, initial_capital=100000):
    final_values = simulations[:, -1] + initial_capital

    results = {
        'median_return': np.median(final_values) - initial_capital,
        'worst_case_5pct': np.percentile(final_values, 5) - initial_capital,
        'best_case_95pct': np.percentile(final_values, 95) - initial_capital,
        'probability_of_loss': (final_values < initial_capital).mean() * 100,
        'max_drawdown_median': np.median([
            calculate_max_dd(sim) for sim in simulations
        ]),
    }
    return results

def calculate_max_dd(equity_curve):
    peak = np.maximum.accumulate(equity_curve)
    drawdown = equity_curve - peak
    return drawdown.min()
Enter fullscreen mode Exit fullscreen mode

Visualizing Results

def plot_monte_carlo(simulations, initial_capital=100000):
    plt.figure(figsize=(12, 6))

    # Plot all simulations in light gray
    for sim in simulations[:200]:
        plt.plot(sim + initial_capital, color='gray', alpha=0.05)

    # Highlight percentiles
    median = np.median(simulations, axis=0) + initial_capital
    p5 = np.percentile(simulations, 5, axis=0) + initial_capital
    p95 = np.percentile(simulations, 95, axis=0) + initial_capital

    plt.plot(median, color='blue', linewidth=2, label='Median')
    plt.plot(p5, color='red', linewidth=1.5, label='5th percentile')
    plt.plot(p95, color='green', linewidth=1.5, label='95th percentile')
    plt.fill_between(range(len(median)), p5, p95, alpha=0.1, color='blue')

    plt.xlabel('Trade Number')
    plt.ylabel('Account Value')
    plt.title('Monte Carlo Simulation - 1000 Paths')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.savefig('monte_carlo.png', dpi=150)
Enter fullscreen mode Exit fullscreen mode

What to Look For

The 5th percentile line is critical. It tells you: "In 95% of scenarios, my account will be above this line." If the 5th percentile shows a 30% drawdown, your strategy will likely experience that at some point.

This is especially relevant when trading with risk limits. Knowing your strategy's drawdown distribution helps you select appropriate parameters. I've compiled drawdown rules for various firms at propfirmkey.com β€” matching these to your Monte Carlo results is a solid approach.

Advanced: Regime-Aware Simulation

Instead of sampling uniformly, weight recent trades more heavily to account for changing market conditions:

def weighted_monte_carlo(trades, num_sims=1000, decay=0.995):
    n = len(trades)
    weights = np.array([decay ** (n - i) for i in range(n)])
    weights /= weights.sum()

    simulations = np.zeros((num_sims, 500))
    for i in range(num_sims):
        sampled = np.random.choice(trades, size=500, p=weights, replace=True)
        simulations[i] = np.cumsum(sampled)

    return simulations
Enter fullscreen mode Exit fullscreen mode

Do you use Monte Carlo analysis in your trading? What sample size do you find reliable?

Top comments (0)