prophet-laplace

"He's not the messiah. He's a very naughty boy." (why) This package makes him useful anyway.

Prophet in a laplace sandwich: the same Prophet API, with calibrated predictive densities. SandwichedProphet fits Prophet in the z-coordinates of a skaters laplace forecaster and maps every forecast back through the exact inverse. Prophet keeps its calendar decomposition, holidays, and extra regressors; the sandwich adds the volatility clock, repeated-value handling, and tails whose stated probabilities come true.

pip install prophet-laplace Source & README

Quickstart

The API mirrors Prophet. Fit on a frame with ds and y, then predict on a future frame.

import pandas as pd
from prophet_laplace import SandwichedProphet

m = SandwichedProphet(k=30)          # k = forecast horizon, in observations
m.fit(df)                            # df has columns ds, y (+ any regressors)

future = pd.DataFrame({"ds": pd.date_range(df["ds"].max() + pd.Timedelta(days=1),
                                           periods=30, freq="D")})
fc = m.predict(future)               # yhat / yhat_lower / yhat_upper, mapped back exactly

The point and interval columns are the median and central 68.27% band of the sandwiched predictive, so the interval reflects the volatility clock and tails rather than Prophet's Gaussian assumption. Extra regressors and Prophet keyword arguments pass straight through.

Calibrated densities

The reason to sandwich is the full predictive density, not just the interval. predictive returns a y-space distribution with logpdf, cdf, and quantile, with exact change-of-variables accounting.

pred = m.predictive(step=1, z_mu=0.0, z_sigma=1.0)

pred.quantile(0.99)    # upper 1% level, tail-aware
pred.logpdf(y_obs)     # score a realised observation
pred.cdf(y_obs)        # PIT value; uniform under calibration

How it works

laplace defines a causal bijection on paths, the Rosenblatt transform zt = Φ−1(Ft(yt)), where Ft is the predictive cdf laplace issued for yt. Under calibration the z stream is close to i.i.d. standard normal, so Prophet is handed a stationarised, unit-scale series and its calendar model works on structure that survives the transform.

Every density maps back with no approximation in the accounting: log fY(y) = log fZ(z) + log ft(y) − log φ(z). Running an opponent between the transform and its inverse is the sandwich; whatever the inner model finds is, by construction, structure laplace alone did not capture.

The measured gap

Measured on 921 non-price FRED series under a pre-registered protocol (statements filed before results, frozen universe, harness and results committed in the skaters repository):

median one-step LL vs laplacefamily-weighted (120 families)
Prophet raw−0.755 nats−4.60 nats
Prophet sandwiched−0.020 nats−0.025 nats

The sandwich closes 97% of Prophet's density gap without retraining anything. The residual 0.02 nats is the epsilon: conditional structure neither model captures. The same construction lifts other forecasters and detectors, tabled on the sandwich page.

v0 demonstrates interoperability: it maps future frames only, and horizons past k reuse the k-step transport, a disclosed approximation. Full API and caveats in the README.