HKUDS/Vibe-Trading · error · ValueError
label_end_times is empty
Error message
label_end_times is empty
What it means
_as_label_spans converts label end times into per-observation span end positions for purged cross-validation. When given a pandas Series, an empty Series means there are no observations/labels to build spans from, so the function refuses immediately rather than producing empty, ambiguous output.
Source
Thrown at agent/src/quantlib/crossvalidation.py:133
Args:
label_end_times: Either a pandas Series whose index is the label start
time and whose values are the label end time, or a positional array
where element ``i`` is the last positional index observation ``i``'s
label depends on.
n_samples: Expected number of samples, checked when supplied.
Returns:
Integer array ``ends`` where ``ends[i]`` is the last positional index
that observation ``i``'s label covers. Always at least ``i``.
Raises:
ValueError: If the input is empty, not 1-D, holds a non-finite value, or
declares a label ending before it starts.
"""
if isinstance(label_end_times, pd.Series):
if label_end_times.empty:
raise ValueError("label_end_times is empty")
starts = label_end_times.index
ends = label_end_times.to_numpy()
# searchsorted on the start index converts label end *times* into label
# end *positions*; the right insertion point minus one keeps a label
# that ends between two observations attached to the earlier one.
positions = np.searchsorted(starts, ends, side="right") - 1
positions = np.clip(positions, np.arange(len(starts)), len(starts) - 1)
span_ends = positions.astype(int)
else:
span_ends = np.asarray(label_end_times, dtype=float)
if span_ends.ndim != 1:
raise ValueError(f"label_end_times must be 1-D, got shape {span_ends.shape}")
if span_ends.size == 0:
raise ValueError("label_end_times is empty")
if not np.isfinite(span_ends).all():
raise ValueError("label_end_times holds a non-finite value")
span_ends = span_ends.astype(int)
if (span_ends < np.arange(span_ends.size)).any():View on GitHub (pinned to 80ffdda44c)
Solutions
- Check `len(label_end_times) > 0` before calling the split functions
- Fix the upstream filter/merge that emptied your dataset
- Skip empty folds/windows explicitly in your CV loop
Example fix
# before folds = purged_kfold_splits(pd.Series(dtype=float), n_splits=5) # after ends = pd.Series([...non-empty...], index=X.index) folds = purged_kfold_splits(ends, n_splits=5)
Defensive patterns
Strategy: validation
Validate before calling
if not isinstance(label_end_times, pd.Series) or label_end_times.empty:
raise ValueError('label_end_times must be a non-empty pd.Series')
folds = purged_kfold_splits(label_end_times, n_splits=5) Type guard
def is_non_empty_series(x) -> bool:
return isinstance(x, pd.Series) and not x.empty and x.notna().all() Try / catch
try:
folds = purged_kfold_splits(ends, n_splits=5)
except ValueError as e:
if 'empty' in str(e):
logger.warning('empty fold window skipped')
folds = []
else:
raise Prevention
- Assert a minimum row count before running CV
- Log dataset size at each CV boundary to catch empty windows
- Skip empty groups explicitly in walk-forward loops
When it happens
Trigger: Calling purged_kfold_splits, purged_walk_forward_splits, combinatorial_purged_splits, or detect_boundary_leakage with label_end_times = pd.Series(dtype=object) or an empty pd.Series.
Common situations: Empty feature frames after filtering by date or ticker; upstream groupby producing an empty group; loading an empty CSV slice in a walk-forward pipeline.
Related errors
- label_end_times must be 1-D, got shape {span_ends.shape}
- label_end_times holds a non-finite value
- fit_ornstein_uhlenbeck needs a series that varies; this one
- find_hedge_ratio needs y and x sharing one index
- find_hedge_ratio needs at least 3 aligned observations, got
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/631b7f4f2fd79f14.
Report an issue: GitHub.