FAQ

A short list, growing as questions recur.

Why is likelihood the default, not CRPS?

A skater's target is a reusable predictive density, and densities are meant to be chained: each stage refines the residual of the last. Held-out log-likelihood is the score under which those refinements compose, the log-likelihood of a chained forecast being the base score plus the contribution of each stage. CRPS is a good score for a different target, coverage or threshold behaviour, and it is reported alongside as a diagnostic. It is a different contract, not a worse one. The full argument, with the worked example and where CRPS is the right choice, is in why skaters ranks by likelihood, by default.

Isn't the benchmark win just p-hacked?

Reasonable thing to ask of any leaderboard. Rather than take one slice on faith, the robustness explorer lets you cut the non-price benchmark any way you like — at random, by category, frequency, stickiness, martingality — and watch the per-series win-rate recompute live with a bootstrap band. A cherry-picked edge falls apart under reslicing; a real one stays high and tight. The price caveat is stated plainly too: on equity/fx/commodity returns GARCH-t wins, and we say so.

Do I need exogenous data or features for this to be useful?

Not to use it. Univariate distributional prediction is a composable component, not a whole pipeline: it runs on the series you have and plugs in before, during, or after the rest of a model. Exogenous structure enters as another stage. See Scope.

Why not just build a bespoke model?

For a single important series, do. The value here is autonomy and scale: thousands of streams, online, unattended, each returning a full distribution rather than a point. See Scope.

Doesn't the transform leave the hard part, the time-dependence, exactly as hard? (the copula objection)

No, and the distinction is worth being precise about. The copula instinct is right for the static transform: push a series through a fixed marginal F and all the serial dependence is still sitting in the uniforms, exactly as hard as before. This transform is the conditional one. F is a one-step-ahead forecast, refreshed every tick, so the time-dependence the forecaster can model is removed before z exists, and what reaches z is only what it missed.

So the objection is really a claim about the forecaster, and the forecaster earns it. Laplace leads the held-out likelihood race against classical, neural and foundation-model baselines on the non-price universe (the benchmarks), and the transformed streams show what that buys: hand z to ARIMA, ETS, GARCH or Prophet and they find almost nothing left, a few hundredths of a nat between them (results log); hand it to the streaming anomaly detectors in timemachines and they run several times better than on raw data. The dependence problem is not relocated, it is mostly finished by the time z exists.

What does remain as hard as before is cross-stream dependence, which a univariate forecaster cannot see; that is second-stage work in z, with log-likelihood adding across the stages. Watch it in the Rosenblatt demo, or read parade.py; the bookkeeping is about twenty lines.

"A nonlinear transform of an optimal estimate is usually not the optimal estimate of the nonlinear transform." Isn't this exactly that mistake?

The rule is E[g(X)] ≠ g(E[X]), and it bites when a point goes through a nonlinearity. Distributions do not have this problem: if Y has law F then F(Y) is uniform, the pullback of a density is exactly a density, and there is no Jensen gap in the map itself. The only estimated object is F, as in any model.

The rule's stated exception is maximum likelihood, and that exception is the design principle here. Everything is scored by log-likelihood, the identity log p(y) = log f̂(y) + log q(z) − log φ(z) holds for the actual estimated f̂, and estimation error in F therefore shows up as measured miscalibration in the parade rather than hiding inside the nonlinearity. When a point is needed it is the mean of the pulled-back distribution by quadrature, the optimal estimate of the transform.

The codebase contains both versions of the rule: the obedient quadrature, and a point plugged through the inverse map. The plug-in lost, and the results log reports it in a footnote. Move the slider below: the transform of the mean stays at 1 while the mean of the transform does not.

y = exp(σz), z ~ N(0,1)  ·  skew σ

Online methods struggle to adjust parameters without a restart. How is that handled?

There is no fit-then-freeze stage, so there is nothing to restart. Every estimator is recursive with forgetting, the ensemble reweights its candidates every tick, a regime change demotes candidates instead of forcing a refit, and windup guards reset degenerate estimators locally.

Adaptation is monitored rather than hidden: the parade computes prequential calibration each tick, so parameter lag shows up as miscalibration, and memory speed is a knob rather than a buried constant. A structural break still costs something, and the benchmarks measure that cost. Any body can be checkpointed, forked or restarted from its state dict; the reweighting is in terminal.py, and the playground demo lets you switch regimes mid-stream and watch.

Is there a multivariate version?

Not in skaters itself: one stream, one forecaster, one distribution. Cross-stream work happens one layer up, where each stream is reduced to its forecaster's expectation and surprise and downstream models consume those instead of raw values.

The first packaged version is ice-skaters, which feeds streaming regressions in river. It is highly preliminary: the benchmarks there report the losing configurations next to the winning ones, so read the boundaries first.