Skip to content

Purge and embargo

These functions filter positional training indices. The splitters compose them into complete cross-validation folds. See time utilities for accepted timestamps and horizon conversion.

purgedcv.purge

purge(train_idx: NDArrayAny, test_idx: NDArrayAny, prediction_times: TimesLike, evaluation_times: TimesLike, purge_horizon: Timedelta | None = None) -> NDArrayAny

Drop training rows whose half-open label horizon overlaps any test horizon.

Each test row contributes a half-open horizon [prediction_time - purge_horizon, evaluation_time + purge_horizon). The intervals are merged before filtering, so disjoint test blocks purge only their local overlap zones rather than the full convex hull between them.

A training row at position i is kept iff its label horizon overlaps none of those merged test horizons.

Parameters:

Name Type Description Default
train_idx NDArrayAny

positional indices of training rows.

required
test_idx NDArrayAny

positional indices of test rows.

required
prediction_times TimesLike

prediction times for all rows.

required
evaluation_times TimesLike

evaluation times for all rows.

required
purge_horizon Timedelta | None

optional symmetric padding (None ≡ zero).

None

Returns:

Type Description
NDArrayAny

The subset of train_idx whose horizons do not overlap the test

NDArrayAny

window. Input ordering and dtype are preserved.

Examples:

>>> import numpy as np
>>> import pandas as pd
>>> from purgedcv import purge
>>> pred = pd.Series(pd.date_range("2024-01-01", periods=10, freq="D"))
>>> evalu = pred + pd.Timedelta(days=3)
>>> train_idx = np.array([0, 1, 2, 3, 4, 8, 9])
>>> test_idx = np.array([5, 6, 7])
>>> purge(train_idx, test_idx, pred, evalu)
array([0, 1, 2])

purgedcv.apply_embargo

apply_embargo(train_idx: NDArrayAny, test_idx: NDArrayAny, prediction_times: TimesLike, evaluation_times: TimesLike, embargo: HorizonLike | None = None, *, embargo_observations: int | None = None, embargo_fraction: float | None = None) -> NDArrayAny

Drop training rows inside a post-test embargo window.

Choose at most one embargo mode:

  • embargo uses a wall-clock duration and drops rows whose prediction_time falls inside any closed window [test_evaluation_time, test_evaluation_time + embargo];
  • embargo_observations drops that many row positions immediately after each contiguous test block;
  • embargo_fraction drops floor(n_samples * fraction) row positions after each contiguous test block.

Embargo is asymmetric: only rows after a test boundary are dropped. embargo == 0, embargo_observations == 0, and a fractional mode that rounds to zero are identities.

Parameters:

Name Type Description Default
train_idx NDArrayAny

positional indices of training rows.

required
test_idx NDArrayAny

positional indices of test rows.

required
prediction_times TimesLike

prediction times for all rows.

required
evaluation_times TimesLike

evaluation times for all rows.

required
embargo HorizonLike | None

post-test embargo duration.

None
embargo_observations int | None

number of row positions to drop after each contiguous test block.

None
embargo_fraction float | None

fraction of the full dataset to drop after each contiguous test block. Must be between 0 and 1 inclusive; the observation count is rounded down.

None

Returns:

Type Description
NDArrayAny

The subset of train_idx outside the post-test embargo windows.

NDArrayAny

Input ordering and dtype are preserved.

Examples:

>>> import numpy as np
>>> import pandas as pd
>>> from purgedcv import apply_embargo
>>> pred = pd.Series(pd.date_range("2024-01-01", periods=20, freq="D"))
>>> evalu = pred + pd.Timedelta(days=1)
>>> train_idx = np.array([11, 12, 13, 14])
>>> test_idx = np.arange(5, 10)
>>> apply_embargo(train_idx, test_idx, pred, evalu, pd.Timedelta(days=1))
array([12, 13, 14])