Skip to content
Module 2 / 2
  1. Python for the Trader - From Backtest to Report
  2. Automation and Bots - When It Makes Sense
  3. Walk-Forward and Monte Carlo - The End of Illusion
Algo Systematic Lesson 07

Walk-Forward and Monte Carlo - The End of Illusion

This is the lesson that separates a prototype from a system ready for a forward test. Until now you tested on a single IS/OOS split. The market, however, changes - the 2020, 2022 and 2024 regimes are three different markets. Walk-Forward answers the question: would your system survive further...

Introduction0:00 / 7:00
Illustration for lesson: Walk-Forward and Monte Carlo - The End of Illusion
7 / 7
Author
Zordon Intelligence Sp. z o.o.
Updated
7 min read
Structure sources
2

Introduction

This is the lesson that separates a prototype from a system ready for a forward test. Until now you tested on a single IS/OOS split. The market, however, changes - the 2020, 2022 and 2024 regimes are three different markets. Walk-Forward answers the question: would your system have survived further optimisations and regimes if you had traded it live over the last 3 years? Monte Carlo answers: what is the distribution of the possible paths of the same edge given a random trade order and execution errors?

Without these two tests every backtest is a photograph, not a film. With Walk-Forward and Monte Carlo you get a film with a distribution of scenarios, not one candy-coated equity curve.

Walk-Forward - simulating the life of a trader

The idea: you split history into windows. In each window you optimise on the IS (e.g. 6 months) and test on the OOS (e.g. 2 months) that runs chronologically AFTER the IS. Then you shift the window 2 months forward and repeat. At the end you join all the OOS segments into one Walk-Forward equity curve.

Definitions:
Anchored Walk-Forward: IS grows (0-6m, 0-8m, 0-10m), OOS fixed 2m after IS
Rolling Walk-Forward: IS fixed 6m sliding, OOS 2m after IS (better for detecting degradation)

KursTradera standard: Rolling 70/30 or 6m/2m for H1/D1
Walk-Forward Rolling algorithm:

Data: 2020-01-01 to 2024-12-31 (5 years H1)
IS window = 12 months, OOS = 3 months, step = 3 months

Iteration 1: IS 2020-01 to 2020-12, optimise ATR_mult, test OOS 2021-01 to 2021-03
Iteration 2: IS 2020-04 to 2021-03, OOS 2021-04 to 2021-06
...
Iteration N: IS 2023-10 to 2024-09, OOS 2024-10 to 2024-12

OOS equity = concat of all OOS trades
You compare IS PF vs OOS PF
Walk-Forward metricInterpretation
WF Efficiency = PF_OOS / PF_IS>0.6 good, 0.4-0.6 average, <0.4 overfit
% profitable OOS windows>60% stable, <50% random
EV degradation over timeIs the OOS EV falling in the last windows? If so -> the edge is ending
MaxDD WF OOSThe real drawdown you can expect, larger than the IS one
Python code - Walk-Forward skeleton:

import pandas as pd

def walk_forward(df, is_months=12, oos_months=3):
    results = []
    start = df["timestamp"].min()
    end = df["timestamp"].max()

    current = start + pd.DateOffset(months=is_months)
    while current + pd.DateOffset(months=oos_months) ≤ end:
        is_start = current - pd.DateOffset(months=is_months)
        is_end = current
        oos_start = current
        oos_end = current + pd.DateOffset(months=oos_months)

        is_data = df[(df["timestamp"]>=is_start) & (df["timestamp"]&lt;is_end)]
        oos_data = df[(df["timestamp"]>=oos_start) & (df["timestamp"]&lt;oos_end)]

        best_param = optimize(is_data) 
        oos_trades = backtest(oos_data, best_param)

        results.append(oos_trades)
        current += pd.DateOffset(months=oos_months)

    wf_trades = pd.concat(results)
    return wf_trades

If you do not have an optimize function - manually test 3 parameter values, pick the stable middle one, not the top 1.

Monte Carlo - the randomness you do not control

