Skip to main content

Temporal cross-validation with leakage protection for time-series ML

Project description

temporalcv

Rigorous cross-validation for time series with leakage detection and gap enforcement.

CI PyPI Docs Python Coverage Open In Colab

DocumentationExamplesLeakage Tutorial


Installation

pip install temporalcv

Quick Start

Validate your model for temporal leakage in 4 lines:

from temporalcv import run_gates
from temporalcv.gates import gate_signal_verification

report = run_gates([gate_signal_verification(model, X, y, n_shuffles=100)])
print(report.status)  # HALT, WARN, or PASS
Status Meaning
HALT Signal detected — investigate (legitimate temporal pattern or leakage?)
WARN Marginal signal — proceed with caution
PASS No signal — model has no detectable predictive power

Why temporalcv?

Standard cross-validation shuffles data randomly. For time series, this means training on future data to predict the past — a form of data leakage that inflates metrics.

temporalcv provides:

  • Leakage detection via validation gates (shuffled target test, suspicious improvement)
  • Gap enforcement for h-step forecasting (no lag-feature contamination)
  • High-persistence metrics (MASE, MC-SS) that measure actual skill
  • Conformal coverage with caveats: marginal under exchangeability; time-series autocorrelation can invalidate the guarantee — use AdaptiveConformalPredictor (Gibbs & Candès 2021) for distribution-shift handling

Feature Comparison

Feature temporalcv sklearn sktime darts
Horizon-derived gap (auto) Manual¹ Manual Manual
Leakage detection gates
Conformal prediction Partial
sklearn-compatible API
Statistical tests (DM, PT) Partial

¹ sklearn TimeSeriesSplit(gap=N) (since v0.24) requires the user to compute N from the forecast horizon themselves; temporalcv derives gap = horizon + extra_gap automatically from the horizon parameter.


Core Features

Walk-Forward CV with Gap

from temporalcv import WalkForwardCV

cv = WalkForwardCV(
    window_type="sliding",
    window_size=104,    # 2 years of weekly data
    horizon=2,          # 2-step ahead forecast
    test_size=1
)

for train_idx, test_idx in cv.split(X, y):
    model.fit(X[train_idx], y[train_idx])
    pred = model.predict(X[test_idx])

The horizon parameter enforces a gap between training and test sets, preventing lagged features from leaking target information.

Validation Gates

from temporalcv.gates import gate_signal_verification, gate_suspicious_improvement

gates = [
    gate_signal_verification(model, X, y, n_shuffles=100),
    gate_suspicious_improvement(model_mae, baseline_mae, threshold=0.20),
]

report = run_gates(gates)
if report.status == "HALT":
    raise ValueError(f"Signal detected — investigate: {report.summary()}")

High-Persistence Metrics

When your series is "sticky" (ACF(1) > 0.9), standard MAE lies — predicting "same as yesterday" looks great but adds no value.

from temporalcv.metrics import mase, mc_skill_score

print(f"MASE: {mase(actual, predicted, y_train):.3f}")
print(f"MC-SS: {mc_skill_score(actual, predicted):.3f}")
Metric What It Measures
MASE Error relative to naive forecast (scale-free)
MC-SS Skill only when target moved

Validation Pipeline

flowchart TD
    A[Data + Model] --> B{Validation Gates}
    B -->|HALT| C[Stop & Investigate]
    B -->|WARN| D[Proceed with Caution]
    B -->|PASS| E[Walk-Forward CV]
    E --> F[Statistical Tests]
    F --> G[Deploy]

Common Leakage Patterns

Learn from these failure modes:

Pattern Example Why It's Bad
Rolling stats on full series .rolling().mean() without .shift() Features encode future
No gap for h-step forecast horizon=0 when predicting 2 steps ahead Lag features leak target
Threshold on full data Regime boundary uses all data Classification cheats

See the failure examples gallery for detailed walkthroughs:


Optional Dependencies

pip install temporalcv[benchmarks]   # M4/M5 benchmarks
pip install temporalcv[changepoint]  # PELT algorithm
pip install temporalcv[dev]          # Testing, linting
pip install temporalcv[all]          # Everything

Core: numpy >= 1.21, scipy >= 1.7, scikit-learn >= 1.0, statsmodels >= 0.13, matplotlib >= 3.5 • Optional: pandas >= 1.3 (pip install temporalcv[pandas])

Platforms: Linux, macOS, Windows | Python: 3.10+


Documentation

Resource Description
Quickstart Get running in 5 minutes
Leakage Tutorial Deep dive on detection
API Reference Full API docs
Examples Gallery 21 real-world cases

Validation Evidence

Test Reference Result
DM test golden values R forecast::dm.test() ✓ Match
Type I error rate 500 Monte Carlo sims 5% ± 2%
Conformal coverage Synthetic AR(1) 95% nominal
Benchmark M4 Competition (4,773 series) ✓ Validated

See Testing Strategy for details.


Citation

@software{temporalcv2025,
  author    = {Behring, Brandon},
  title     = {temporalcv: Temporal cross-validation with leakage protection},
  year      = {2025},
  publisher = {GitHub},
  url       = {https://github.com/brandon-behring/temporalcv}
}

Ecosystem

Part of the Rigorous AI Engineering ecosystem:

Project Description
temporalcv (this repo) Temporal cross-validation with leakage detection
ir-eval Statistical retrieval evaluation with drift detection
research-kb Graph-boosted semantic search for research literature

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

MIT License — see LICENSE

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

temporalcv-2.3.0.tar.gz (552.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

temporalcv-2.3.0-py3-none-any.whl (279.8 kB view details)

Uploaded Python 3

File details

Details for the file temporalcv-2.3.0.tar.gz.

File metadata

  • Download URL: temporalcv-2.3.0.tar.gz
  • Upload date:
  • Size: 552.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for temporalcv-2.3.0.tar.gz
Algorithm Hash digest
SHA256 3f813a00bcbead8cbbcc90387fd2e754c11cd4e56427f9a846cd8657005f60f0
MD5 3ffe95f7e9e21e032337ade3d99ca974
BLAKE2b-256 dbf723e9e91ae628e43537f75d6de852da4d40fa18edde54bdfecc1d61558bf9

See more details on using hashes here.

Provenance

The following attestation bundles were made for temporalcv-2.3.0.tar.gz:

Publisher: publish.yml on brandon-behring/temporalcv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file temporalcv-2.3.0-py3-none-any.whl.

File metadata

  • Download URL: temporalcv-2.3.0-py3-none-any.whl
  • Upload date:
  • Size: 279.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for temporalcv-2.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 96eec20402042f3afd49226b67ce4ea0fea98f1acd475729344e27f41e64a044
MD5 00fd9ada7e93409b94dce0f53ee63708
BLAKE2b-256 a64d02c92e5490fdd45ada69940f4965dfa2908cdc888c3b6acd0425116b94cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for temporalcv-2.3.0-py3-none-any.whl:

Publisher: publish.yml on brandon-behring/temporalcv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page