Skip to content
← Research notes

Purged K-Fold Cross-Validation with Embargo in Python

Why standard K-fold leaks information in financial time series, and how purging and embargo remove overlapping labels before validation.

Published 2026-10-11 · Educational explainer, not investment advice

The leakage problem

Financial labels usually span an interval: a label assigned at time t depends on prices up to t + h. When a training observation's label window overlaps a test observation's window, the model has effectively seen part of the test outcome.

Shuffled K-fold makes this worse because neighbouring, highly correlated observations land on both sides of the split. Validation scores then overstate out-of-sample skill.

Purging and embargo

Purging removes every training observation whose label interval overlaps any test label interval. Embargo additionally drops a small band of training observations immediately after the test fold, because serial correlation can carry information forward.

Folds stay contiguous in time; only the training set is trimmed.

import numpy as np
import pandas as pd
def purged_kfold(t1: pd.Series, n_splits=5, embargo_pct=0.01):
"""t1: index = label start, values = label end."""
idx = np.arange(len(t1))
embargo = int(len(t1) * embargo_pct)
for test in np.array_split(idx, n_splits):
t0, t_end = t1.index[test[0]], t1.iloc[test].max()
train = idx[(t1.values < t0) | (t1.index > t_end)]
hi = test[-1] + embargo
train = train[(train < test[0]) | (train > hi)]
yield train, test

In practice

Choose the embargo from the label horizon and the autocorrelation of features. Report the number of purged observations per fold so reviewers can see how much data was removed.

Source: López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley. Chapter 7.

Run this method as part of a structured research workflow.

Open Voltacent Agent