You have 200 trades with an EV of 0.2R. But the order matters. 10 losses in a row at the start is a different kind of pain than 10 losses spread out. Monte Carlo shuffles the order and simulates thousands of paths.

3 types of Monte Carlo for a trader

1. Reshuffle (the simplest, you must have it): You shuffle the R-multiples without changing their values. It shows the effect of order.

2. Randomisation with a distribution (better): You draw R from the same distribution (mean, std, win rate). It shows the effect of the variability of the distribution.

3. Monte Carlo with execution error (advanced): You add a random error to every trade: slippage of ±0.05R, slip on the SL, a 5% chance of a missed trade. It shows fragility.

import numpy as np

def monte_carlo_reshuffle(trades_df, n_sim=5000):
    R = trades_df["R_net"].values
    sim_equities = []
    sim_maxdd = []

    for _ in range(n_sim):
        shuffled = np.random.permutation(R)
        equity = np.cumsum(shuffled)
        peak = np.maximum.accumulate(equity)
        dd = equity - peak
        sim_equities.append(equity[-1])
        sim_maxdd.append(dd.min())

    return (
        "final_equity_p5": np.percentile(sim_equities, 5),
        "final_equity_median": np.median(sim_equities),
        "final_equity_p95": np.percentile(sim_equities, 95),
        "maxdd_median": np.median(sim_maxdd),
        "maxdd_p95": np.percentile(sim_maxdd, 95),
        "prob_profit": np.mean(np.array(sim_equities) > 0)
    )
Monte Carlo resultDecision
prob_profit <70% after costsSystem too risky for automation
final_equity_p5 < -20R5% of scenarios end tragically - halve your risk
maxdd_p95 = -25R and you risk 1%Prepare for a 25% drawdown of capital

Combining Walk-Forward + Monte Carlo = the final report

The final report of a system that is fit for a forward test:

1. Simple IS/OOS backtest - EV, PF, SQN
2. Walk-Forward Rolling 12m/3m - WF Efficiency, % profitable OOS windows, Equity WF OOS
3. Monte Carlo 5000 reshuffle on WF OOS trades - 5/50/95 percentiles of equity and MaxDD, prob_profit
4. Destructive tests from Lesson 3: 1 bar delay, costs x2, random entry
5. Decision: YES / NO for forward with a risk limit
Example of a decision in the report:

System: BTC H1 Pullback Trend v03
WF Efficiency: 0.62 (IS PF 1.6 -> OOS PF 0.99? No, 1.6*0.62=0.99 too low) -> correction: IS PF 1.8 -> OOS 1.26 = 0.7 good
% profitable OOS windows: 68%
Monte Carlo prob_profit: 82%
Monte Carlo MaxDD p95: -18R
Verdict: To forward with 0.5% risk per trade, Daily Stop -3R, MaxDD stop -15R, recalibration every 3 months

When the plan says do not trade

  1. When WF Efficiency <0.4: The system is over-optimised. It goes back to the drawing board, not to the market.
  2. When Monte Carlo prob_profit <65% after costs x2: You have a 1/3 chance of a loss over the long term despite a positive EV. That is not an edge to automate.
  3. When the WF OOS equity is flat while the IS equity rises: The classic overfit - a beautiful IS, zero OOS. Stop.
  4. When you do not have at least 5 OOS windows in Walk-Forward: Too few to judge stability. You need at least 2 years of H1 data to build 6 windows of 12m/3m.
  5. When you have not calculated the MaxDD p95 from Monte Carlo and have no plan for it: You do not know what the worst 5% of scenarios look like. The market will deliver exactly that scenario in the first month.

The mistakes that cost the most

  1. Anchored Walk-Forward with an IS that grows indefinitely. The old 2020 regime influences a 2024 decision. Rolling is better for detecting change.
  2. Monte Carlo with only 100 simulations. Too few to calculate the 5% tail. Minimum 1000, better 5000. 100 is noise.
  3. Ignoring the clustering of losses. Reshuffle assumes that trades are independent. In reality losses cluster in high vol. Add a block test: shuffle blocks of 10 trades, not individual trades.
  4. Optimising in WF by PF instead of by stability. You pick the top PF from the IS that has the largest variance. Pick the parameter with the median PF among the top 30%, not the top 1.
  5. No recalibration. You run the WF once and trade for a year. WF is a process: every 3 months re-optimise on the rolling IS and check whether the parameters are stable.

