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
|
Returns:
| Type | Description |
|---|---|
NDArrayAny
|
The subset of |
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:
embargouses a wall-clock duration and drops rows whoseprediction_timefalls inside any closed window[test_evaluation_time, test_evaluation_time + embargo];embargo_observationsdrops that many row positions immediately after each contiguous test block;embargo_fractiondropsfloor(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 |
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])