Walk-Forward, Purged K-Fold, & Combinatorial Purged CV
Created by Dr. Pedram Jahangiry | Enhanced with Claude
This tool walks through three ways of splitting time ordered data for validation: walk-forward (expanding and rolling), purged K-fold, and combinatorial purged CV. Set the forecast horizon and the number of lag features, and the page works out which observations must be dropped to stop look-ahead bias, then shows exactly which values each row touches. It follows the methodology in Marcos López de Prado's Advances in Financial Machine Learning, including how combinatorial purged CV builds multiple backtest paths.
Walk-Forward CV respects the temporal ordering of time series by always training on past data and testing on future data. It comes in two variants:
Walk-forward needs one buffer. When the target is h steps ahead, the last training labels reach into the test period, so leave a gap of h − 1 rows between train and test. Click any split below to see where each training row's label lands.
Each square in the chart above is one row: its features sit at that square, and its label sits h squares to the right. The splits chart only shows where a row starts. This view shows where its label ends.
Standard K-fold treats observations as interchangeable and often shuffles them, but time series data is not i.i.d. Nearby observations are correlated, and every row reaches forward through its label and backward through its lag features. Rows near a test fold can therefore carry test information into training. That is data leakage, or look-ahead bias in finance language.
Purged K-Fold CV (López de Prado, 2018) fixes this with two buffers whose size comes straight from your model setup:
Even with contiguous, unshuffled folds, a label that looks h steps ahead and features that look p steps back cross the fold boundaries. Switch to Naive K-fold below and the red marks show exactly which test values leak into training.
A training row is purged when its label span reaches into the shaded window, and embargoed when its lag features do. Hover or tap any row.
Purging handles what the label sees ahead, and the embargo handles what the features see behind. Both sizes come from the model: h − 1 for the purge and p for the embargo. Every interior test block costs 2(h − 1) + p training rows, so long horizons and many lags make purged K-fold expensive on short series.
Rows after the test block still train the model, so it learns from data that comes later than the test period. Purging removes overlap, not the future. For an estimate a trader could have produced in real time, use walk-forward with a gap of h − 1.
CPCV (López de Prado, 2018) extends purged K-fold to answer a question the other methods cannot: how much does out-of-sample performance vary across alternative histories?
How it works: Divide data into N groups, choose k as test groups in each split. This produces C(N, k) splits. Each observation is tested C(N−1, k−1) times. Path p gives group g the forecast from the p-th split that tested g, so a repeated split number means those groups were held out together, and across the paths every out-of-sample forecast is used once.
Each path is stitched from models that trained partly on data later than the period they are scored on, so no single path is a backtest a trader could have run. The paths also share training data, so they are correlated rather than independent draws.
CPCV produces multiple backtest paths, so you see the distribution of out-of-sample performance instead of one number. A strategy that only shines on a few paths was probably lucky. Turn on purge and embargo to see the cost: with a long horizon, a train group squeezed between two test groups can disappear completely.
| Property | Standard K-Fold | Walk-Forward | Purged K-Fold | CPCV |
|---|---|---|---|---|
| Never trains on future data | ✗ | ✓ | ✗ (trains after the test block) | ✗ (trains after the test groups) |
| Keeps time blocks intact (no shuffling) | ✗ (often shuffled) | ✓ | ✓ | ✓ |
| Prevents label leakage | ✗ | ✓ (with a gap of h − 1) | ✓ (purge) | ✓ (purge) |
| Prevents feature leakage | ✗ | ✓ (training always comes first) | ✓ (embargo) | ✓ (embargo) |
| Multiple backtest paths | ✗ | ✗ | ✗ | ✓ |
| Distribution of results for overfitting analysis | ✗ | ✗ | ✗ | ✓ |
| Data efficiency | High | Lower | High | High |
| Backtest paths | 1 | 1 | 1 | φ(N,k) |