The sandwich, live
Prophet and the sandwich agree on the mean. They disagree on the band, and you can watch why.
Prophet forecasts a trend-and-seasonality mean and wraps it
in a fixed-width Gaussian interval: the same ±1.96σ
whether the series is calm or bursting, with light tails. The sandwich
leaves the mean untouched and changes the coordinates. It runs Prophet in
the z-coordinates of a laplace forecaster,
zt = Φ−1(Ft(yt)),
and maps the forecast back through the exact inverse. Downstairs the noise
is boring; upstairs the band breathes with the volatility clock and the
stated probabilities come true.
upstairs: the series, Prophet's fixed band vs the sandwiched band, with 8-step fans
downstairs: the same points in laplace's coordinates, where Prophet does its work
Hit Volatility burst and watch upstairs: the
sandwiched band widens to keep the dots inside, while Prophet's fixed
band stays put and the points spill past its stated 95%. In the calm
stretches Prophet's band is instead too wide. Downstairs the dots sit in
the same ±1.96 band throughout, because the map absorbed the
structure. laplace runs live from npm; Prophet's part is the
shared calendar mean, which the sandwich never touches.
Why it matters: the band was the problem
Prophet's mean is fine. Its density is not: a fixed Gaussian cannot state an interval that comes true on series whose volatility moves, and its tails are too thin. Because the sandwich is an exact change of variables, the fix costs nothing in accounting and needs no retraining. Measured on 921 non-price FRED series, pre-registered:
| median one-step LL vs laplace | family-weighted (120 families) | |
|---|---|---|
| Prophet raw | −0.755 nats | −4.60 nats |
| Prophet sandwiched | −0.020 nats | −0.025 nats |
The sandwich closes 97% of the density gap without touching Prophet's
calendar model. The full construction, and the same table for other
forecasters and detectors, is on
the sandwich page.
To run it yourself: pip install prophet-laplace
(the API).