HKUDS/Vibe-Trading · error · ValueError

embargo_fraction must be in [0, 1), got {embargo_fraction}

Error message

embargo_fraction must be in [0, 1), got {embargo_fraction}

What it means

embargo_fraction must lie in [0, 1); it is the fraction of the sample embargoed after each test block. Values below 0 or >= 1 (including 1.0) are rejected because the embargo size is computed as a fraction of n_samples and 1.0 would drop the entire training set.

Source

Thrown at agent/src/quantlib/crossvalidation.py:247

            label is assumed to resolve within its own bar, so purging removes
            only the boundary and the embargo does the remaining work.
        n_folds: Number of folds, at least :data:`MIN_FOLDS`.
        embargo_fraction: Fraction of the sample embargoed after each test block.

    Yields:
        One :class:`Split` per fold, in chronological order of the test block.

    Raises:
        ValueError: If ``n_folds`` is below :data:`MIN_FOLDS`, exceeds the
            sample size, if ``embargo_fraction`` is negative or at least 1, or
            if ``label_end_times`` does not match the sample.
    """
    if n_folds < MIN_FOLDS:
        raise ValueError(f"n_folds must be at least {MIN_FOLDS}, got {n_folds}")
    if n_samples < n_folds:
        raise ValueError(f"{n_samples} samples cannot make {n_folds} folds")
    if not 0.0 <= embargo_fraction < 1.0:
        raise ValueError(
            f"embargo_fraction must be in [0, 1), got {embargo_fraction}"
        )

    if label_end_times is None:
        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

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Convert percent to fraction: divide by 100
  2. If you need an embargo of N bars, pass N / n_samples (and verify it stays < 1)
  3. Validate config: assert 0.0 <= embargo_fraction < 1.0 at load time

Example fix

// before
splits = list(purged_kfold_splits(X, n_folds=5, embargo_fraction=5, label_end_times=le))
// after
splits = list(purged_kfold_splits(X, n_folds=5, embargo_fraction=5/100, label_end_times=le))
Defensive patterns

Strategy: validation

Validate before calling

assert 0.0 <= embargo_fraction < 1.0, 'embargo_fraction must be a fraction in [0,1)'

Prevention

When it happens

Trigger: Calling purged_kfold_splits (or the group variant) with embargo_fraction=1.0, a negative value, or a percentage like 5 instead of 0.05.

Common situations: Config expressed in percent (5 meaning 5%) passed directly, copying embargo in bars instead of fraction, or floating-point drift reaching exactly 1.0.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/aa38a107f6508c64. Report an issue: GitHub.