temporalcv 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. temporalcv-1.0.0/.gitignore +64 -0
  2. temporalcv-1.0.0/LICENSE +21 -0
  3. temporalcv-1.0.0/PKG-INFO +408 -0
  4. temporalcv-1.0.0/README.md +340 -0
  5. temporalcv-1.0.0/pyproject.toml +174 -0
  6. temporalcv-1.0.0/src/temporalcv/__init__.py +473 -0
  7. temporalcv-1.0.0/src/temporalcv/bagging/__init__.py +215 -0
  8. temporalcv-1.0.0/src/temporalcv/bagging/base.py +397 -0
  9. temporalcv-1.0.0/src/temporalcv/bagging/strategies/__init__.py +17 -0
  10. temporalcv-1.0.0/src/temporalcv/bagging/strategies/block_bootstrap.py +150 -0
  11. temporalcv-1.0.0/src/temporalcv/bagging/strategies/feature_bagging.py +171 -0
  12. temporalcv-1.0.0/src/temporalcv/bagging/strategies/residual_bootstrap.py +311 -0
  13. temporalcv-1.0.0/src/temporalcv/bagging/strategies/stationary_bootstrap.py +184 -0
  14. temporalcv-1.0.0/src/temporalcv/benchmarks/__init__.py +99 -0
  15. temporalcv-1.0.0/src/temporalcv/benchmarks/base.py +412 -0
  16. temporalcv-1.0.0/src/temporalcv/benchmarks/fred.py +233 -0
  17. temporalcv-1.0.0/src/temporalcv/benchmarks/gluonts.py +208 -0
  18. temporalcv-1.0.0/src/temporalcv/benchmarks/m5.py +165 -0
  19. temporalcv-1.0.0/src/temporalcv/benchmarks/monash.py +258 -0
  20. temporalcv-1.0.0/src/temporalcv/changepoint.py +614 -0
  21. temporalcv-1.0.0/src/temporalcv/compare/__init__.py +117 -0
  22. temporalcv-1.0.0/src/temporalcv/compare/adapters/__init__.py +49 -0
  23. temporalcv-1.0.0/src/temporalcv/compare/adapters/multi_series.py +302 -0
  24. temporalcv-1.0.0/src/temporalcv/compare/adapters/statsforecast_adapter.py +216 -0
  25. temporalcv-1.0.0/src/temporalcv/compare/base.py +571 -0
  26. temporalcv-1.0.0/src/temporalcv/compare/docs.py +370 -0
  27. temporalcv-1.0.0/src/temporalcv/compare/results.py +366 -0
  28. temporalcv-1.0.0/src/temporalcv/compare/runner.py +499 -0
  29. temporalcv-1.0.0/src/temporalcv/conformal.py +1561 -0
  30. temporalcv-1.0.0/src/temporalcv/cv.py +1945 -0
  31. temporalcv-1.0.0/src/temporalcv/cv_financial.py +703 -0
  32. temporalcv-1.0.0/src/temporalcv/diagnostics/__init__.py +23 -0
  33. temporalcv-1.0.0/src/temporalcv/diagnostics/influence.py +240 -0
  34. temporalcv-1.0.0/src/temporalcv/diagnostics/sensitivity.py +250 -0
  35. temporalcv-1.0.0/src/temporalcv/gates.py +1790 -0
  36. temporalcv-1.0.0/src/temporalcv/guardrails.py +637 -0
  37. temporalcv-1.0.0/src/temporalcv/inference/__init__.py +41 -0
  38. temporalcv-1.0.0/src/temporalcv/inference/block_bootstrap_ci.py +472 -0
  39. temporalcv-1.0.0/src/temporalcv/inference/wild_bootstrap.py +334 -0
  40. temporalcv-1.0.0/src/temporalcv/lag_selection.py +407 -0
  41. temporalcv-1.0.0/src/temporalcv/metrics/__init__.py +152 -0
  42. temporalcv-1.0.0/src/temporalcv/metrics/asymmetric.py +537 -0
  43. temporalcv-1.0.0/src/temporalcv/metrics/core.py +587 -0
  44. temporalcv-1.0.0/src/temporalcv/metrics/event.py +718 -0
  45. temporalcv-1.0.0/src/temporalcv/metrics/financial.py +607 -0
  46. temporalcv-1.0.0/src/temporalcv/metrics/quantile.py +485 -0
  47. temporalcv-1.0.0/src/temporalcv/metrics/volatility_weighted.py +665 -0
  48. temporalcv-1.0.0/src/temporalcv/persistence.py +722 -0
  49. temporalcv-1.0.0/src/temporalcv/py.typed +2 -0
  50. temporalcv-1.0.0/src/temporalcv/regimes.py +578 -0
  51. temporalcv-1.0.0/src/temporalcv/stationarity.py +478 -0
  52. temporalcv-1.0.0/src/temporalcv/statistical_tests.py +3217 -0
  53. temporalcv-1.0.0/src/temporalcv/validators/__init__.py +55 -0
  54. temporalcv-1.0.0/src/temporalcv/validators/theoretical.py +503 -0
  55. temporalcv-1.0.0/tests/__init__.py +1 -0
  56. temporalcv-1.0.0/tests/adversarial/__init__.py +0 -0
  57. temporalcv-1.0.0/tests/anti_patterns/__init__.py +13 -0
  58. temporalcv-1.0.0/tests/anti_patterns/test_boundary_violations.py +235 -0
  59. temporalcv-1.0.0/tests/anti_patterns/test_lag_leakage.py +229 -0
  60. temporalcv-1.0.0/tests/benchmarks/__init__.py +5 -0
  61. temporalcv-1.0.0/tests/benchmarks/test_cv_benchmarks.py +282 -0
  62. temporalcv-1.0.0/tests/benchmarks/test_gate_benchmarks.py +260 -0
  63. temporalcv-1.0.0/tests/benchmarks/test_metric_benchmarks.py +308 -0
  64. temporalcv-1.0.0/tests/conftest.py +337 -0
  65. temporalcv-1.0.0/tests/fixtures/golden_reference.json +106 -0
  66. temporalcv-1.0.0/tests/integration/__init__.py +8 -0
  67. temporalcv-1.0.0/tests/integration/test_e2e_benchmark.py +583 -0
  68. temporalcv-1.0.0/tests/integration/test_full_workflow.py +304 -0
  69. temporalcv-1.0.0/tests/known_answer/__init__.py +0 -0
  70. temporalcv-1.0.0/tests/monte_carlo/__init__.py +1 -0
  71. temporalcv-1.0.0/tests/monte_carlo/test_conformal_coverage.py +240 -0
  72. temporalcv-1.0.0/tests/monte_carlo/test_dm_coverage.py +218 -0
  73. temporalcv-1.0.0/tests/monte_carlo/test_wild_bootstrap_coverage.py +238 -0
  74. temporalcv-1.0.0/tests/property/__init__.py +4 -0
  75. temporalcv-1.0.0/tests/property/test_cv_invariants.py +262 -0
  76. temporalcv-1.0.0/tests/property/test_financial_cv_invariants.py +321 -0
  77. temporalcv-1.0.0/tests/property/test_gate_invariants.py +210 -0
  78. temporalcv-1.0.0/tests/property/test_metric_invariants.py +337 -0
  79. temporalcv-1.0.0/tests/property/test_stationarity_invariants.py +205 -0
  80. temporalcv-1.0.0/tests/reproducibility/__init__.py +5 -0
  81. temporalcv-1.0.0/tests/reproducibility/test_seed_determinism.py +317 -0
  82. temporalcv-1.0.0/tests/test_bagging.py +689 -0
  83. temporalcv-1.0.0/tests/test_benchmarks.py +520 -0
  84. temporalcv-1.0.0/tests/test_block_bootstrap_ci.py +463 -0
  85. temporalcv-1.0.0/tests/test_changepoint.py +548 -0
  86. temporalcv-1.0.0/tests/test_compare.py +697 -0
  87. temporalcv-1.0.0/tests/test_conformal.py +1321 -0
  88. temporalcv-1.0.0/tests/test_cross_fit.py +277 -0
  89. temporalcv-1.0.0/tests/test_cv.py +1450 -0
  90. temporalcv-1.0.0/tests/test_cv_financial.py +399 -0
  91. temporalcv-1.0.0/tests/test_edge_cases.py +476 -0
  92. temporalcv-1.0.0/tests/test_gates.py +904 -0
  93. temporalcv-1.0.0/tests/test_gates_residual.py +397 -0
  94. temporalcv-1.0.0/tests/test_gates_theoretical.py +438 -0
  95. temporalcv-1.0.0/tests/test_golden_reference.py +154 -0
  96. temporalcv-1.0.0/tests/test_guardrails.py +496 -0
  97. temporalcv-1.0.0/tests/test_influence.py +272 -0
  98. temporalcv-1.0.0/tests/test_integration.py +392 -0
  99. temporalcv-1.0.0/tests/test_lag_selection.py +448 -0
  100. temporalcv-1.0.0/tests/test_metrics_asymmetric.py +616 -0
  101. temporalcv-1.0.0/tests/test_metrics_core.py +341 -0
  102. temporalcv-1.0.0/tests/test_metrics_event.py +651 -0
  103. temporalcv-1.0.0/tests/test_metrics_financial.py +628 -0
  104. temporalcv-1.0.0/tests/test_metrics_quantile.py +658 -0
  105. temporalcv-1.0.0/tests/test_metrics_volatility.py +574 -0
  106. temporalcv-1.0.0/tests/test_persistence.py +501 -0
  107. temporalcv-1.0.0/tests/test_regimes.py +599 -0
  108. temporalcv-1.0.0/tests/test_residual_bootstrap.py +430 -0
  109. temporalcv-1.0.0/tests/test_sensitivity.py +384 -0
  110. temporalcv-1.0.0/tests/test_stationarity.py +518 -0
  111. temporalcv-1.0.0/tests/test_statistical_tests.py +3572 -0
  112. temporalcv-1.0.0/tests/test_stratified_reports.py +414 -0
  113. temporalcv-1.0.0/tests/test_theoretical_bounds.py +379 -0
  114. temporalcv-1.0.0/tests/test_wild_bootstrap.py +244 -0
  115. temporalcv-1.0.0/tests/validation/__init__.py +9 -0
  116. temporalcv-1.0.0/tests/validation/test_residual_diagnostics.py +310 -0
  117. temporalcv-1.0.0/tests/validation/test_shuffled_target.py +305 -0
  118. temporalcv-1.0.0/tests/validation/test_synthetic_ar1.py +280 -0
  119. temporalcv-1.0.0/tests/validation/test_theoretical_bounds.py +329 -0
