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 npimport pandas as pddef 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, testIn 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