Measurable exercise

Goal: Build a Walk-Forward + Monte Carlo report for the system from lesson 5.

Task, 3h:

  1. Take 3 years of H1 data (BTC or another liquid market). Split it Rolling 12m/3m.
  2. For each IS test 3 parameter values (e.g. ATR SL 1.0, 1.5, 2.0) and pick the one with the highest but stable PF (not the lowest and not the highest).
  3. Build the WF OOS equity - join all the OOS trades into one DataFrame.
  4. Calculate:
WF_Efficiency = PF_WF_OOS / PF_IS_avg
%_profitable_windows = count(PF_OOS_window >1) / N_windows
Monte Carlo 2000 simulations on WF OOS: prob_profit, final_eq p5/median/p95, MaxDD p95
  1. Fill in the final table:
MetricValueKursTradera thresholdPASS?
WF Efficiency>0.6
% windows >0>60%
MC prob_profit>70%
MC MaxDD p95<20R
PF after costs x2>1.2

If 4/5 PASS -> the system goes to forward demo with small risk. If <3 PASS -> no edge.

Check yourself

  1. How does Rolling Walk-Forward differ from Anchored, and which one detects edge degradation better?
  2. What is WF Efficiency and what threshold do we treat as the minimum?
  3. Why do you need at least 1000 Monte Carlo simulations rather than 100?
  4. Explain the difference between Monte Carlo reshuffle and randomisation with a distribution.
  5. You have WF Efficiency 0.35, MC prob_profit 60%, MaxDD p95 -30R. Is this a system to trade? What do you do?

Frequently asked questions

How many Walk-Forward windows do I need at minimum? At least 5-6 windows to calculate the % of profitable ones. For H1, 3 years = 9 windows of 12m/3m with a 3m step. For D1 you need 5-7 years. Fewer windows = no statistics.

Does Walk-Forward guarantee a profit in the future? No. It is the best simulation of a trader’s life that we have, but the future may be a different regime than the past. That is why you add Monte Carlo and a daily stop and recalibration.

Can I do Walk-Forward in Excel? Yes, for 3-4 windows by copying the data by hand. For 10+ windows Python is 20x faster. In Excel you build a proof of concept, in Python production.

What if Monte Carlo shows a 10% chance of ruin? Cut the risk per trade by 50% and calculate again. Ruin = MaxDD > your maximum tolerated. If it is still >5%, the system is too risky or the risk is too large. Reduce the position, do not ignore the MC.

When should I recalibrate a live Walk-Forward system? Every fixed period equal to the OOS (e.g. every 3 months if OOS=3m) or after a MaxDD > 1.5* the MC p50. Do not recalibrate after 3 losses. Recalibrate by process, not by emotion.


Advertisement

Key takeaways

  • This is the lesson that separates a prototype from a system ready for a forward test. Until now you tested on a single IS/OOS split. The market, however, changes - the 2020, 2022 and 2024 regimes are three different markets. Walk-Forward answers the question: would your system survive further...

Structure sources

The material is based on source documents. Variable values — fees, limits, regulatory figures — are worth checking at the source before making a decision.

  • TradingView — Pine Script reference
  • Python for Finance — Yves Hilpisch

Disclaimer

  • Educational material. Not investment advice or a recommendation. Trading involves the risk of losing capital.
  • The materials are educational. They are not investment advice or a recommendation within the meaning of financial instruments trading regulations. Numbers in examples are illustrative unless a measurement date and source are given.

Who writes this and how we check it

The materials are written and verified by Redakcja Kurs Tradera — the rules are described on about the site: every number has a source, and we show gaps openly. Report a factual error via contact — corrections are described in the content.

Course progress 0 / 7

Progress is stored only in this browser (localStorage) — there is no account and no copy on the server. Clearing site data will remove it. Manage your data