@@ -0,0 +1,64 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ .Python
8
+ build/
9
+ develop-eggs/
10
+ dist/
11
+ downloads/
12
+ eggs/
13
+ .eggs/
14
+ lib/
15
+ lib64/
16
+ parts/
17
+ sdist/
18
+ var/
19
+ wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+
24
+ # Virtual environments
25
+ .env
26
+ .venv
27
+ env/
28
+ venv/
29
+ ENV/
30
+
31
+ # pytest / coverage
32
+ .pytest_cache/
33
+ .hypothesis/
34
+ .coverage
35
+ .coverage.*
36
+ htmlcov/
37
+ .tox/
38
+ .nox/
39
+
40
+ # Sphinx build output
41
+ docs/_build/
42
+
43
+ # mypy
44
+ .mypy_cache/
45
+ .dmypy.json
46
+ dmypy.json
47
+
48
+ # IDEs
49
+ .idea/
50
+ .vscode/
51
+ *.swp
52
+ *.swo
53
+ *~
54
+
55
+ # Jupyter
56
+ .ipynb_checkpoints/
57
+
58
+ # OS
59
+ .DS_Store
60
+ Thumbs.db
61
+
62
+ # Benchmark data and intermediate files
63
+ None/
64
+ .tracking/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Brandon Behring
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,408 @@
1
+ Metadata-Version: 2.4
2
+ Name: temporalcv
3
+ Version: 1.0.0
4
+ Summary: Temporal cross-validation with leakage protection for time-series ML
5
+ Project-URL: Homepage, https://github.com/brandonmbehring-dev/temporalcv
6
+ Project-URL: Documentation, https://github.com/brandonmbehring-dev/temporalcv#readme
7
+ Project-URL: Repository, https://github.com/brandonmbehring-dev/temporalcv
8
+ Project-URL: Issues, https://github.com/brandonmbehring-dev/temporalcv/issues
9
+ Author: Brandon Behring
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: cross-validation,forecasting,leakage-detection,machine-learning,temporal-validation,time-series,walk-forward
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Scientific/Engineering
24
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.9
27
+ Requires-Dist: numpy>=1.21
28
+ Requires-Dist: scikit-learn>=1.0
29
+ Requires-Dist: scipy>=1.7
30
+ Requires-Dist: statsmodels>=0.13
31
+ Provides-Extra: all
32
+ Requires-Dist: datasetsforecast>=0.0.8; extra == 'all'
33
+ Requires-Dist: fredapi>=0.5; extra == 'all'
34
+ Requires-Dist: gluonts>=0.13; extra == 'all'
35
+ Requires-Dist: pandas>=1.3; extra == 'all'
36
+ Requires-Dist: statsforecast>=1.5; extra == 'all'
37
+ Provides-Extra: benchmarks
38
+ Requires-Dist: datasetsforecast>=0.0.8; extra == 'benchmarks'
39
+ Requires-Dist: fredapi>=0.5; extra == 'benchmarks'
40
+ Provides-Extra: changepoint
41
+ Requires-Dist: ruptures>=1.1; extra == 'changepoint'
42
+ Provides-Extra: compare
43
+ Requires-Dist: statsforecast>=1.5; extra == 'compare'
44
+ Provides-Extra: dev
45
+ Requires-Dist: hypothesis>=6.0; extra == 'dev'
46
+ Requires-Dist: mypy>=1.0; extra == 'dev'
47
+ Requires-Dist: pip-audit>=2.0; extra == 'dev'
48
+ Requires-Dist: pre-commit>=3.0; extra == 'dev'
49
+ Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
50
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
51
+ Requires-Dist: pytest>=7.0; extra == 'dev'
52
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
53
+ Provides-Extra: docs
54
+ Requires-Dist: myst-parser>=2.0.0; extra == 'docs'
55
+ Requires-Dist: sphinx-autodoc-typehints>=1.25; extra == 'docs'
56
+ Requires-Dist: sphinx-copybutton>=0.5.2; extra == 'docs'
57
+ Requires-Dist: sphinx-rtd-theme>=2.0; extra == 'docs'
58
+ Requires-Dist: sphinx>=7.2; extra == 'docs'
59
+ Provides-Extra: fred
60
+ Requires-Dist: fredapi>=0.5; extra == 'fred'
61
+ Provides-Extra: gluonts
62
+ Requires-Dist: gluonts>=0.13; extra == 'gluonts'
63
+ Provides-Extra: monash
64
+ Requires-Dist: datasetsforecast>=0.0.8; extra == 'monash'
65
+ Provides-Extra: pandas
66
+ Requires-Dist: pandas>=1.3; extra == 'pandas'
67
+ Description-Content-Type: text/markdown
68
+
69
+ # temporalcv
70
+
71
+ **Temporal cross-validation with leakage protection for time-series ML.**
72
+
73
+ [![CI](https://github.com/brandonmbehring-dev/temporalcv/actions/workflows/ci.yml/badge.svg)](https://github.com/brandonmbehring-dev/temporalcv/actions)
74
+ [![PyPI](https://img.shields.io/pypi/v/temporalcv.svg)](https://pypi.org/project/temporalcv/)
75
+ [![Python](https://img.shields.io/pypi/pyversions/temporalcv.svg)](https://pypi.org/project/temporalcv/)
76
+ [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/brandonmbehring-dev/temporalcv/blob/main/notebooks/demo.ipynb)
77
+
78
+ ---
79
+
80
+ ## Why temporalcv?
81
+
82
+ Time-series ML has a leakage problem. Standard cross-validation doesn't respect temporal order, and even "proper" walk-forward implementations often miss subtle bugs:
83
+
84
+ - **Lag features computed on full series** (leaks future information)
85
+ - **No gap between train and test** (target leaks into features)
86
+ - **Thresholds computed on full series** (future information in classification)
87
+
88
+ temporalcv provides **validation gates** that catch these bugs before they corrupt your results.
89
+
90
+ ---
91
+
92
+ ## Architecture
93
+
94
+ ```
95
+ ┌─────────────────────────────────────────────────────────────────────────┐
96
+ │ VALIDATION PIPELINE │
97
+ ├─────────────────────────────────────────────────────────────────────────┤
98
+ │ │
99
+ │ Data + Model │
100
+ │ │ │
101
+ │ ▼ │
102
+ │ ┌──────────────────────────────────────────────────────────────┐ │
103
+ │ │ VALIDATION GATES │ │
104
+ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
105
+ │ │ │ Shuffled │ │ Temporal │ │ Suspicious │ │ │
106
+ │ │ │ Target Test │ │ Boundary │ │ Improvement │ │ │
107
+ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
108
+ │ │ │ │ │ │ │
109
+ │ │ └─────────────────┼─────────────────┘ │ │
110
+ │ │ ▼ │ │
111
+ │ │ ┌───────────────────────┐ │ │
112
+ │ │ │ HALT / WARN / PASS │ │ │
113
+ │ │ └───────────────────────┘ │ │
114
+ │ └──────────────────────────────────────────────────────────────┘ │
115
+ │ │ │
116
+ │ HALT ◄───────────┼───────────► PASS │
117
+ │ │ │ │ │
118
+ │ ▼ ▼ ▼ │
119
+ │ ┌─────────┐ ┌─────────┐ ┌─────────────────────────────┐ │
120
+ │ │ STOP & │ │ WARN │ │ CONTINUE TO: │ │
121
+ │ │INVESTIGATE│ │ USER │ │ - Walk-Forward CV │ │
122
+ │ └─────────┘ └─────────┘ │ - Statistical Tests (DM/PT)│ │
123
+ │ │ - Conformal Prediction │ │
124
+ │ │ - Deployment │ │
125
+ │ └─────────────────────────────┘ │
126
+ └─────────────────────────────────────────────────────────────────────────┘
127
+ ```
128
+
129
+ ### Gate Priority
130
+
131
+ | Status | Meaning | Action |
132
+ |--------|---------|--------|
133
+ | **HALT** | Critical failure detected | Stop immediately, investigate |
134
+ | **WARN** | Suspicious signal | Proceed with caution, verify externally |
135
+ | **PASS** | Validation passed | Continue to next stage |
136
+
137
+ ---
138
+
139
+ ## What Makes This Unique
140
+
141
+ 1. **Shuffled Target Test** — The definitive leakage detector
142
+ - If your model beats a permuted baseline, features encode target position
143
+ - Catches: rolling stats on full series, lookahead bias, centered windows
144
+
145
+ 2. **HALT/WARN/PASS Framework** — Actionable validation status
146
+ - Not just metrics, but decisions
147
+ - Prioritized: HALT > WARN > PASS
148
+
149
+ 3. **Temporal-Aware Conformal Prediction**
150
+ - Adaptive conformal for distribution shift (Gibbs & Candès 2021)
151
+ - Approximate coverage for time series (exact guarantees require exchangeability)
152
+
153
+ 4. **High-Persistence Metrics** — For sticky series (ACF(1) > 0.9)
154
+ - MASE, MC-SS ratio, directional accuracy
155
+ - Standard metrics mislead on near-unit-root data
156
+
157
+ 5. **sklearn Integration** — Drop-in replacement
158
+ - `WalkForwardCV` works with `cross_val_score`, `GridSearchCV`
159
+ - Proper gap enforcement for h-step forecasting
160
+
161
+ ---
162
+
163
+ ## Julia Implementation
164
+
165
+ The Julia version of this library is available in a separate repository: **[temporalcv.jl](https://github.com/brandondebehring/temporalcv.jl)**.
166
+
167
+ It provides native Julia implementations of the same core validation gates and statistical tests.
168
+
169
+ ---
170
+
171
+ ## Comparison vs sklearn TimeSeriesSplit
172
+
173
+ | Feature | temporalcv | sklearn | Winner |
174
+ |---------|------------|---------|--------|
175
+ | Gap Enforcement | ✅ Native | ✅ v1.0+ | Both |
176
+ | Window Types | Expanding + Sliding | Expanding only | **temporalcv** |
177
+ | Leakage Detection | 3 validation gates | None | **temporalcv** |
178
+ | Statistical Tests | DM, PT, HAC | None | **temporalcv** |
179
+ | Conformal Prediction | Split + Adaptive | External (MAPIE) | **temporalcv** |
180
+ | Financial CV | Purging + Embargo | None | **temporalcv** |
181
+ | Split Speed | ~0.035 ms | ~0.012 ms | sklearn |
182
+
183
+ **Key Insight**: sklearn's `TimeSeriesSplit` handles basic temporal splits well. temporalcv adds the validation layer that catches bugs *before* they corrupt your results.
184
+
185
+ ---
186
+
187
+ ## Installation
188
+
189
+ ```bash
190
+ pip install temporalcv
191
+ ```
192
+
193
+ For development:
194
+ ```bash
195
+ pip install temporalcv[dev]
196
+ ```
197
+
198
+ ### Optional Dependencies
199
+
200
+ temporalcv has modular dependencies for specific features:
201
+
202
+ | Feature | Install Command | When Needed |
203
+ |---------|----------------|-------------|
204
+ | **Benchmarks** | `pip install temporalcv[benchmarks]` | Running M4/M5 benchmarks |
205
+ | **Changepoint** | `pip install temporalcv[changepoint]` | PELT algorithm (requires `ruptures`) |
206
+ | **Model Comparison** | `pip install temporalcv[compare]` | Benchmark runner with DM tests |
207
+ | **Development** | `pip install temporalcv[dev]` | Testing, linting, type checking |
208
+ | **All Features** | `pip install temporalcv[all]` | Everything above |
209
+
210
+ **Core dependencies** (always installed):
211
+ - `numpy >= 1.23.0`
212
+ - `scipy >= 1.9.0`
213
+ - `scikit-learn >= 1.1.0`
214
+ - `pandas >= 1.5.0`
215
+
216
+ ### Platform Compatibility
217
+
218
+ | Platform | Status | Tested Versions |
219
+ |----------|--------|-----------------|
220
+ | **Linux** | ✅ Fully supported | Ubuntu 20.04+, Debian 11+ |
221
+ | **macOS** | ✅ Fully supported | macOS 11+ (Intel & Apple Silicon) |
222
+ | **Windows** | ✅ Fully supported | Windows 10+, Windows Server 2019+ |
223
+
224
+ **Python versions**: 3.9, 3.10, 3.11, 3.12
225
+
226
+ **CI Matrix**: All combinations tested on every PR via GitHub Actions.
227
+
228
+ ---
229
+
230
+ ## Quick Example
231
+
232
+ ```python
233
+ from temporalcv import run_gates, WalkForwardCV
234
+ from temporalcv.gates import gate_shuffled_target, gate_suspicious_improvement
235
+
236
+ # Validate your model doesn't have leakage
237
+ # Step 1: Compute gate results
238
+ # Note: n_shuffles>=100 required for statistical power in permutation mode (default)
239
+ gate_results = [
240
+ gate_shuffled_target(my_model, X, y, n_shuffles=100),
241
+ gate_suspicious_improvement(model_mae, persistence_mae, threshold=0.20),
242
+ ]
243
+
244
+ # Step 2: Aggregate into report
245
+ report = run_gates(gate_results)
246
+
247
+ if report.status == "HALT":
248
+ raise ValueError(f"Leakage detected: {report.summary()}")
249
+
250
+ # Walk-forward CV with proper gap enforcement
251
+ cv = WalkForwardCV(
252
+ window_type="sliding",
253
+ window_size=104,
254
+ horizon=2, # Minimum required separation for 2-step forecasting
255
+ extra_gap=0, # Optional: add safety margin (default: 0)
256
+ test_size=1
257
+ )
258
+
259
+ for train_idx, test_idx in cv.split(X, y):
260
+ # Guaranteed: train_idx[-1] + gap < test_idx[0]
261
+ model.fit(X[train_idx], y[train_idx])
262
+ predictions = model.predict(X[test_idx])
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Features
268
+
269
+ ### Validation Gates
270
+ - **Shuffled target test** - Definitive leakage detection
271
+ - **Synthetic AR(1) bounds** - Theoretical validation
272
+ - **Suspicious improvement detection** - >20% = investigate
273
+ - **Temporal boundary audit** - No future in features
274
+
275
+ ### Statistical Tests
276
+ - **Diebold-Mariano test** - With HAC variance estimation
277
+ - **Pesaran-Timmermann test** - Direction accuracy (3-class)
278
+
279
+ ### Walk-Forward CV
280
+ - Sliding and expanding windows
281
+ - Gap parameter enforcement
282
+ - sklearn-compatible splitter API
283
+
284
+ ### High-Persistence Metrics
285
+ - **MC-SS** - Move-Conditional Skill Score
286
+ - **Move-only MAE** - Error when target moved
287
+ - **Direction Brier** - Probabilistic direction accuracy
288
+
289
+ ---
290
+
291
+ ## Examples
292
+
293
+ Real-world case studies demonstrating key features:
294
+
295
+ | Example | Description |
296
+ |---------|-------------|
297
+ | [01_leakage_detection.py](examples/01_leakage_detection.py) | Shuffled target test catches lookahead bias |
298
+ | [02_walk_forward_cv.py](examples/02_walk_forward_cv.py) | Gap enforcement for h-step forecasting |
299
+ | [03_statistical_tests.py](examples/03_statistical_tests.py) | DM test: is improvement significant? |
300
+ | [04_high_persistence.py](examples/04_high_persistence.py) | MASE metrics for sticky series |
301
+ | [05_conformal_prediction.py](examples/05_conformal_prediction.py) | Adaptive intervals under distribution shift |
302
+
303
+ **Interactive Demo**: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/brandonmbehring-dev/temporalcv/blob/main/notebooks/demo.ipynb)
304
+
305
+ ---
306
+
307
+ ## Benchmark Comparison
308
+
309
+ ### Feature Matrix
310
+
311
+ | Feature | temporalcv | sklearn | sktime | Darts |
312
+ |---------|------------|---------|--------|-------|
313
+ | **Gap enforcement** | ✅ Built-in | ❌ Manual | ❌ Manual | ❌ Manual |
314
+ | **Leakage detection** | ✅ Gates | ❌ None | ❌ None | ❌ None |
315
+ | **Horizon validation** | ✅ Warnings | ❌ None | ❌ None | ❌ None |
316
+ | **Statistical tests (DM)** | ✅ HAC variance | ❌ None | ✅ Basic | ❌ None |
317
+ | **Conformal prediction** | ✅ Adaptive | ❌ None | ❌ None | ✅ Split |
318
+ | **sklearn compatible** | ✅ Full | ✅ Native | ✅ Full | ❌ Partial |
319
+
320
+ ### Why Not Just sklearn's TimeSeriesSplit?
321
+
322
+ ```python
323
+ from sklearn.model_selection import TimeSeriesSplit
324
+
325
+ # sklearn: No gap, no horizon validation
326
+ cv = TimeSeriesSplit(n_splits=5) # Target leakage possible for h>1
327
+
328
+ # temporalcv: Gap enforcement + validation
329
+ from temporalcv import WalkForwardCV
330
+ cv = WalkForwardCV(n_splits=5, horizon=2, extra_gap=0) # total_separation = horizon + extra_gap
331
+ ```
332
+
333
+ ### Benchmark Runner
334
+
335
+ Compare models across datasets:
336
+
337
+ ```python
338
+ from temporalcv.benchmarks import create_synthetic_dataset
339
+ from temporalcv.compare import run_benchmark_suite, NaiveAdapter
340
+
341
+ datasets = [create_synthetic_dataset(seed=i) for i in range(3)]
342
+ report = run_benchmark_suite(datasets, [NaiveAdapter()], include_dm_test=True)
343
+ print(report.to_markdown())
344
+ ```
345
+
346
+ ---
347
+
348
+ ## Documentation
349
+
350
+ ### Getting Started
351
+ - [**Quickstart Guide**](docs/quickstart.md) - Get started in 5 minutes
352
+
353
+ ### Tutorials
354
+ - [Leakage Detection](docs/tutorials/leakage_detection.md) - Catch data leakage with validation gates
355
+ - [Walk-Forward CV](docs/tutorials/walk_forward_cv.md) - Proper temporal cross-validation
356
+ - [High-Persistence Metrics](docs/tutorials/high_persistence.md) - Metrics for sticky series
357
+ - [Uncertainty Quantification](docs/tutorials/uncertainty.md) - Prediction intervals with coverage guarantees
358
+
359
+ ### API Reference
360
+ - [Validation Gates](docs/api/gates.md) - HALT/PASS/WARN framework
361
+ - [Walk-Forward CV](docs/api/cv.md) - sklearn-compatible temporal CV
362
+ - [Statistical Tests](docs/api/statistical_tests.md) - DM test, PT test, HAC variance
363
+ - [High-Persistence Metrics](docs/api/persistence.md) - MC-SS, move-conditional MAE
364
+ - [Regime Classification](docs/api/regimes.md) - Volatility and direction regimes
365
+ - [Conformal Prediction](docs/api/conformal.md) - Distribution-free intervals
366
+ - [Bagging](docs/api/bagging.md) - Time-series-aware bagging
367
+ - [Event Metrics](docs/api/metrics.md) - Brier score, PR-AUC
368
+
369
+ ### Internal
370
+ - [Planning Documentation](docs/plans/INDEX.md)
371
+ - [Ecosystem Gap Analysis](docs/plans/reference/ecosystem_gaps.md)
372
+
373
+ ### Help & Support
374
+ - [**Troubleshooting Guide**](docs/troubleshooting.md) - Common issues and solutions
375
+ - [**Testing Strategy**](docs/testing_strategy.md) - How temporalcv is tested
376
+ - [**Benchmark Methodology**](docs/benchmarks/methodology.md) - How benchmark results are generated
377
+ - [**GitHub Issues**](https://github.com/brandonmbehring-dev/temporalcv/issues) - Report bugs or request features
378
+
379
+ ---
380
+
381
+ ## Citation
382
+
383
+ If you use temporalcv in your research, please cite:
384
+
385
+ ```bibtex
386
+ @software{temporalcv2025,
387
+ author = {Behring, Brandon},
388
+ title = {temporalcv: Temporal cross-validation with leakage protection},
389
+ year = {2025},
390
+ publisher = {GitHub},
391
+ url = {https://github.com/brandonmbehring-dev/temporalcv},
392
+ version = {1.0.0}
393
+ }
394
+ ```
395
+
396
+ See [CITATION.cff](CITATION.cff) for additional citation formats.
397
+
398
+ ---
399
+
400
+ ## License
401
+
402
+ MIT License - see [LICENSE](LICENSE)
403
+
404
+ ---
405
+
406
+ ## Contributing
407
+
408
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.