A fast SOTA univariate distributional time-series prediction algorithm
翻譯準備中
正在載入完整 README。
檢視完整 README ↗A light, accurate, autonomous distributional forecaster for non-price economic series in particular. Watch here.
Laplace beats (almost) everything.
And it beats them across nearly every regime, giving ground only on price/returns (to GARCH-t) and, narrowly, on the hard, repeating waveforms (to CSP1).
Laplace is fast, dependency-free, online univariate distributional forecasting with parity-locked ports in Python, JavaScript, R, Julia and Rust (all matched to the reference within 1e-6; JavaScript and Pyodide run it in the browser). It's a general-purpose forecaster for non-price economic series. On FRED change-series scored one step ahead, it beats AutoARIMA, AutoETS, AutoTheta, GARCH-t and NPTS on held-out log score at every frequency, and on 2,179 daily series it beats every zero-shot foundation model tested. On 5,576 monthly series the newest foundation models (Timestral-209M, TimeH2O, TimesFM 3.0, t0-gamma) are ahead, by 0.05 to 0.10 nats per step at the median, and on 3,013 weekly series three of the four are. On price and return series laplace, GARCH-t and the foundation models are level. Every foundation-model figure depends on how its quantiles are turned into a density (see the benchmark paper).
Not for price/return series: We recommend GARCH-t there instead.
When CRPS is the target:
A scoring rule is a settlement rule — match it to what you actually want. skaters defaults to held-out
log-likelihood because it ranks reusable densities, and on CRPS laplace still beats most of the competition. But if
your target really is CDF shape or threshold behaviour, CRPS is a reasonable contract and a method like conformal
prediction may suit — just know it is a different contract, not a better density.
(Why skaters ranks by likelihood, by default →)
pip install skaters
from skaters import laplace
f = laplace(k=3)
state = None
forecast = None # the fan issued LAST tick, aimed at this y
for y in observations:
if forecast is not None:
forecast[0].logpdf(y) # one-step-ahead log score
forecast[0].cdf(y) # one-step-ahead PIT
forecast, state = f(y, state)
forecast[0].mean # point forecast for the NEXT tick
forecast[0].std # uncertainty
forecast[0].quantile(0.975) # upper edge of the central 95% band
Score a forecast only against observations that arrive after it was issued; the predictive returned alongside y aims at the next tick, and the parade in state["pit"]/state["z"] does this bookkeeping for you. Every skater returns a list of predictive distributions, one for each horizon $h = 1, \ldots, k$. Point forecasts, uncertainty, density evaluation, and quantiles are all aspects of the same object.
laplace — the general forecasterskaters exposes exactly one forecaster, laplace. Everything else is a
building block (transforms, leaves, ensembles) you can compose. ("skater" is the
concept — any (y, state) -> ([Dist], state) function, borrowed from the old
timemachines package.) At multi-step horizons (k>1) it is multi-scale by
default (below).
from skaters import laplace
f = laplace(k=1)
A likelihood-weighted Bayesian ensemble over a large candidate population (EMA,
differencing, drift, Holt, AR, fractional differencing, seasonal, a Yeo-Johnson
coordinate grid, a fast/slow two-systems block, and — at multi-step horizons
(k>1) — an Ornstein–Uhlenbeck mean-reversion group). Three things are on by
default, each a free or near-free win:
objective="crps"). On a
2,500-series FRED study this matches a CRPS specialist on CRPS and lifts
likelihood on real data. Switch back with objective="likelihood".sticky=True) — near-Dirac atoms on the exact values a
series revisits. Free on continuous data (it vanishes), a large win on
grid/repeating series (policy rates, posted prices).f = laplace(k=1) # CRPS leaf + lattice, both on
f = laplace(k=1, objective="likelihood") # pure-likelihood leaf
f = laplace(k=1, sticky=False) # no lattice projection
Calibration state, free. Every arriving point is resolved against the
forecasts previously made for it: state["pit"][m-1] is its probability
integral transform under the m-step-ahead predictive issued m steps ago
(roughly Uniform(0,1) when calibrated) and state["z"][m-1] the same through
the standard-normal quantile (roughly N(0,1); z is clamped to ±7.03, never
infinite). That calibrated-surprise signal is the null model streaming anomaly
detection is built on, and that work lives in its own project:
timemachines — calibrated
online anomaly detection with honest false-alarm rates, built on skaters.
On the hard-waveform arm (near-deterministic, repeating cycles) CSP is handed the seasonal period, while laplace is not and must infer structure generically. Its edge there reflects that head start, not a like-for-like loss. ↩
以上為 README 的開頭部分。其餘內容請閱讀原文。 檢視完整 README ↗