Releases: microprediction/skaters
Release list
v0.13.0 — GPD tails by default
Generalized-Pareto tails, on by default. Every laplace predictive now splices censored-ML GPD tails over the body's own tail region (pass tails="gaussian" to opt out). The body's matured PIT defines frozen warm-up-quantile thresholds per horizon; exceedances fit a GPD per side (Grimshaw profile); logpdf, cdf, quantile, crps, and the parade's state["z"] all read the corrected tail. Measured on non-price FRED: +0.027 nats/tick median held-out log-likelihood (84–85% of series), and the parade-z alarm rate at nominal 1e-3 drops from ~8× over budget to ~1.4× — the anomaly thresholds now mean what they say in the far tail too. CRPS unchanged within noise; ~5% runtime; masking-resistant intake (winsorised with a changepoint escape); spliced predictives round-trip through Dist.from_dict.
Also since v0.12.1: the coverage/calibration study (laplace's nominal-90% interval covers a median 89.3% and is within ±2 pts of nominal on 65% of 1,000 series, vs 94–95% actual coverage for AutoARIMA/AutoETS/GARCH-t's "90%" bands — harness committed as benchmarks/coverage_study.py); release gates; arXiv and JOSS paper variants; six new copyable skills on the site (basic-use, laplace-sandwich, mean-reversion, anomaly-detection, residual-review, pretty-timeseries-page) and the "Running normalization" demo.
Python + JavaScript twins; parity 105,658 values across 54 scenarios; 671 tests pass on Python 3.10–3.13.
0.12.1 — skater state is pure data
Terminal-ensemble leaf closures moved out of the state dict into the wrapper: laplace state now pickles, enabling checkpoint/restore in streaming deployments. No numerical change (full suite + JS parity green). Found by the timemachines hardening suite. Python (PyPI) and JS twin (npm) both bumped.
skaters 0.12.0 — better default forecaster
laplace's default terminal-leaf scale_alpha is now 0.03 (was 0.01) — the residual-scale EWMA tracks changing volatility faster, which was leaving log-likelihood on the table through volatility clusters.
Validated on the continuous FRED universe, out-of-sample (600 series; 387 non-price + 213 price): beats the old default on held-out log-likelihood (~+0.02 nats median, ~79% of series) and CRPS (~−0.2% relative, ~80% of series), on both asset classes. Better calibration helps every proper score — it's not a CRPS-for-LL trade.
- New optional
scale_alpha/scaleAlphaargument onlaplace; pass0.01to reproduce the previous default (and the paper's numbers). - Python + JS mirrored, parity re-verified to 1e-6; 619 tests pass.
- Method, harness, and full tables on the
laplace-leaf-experimentsbranch (benchmarks/leaf_experiments/).
Publishes to npm via the release workflow (provenance, parity gate).
skaters 0.11.4 (npm)
Docs release: the README now leads with the live in-browser race demo — the JS port racing arima, @bsull/augurs (ETS and MSTL), and Prophet (Stan compiled to WASM) on real FRED series, scored on held-out log-likelihood. No code changes since 0.11.3.
skaters 0.11.3 (npm)
First npm publish since 0.11.0 — carries three accumulated fixes (0.11.1 and
0.11.2 were bumped but never released), all parity-verified against Python:
- 0.11.3 —
Dist.logpdfno longer underflows to-Infinityfor finite
inputs when the scale collapses near a Dirac; computed as a log-sum-exp over
per-component log densities. Numerically identical wherever it did not
underflow (parity vectors unchanged). - 0.11.2 — RLS covariance windup in
ar/grouped_arunder low-excitation
input could overflowPtoInf(~74k steps) and yieldNaNforecasts;P
now resets when it grows implausibly large. - 0.11.1 — the CRPS leaf's exponentiated-gradient update could overflow
exp()toInf, normalizing weights toNaN; now stabilized by subtracting
the max exponent.
Publishes to npm via the release workflow (provenance, parity gate).
v0.11.0 — multi-scale laplace by default at k>1
laplace(k>1) is now multi-scale by default: one full instance per decimation stride (default {1, ceil(sqrt(k)), k}), each horizon mixing its eligible scales' predictives under likelihood softmax weights. scales=[1] opts out; k=1 is unchanged (bitwise).
On 7,335 non-price FRED series the mixture beats the native fan-out on 64% of series at h=20 (mean held-out LL +1.10 → +2.81) and wins every h=20 log-likelihood contest vs AutoARIMA / AutoETS / GARCH-t / Prophet, at no short-horizon cost.
Correctness fixes: JS warm-up mixtures were never pruned (missing Dist.length); the JS port now matches Python 3.12's Neumaier-compensated sum() via fsum(); prune() pair selection is deterministic under platform ulp noise. Parity: 104,678 values across 53 scenarios.
Also: reviewer-revision of the JSS paper, docs sweep, rewritten examples, playground demo showing the clocks being mixed live.
v0.10.0 — one forecaster
Breaking change: skaters now exposes exactly one forecaster, laplace. doob and mean_revert are removed — they were strictly dominated by laplace in every regime tested (including levels, doob's design home). Mean-reversion and GARCH-style volatility remain available by composition: ou_transform, garch_leaf, and the multi-step (k>1) OU pool group inside laplace.
from skaters import laplace # the one forecaster
f = laplace(k=1)
f = laplace(k=1, leaf=garch_leaf) # opt-in GARCH(1,1)-t leaf for heavy tailsAlso since 0.9.1
- Calibration fix:
ema/standardize/theta/driftmeasured their residual against post-update state, shrinking the predictive interval by(1-α)(e.g. a nominal 90% interval covered 81%). Fixed — now ~90% coverage. Point forecasts unchanged. - Ensemble forgetting:
laplacenow usesforget=0.99, keeping it adaptive to regime change at +0.02 nats on held-out FRED data. - Honest scope:
skatersis positioned and benchmarked as a general-purpose forecaster for non-price economic series — highest mean held-out log-likelihood and best win-rate vs every baseline, including GARCH-t (68%/65% family-weighted) across 894 non-price FRED series. No free lunch on price/returns — there a fitted GARCH-t wins, and we recommend it.
Python ⇄ JavaScript parity maintained to 1e-6; CI now gates tests + parity before publish.
v0.9.1
Patch: expose skaters.__version__ (read from package metadata). No functional changes since v0.9.0.
v0.9.0
Adds two mean-reversion capabilities and a GARCH leaf, all dual-runtime (Python = JavaScript to 1e-6). No breaking changes.
New forecaster: mean_revert
The mean-reverting counterpart to doob — an online Bayesian average over Ornstein–Uhlenbeck reversion speeds, for multi-step mean reversion (pairs-trading spreads, volatility, rates). Built on a new reusable ou_transform primitive.
from skaters import mean_revert
f = mean_revert(k=10) # signed spreads — linear
f = mean_revert(k=10, coordinate=0.5) # positive series (vol/rates) — sqrt/CIRlaplace gains multi-step mean reversion
At k>1, the candidate pool now includes an OU mean-reversion group. The one-step pool is unchanged (same speed/results). New laplace(leaf=...) override to swap the terminal leaf.
New terminal leaf: garch_leaf
An opt-in GARCH(1,1)-t conditional-variance leaf for price/return series. laplace(leaf=garch_leaf) recovers ~60% of the held-out log-likelihood gap to a fitted GARCH-t — dependency-free and online.
from skaters import laplace, garch_leaf
f = laplace(k=1, leaf=garch_leaf)Dual-runtime preserved
All new code is ported to JavaScript and parity-checked to 1e-6 — mean_revert, ou_transform, and garch_leaf run in the browser via Pyodide too.
Docs & paper
Tweedie / score-driven framing cited (Hansen & Tong 2026; Harvey 2013); a multi-step forecast-fan demo added to the playground; SOTA benchmark results refreshed.
skaters 0.8.1
No library code changes — skaters 0.8.1 is identical to 0.8.0 at runtime. This release is documentation, benchmarks, and the paper. (Re-publishes with the corrected README/metadata and the new [project.urls].)
Benchmarks — honest, and broadened to eight distributional baselines
The SOTA study now scores laplace against everything we could find that claims a distributional one-step forecast, all through the identical Dist interface on held-out log-likelihood and CRPS:
- AutoARIMA, AutoETS (statsforecast)
- SARIMAX, ETS (statsmodels — exact closed-form Gaussian)
- GARCH(1,1)-t (
arch— the heavy-tail / volatility-clustering SOTA) - NeuralForecast-StudentT (a neural density head)
- AutoARIMA + conformal and + ACI
On 500 FRED change-series, laplace wins the per-series log-likelihood race against all eight. The decisive test is GARCH-t — the heavy-tail specialist — which laplace still edges on the continuous subset (mean continuous logpdf 2.86 vs 2.72). On CRPS it beats the smoothing/GARCH/neural baselines, ties the ARIMA family, and loses to the CRPS-optimized conformal variants. Win-rates are now per-series (the earlier family-clustered numbers were inflated and have been corrected throughout).
The NeuralForecast 100% is explicitly flagged as NF's weak online-univariate regime, not its global-training strength.
Paper
A detailed Journal of Statistical Software write-up — papers/skaters-jss.tex (builds to skaters-jss.pdf) — covering the Dist algebra, model first, conform last, the lattice projection, coordinate learning, the doob martingale clock, and the eight-baseline study.
Other
- New top-level
SKILL.md— a tongue-in-cheekforecast-roastcode-review skill. - The benchmark harness is now parallelized across cores (
ProcessPoolExecutor).