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.2.0.tar.gz (546.2 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.2.0-py3-none-any.whl (273.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for temporalcv-2.2.0.tar.gz
Algorithm Hash digest
SHA256 7783a3a9ea9085c64fe5e80d8c3f7749b78420a592d2032ace5e0cb08c139ce3
MD5 3a70364f2ce03b020a2c5e5885dfa5a3
BLAKE2b-256 b0f410eca50b9009941d6ef87afc697f36055e1ac76521ce2bf3cdaf754ab2f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for temporalcv-2.2.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: temporalcv-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 273.4 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4f846c210b28708b99154cbb9a3026d6e9ddf85d2c61653e9b2dd7c9ee77318c
MD5 c1143eaae53ebe99d05495eb9a3a4bec
BLAKE2b-256 cb8054c25327357c876559231be2f8e337904cb82491b4caf7b4e11defc377ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for temporalcv-2.2.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