HKUDS/Vibe-Trading · error · ValueError
Purge and embargo removed all training samples for fold {fol
Error message
Purge and embargo removed all training samples for fold {fold} What it means
After removing training observations whose labels overlap the test block (purge) and those within the embargo window after it, no training rows remain for the current fold. The splitter refuses to yield an empty train set because fitting a model on it would crash or silently produce garbage scores.
Source
Thrown at agent/src/quantlib/crossvalidation.py:270
label_ends = np.arange(n_samples)
else:
label_ends = _as_label_spans(label_end_times, n_samples)
embargo_size = int(round(n_samples * embargo_fraction))
boundaries = np.linspace(0, n_samples, n_folds + 1).astype(int)
for fold in range(n_folds):
start, stop = int(boundaries[fold]), int(boundaries[fold + 1])
if stop <= start:
continue
test_mask = np.zeros(n_samples, dtype=bool)
test_mask[start:stop] = True
train, purged, embargoed = _apply_purge_and_embargo(
label_ends, test_mask, embargo_size
)
if train.size == 0:
raise ValueError(f"Purge and embargo removed all training samples for fold {fold}")
yield Split(
train=train,
test=np.arange(start, stop),
purged=purged,
embargoed=embargoed,
test_bounds=(start, stop - 1),
)
def group_purged_kfold_splits(
groups: Sequence[object] | pd.Series | np.ndarray,
n_folds: int = 5,
embargo_fraction: float = DEFAULT_EMBARGO_FRACTION,
) -> Iterator[Split]:
"""Purged and embargoed K-fold cross-validation for panel and multi-asset datasets.
Groups all observations sharing a time group identifier (e.g. date or bar timestamp)
so that simultaneous observations across different assets are never split acrossView on GitHub (pinned to 80ffdda44c)
Solutions
- Reduce embargo_fraction
- Reduce n_folds so test blocks (and their purge footprints) are larger and fewer
- Use a shorter label horizon or a longer sample so enough non-overlapping train rows exist
- Switch to purged_walk_forward_splits which naturally accounts for chronological label spans
Example fix
// before splits = list(purged_kfold_splits(X, n_folds=10, embargo_fraction=0.3, label_end_times=le)) // after splits = list(purged_kfold_splits(X, n_folds=5, embargo_fraction=0.05, label_end_times=le))
Defensive patterns
Strategy: try-catch
Validate before calling
embargo_size = int(embargo_fraction * len(X)) # rough sanity: widest label span + embargo must leave room in the smallest train region assert (len(X) // n_folds) > (label_ends.max() - np.arange(len(label_ends))).max() + embargo_size, 'risk of empty train fold'
Try / catch
try:
splits = list(purged_kfold_splits(X, n_folds=n, embargo_fraction=e, label_end_times=le))
except ValueError as err:
if 'removed all training samples' in str(err):
n, e = max(2, n // 2), e / 4 # relax and retry once
splits = list(purged_kfold_splits(X, n_folds=n, embargo_fraction=e, label_end_times=le))
else:
raise Prevention
- Keep label horizon well below fold size
- Start with embargo_fraction=0 and increase gradually
- Prefer purged_walk_forward_splits for very long labels
When it happens
Trigger: Long label horizons relative to the sample plus a large embargo_fraction: for a fold near the start or end of the data, every candidate training row overlaps a test label or falls inside the embargo window (e.g. label_end_times spanning 50% of the sample with 10 folds).
Common situations: Overlapping multi-day labels on short price history, high fold counts with wide labels, or an aggressive embargo_fraction copied from a longer dataset.
Related errors
- embargo_fraction must be in [0, 1), got {embargo_fraction}
- a label cannot end before the observation it belongs to star
- label_end_times has {span_ends.size} entries but the sample
- n_folds must be at least {MIN_FOLDS}, got {n_folds}
- {n_samples} samples cannot make {n_folds} folds
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/73e8eed34fe677d7.
Report an issue: GitHub.