Time Series Cross Validation

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 Cross Validation

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:

  • Expanding Window: the training set grows over time, and each split adds more historical data. Uses all available past data, but training cost increases with each split.
  • Rolling (Sliding) Window: the training set has a fixed size that slides forward and drops the oldest data as new data is added. Better for non-stationary data where old patterns may be irrelevant.

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.

5
5
2
3
0
Train
Train whose label reaches the test period
Gap (purged)
Test
Unused
Split 1: where each 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.

Key Insight

Purged K-Fold Cross Validation

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:

  • Purging: drop training rows whose label span (t, t+h] overlaps the test labels, on both sides of each test block. That is h − 1 rows per side.
  • Embargo: drop the next p rows after the post-test purge, because their lag features are built from test period values.

⚠ Why Not Standard K-Fold?

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.

Split:
Test fold:
Train
Test
Purged
Embargo
Train that leaks (naive)
No usable row
Every fold at a glance (each column is one time point t; click a fold to inspect it)
What each row touches in fold 3

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.

Key Insight

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.

What purging does not fix

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.

Combinatorial Purged Cross Validation (CPCV)

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?

  • Multiple backtest paths: instead of one backtest path, CPCV generates φ(N,k) = C(N−1, k−1) paths that each span the entire dataset.
  • A distribution, not a point: with many paths you get a distribution of performance metrics (e.g., Sharpe ratios). That supports overfitting analysis such as the Probability of Backtest Overfitting (PBO), which is computed with the related CSCV procedure.

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.

Keep in mind

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.

6
2
Train
Test

All C(N, k) Splits
Backtest Paths — click a path to highlight its source splits

Key Insight

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.

Comparison of Methods

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)