Repository navigation
v0.1.0
First release. Effect Prophet is a TypeScript implementation of Meta's
Prophet forecasting model, built on
Effect with a Rust/WebAssembly numerical backend, and checked against
Python Prophet 1.4.0.
Forecasting
fit(history, options?)fits a model from{ timestamp, value }rows and returns an
immutable fitted model.predict(model, timestamps | rows)returns, for each row, the
forecast value, the trend, and every additive and multiplicative component broken out.- Three trend types, each fitted with Prophet's MAP model:
- Linear with automatic or explicit changepoints (count, range, prior scale), or none.
- Flat: a constant level. Accepts additive events, regressors and conditional
seasonalities as well as multiplicative components, like Python. - Logistic (growth with a ceiling), with per-row
capacityand optionalfloor, and
automatic or explicit changepoints.
- Seasonality: automatic yearly, weekly and daily patterns that switch on once there is enough
history (two years for yearly, two weeks for weekly, and two days for daily); custom seasonalities with their own
period, Fourier order and prior scale; per-seasonality additive or multiplicative mode; and
conditional seasonalities that apply only on rows where a flag is set. - Events and holidays: named events with date lists, lower and upper windows, per-event prior
scales and additive or multiplicative mode.parseEventCalendarvalidates calendars up front. - Regressors: extra numeric factors with prior scale, additive or multiplicative mode, and
standardization (auto,always,never).getRegressorCoefficientsreports what the model
learned for each regressor. - Multiplicative components: seasonality, events and regressors can scale with the trend
instead of adding to it, with a globalseasonalityModeandholidaysModeand per-component
overrides. - Target scaling: Prophet's
absmaxandminmaxmodes. Logistic growth has explicit
target-scaling and floor policies. - Optimizer settings: choose Newton or L-BFGS through the optimizer option, with Prophet's
defaults, including its L-BFGS-to-Newton fallback and tunable L-BFGS settings. - Uncertainty intervals:
predictUncertaintysimulates future trend changes and observation
noise per path, as Python'svectorized=Falsedoes, and returns either intervals or the raw
samples. A seed is required so results are repeatable. Intervals support up to 10,000 rows and
2,048 samples;output: "samples"is capped at 1,000,000 values. - Input checking: timestamps must be exact UTC ISO strings. Missing targets, duplicate or
unordered rows, bad capacities and missing regressor values are rejected with specific errors
instead of being silently dropped.
Evaluation and model selection
- Rolling-origin cross-validation:
planRollingOriginpreviews the folds andcrossValidate
runs them, with point or interval forecasts, explicit or generated cutoffs, and a configurable
horizon, period and initial window. - Metrics:
performanceMetricscomputes MAE, MSE, RMSE, MAPE, MDAPE, SMAPE and interval
coverage, per row, per horizon, overall or rolling, with a choice of how MAPE treats zero actuals. - Baselines:
crossValidateBaselineandcomparePerformancescore simple rules (last
observation, training mean, seasonal naive) on the same folds and compare them with a model. - Model search:
searchModelsfits and cross-validates candidate settings, ranks them by a
chosen metric, and either records or stops on candidate failures. - Holdout evaluation:
evaluateHoldoutselects settings on a development set and then
evaluates once on a final holdout. Reports can be saved withencodeEvaluationReportand
restored withdecodeEvaluationReport. Plain arrays are accepted for both partitions.
Saving models
encodeFittedModelanddecodeFittedModelturn a fitted model into plain JSON-friendly data and
back, with validation. A restored model forecasts identically, without refitting and without the
fitting backend layer.- The format is this library's own. Python Prophet's
model_to_jsonformat is not supported.
Effect integration
- Everything returns an
Effectwith typed errors. Fitting runs through a
prophetFittingBackendLayerthat you provide. - Typed errors with a
reasonfield:InputValidationError(with issue paths),
FittingError,PredictionError,ModelSerializationErrorand the evaluation, metric, search,
report and holdout errors. Failures inside the WebAssembly engine are reported with the phase
they happened in. - Tracing: named spans on the public operations (
Prophet.fit,Prophet.predictand others)
and on engine calls (effect-prophet.wasm.fitand.predict) that join whatever trace is active.
Fit spans record counts and labels such as rows, changepoints, parameters, solver iterations and
termination reason, and whether the call loaded the engine. They never contain data, names,
coefficients, seeds or error messages. Nothing is exported unless your app provides a tracer.
Numerical backend
- Prophet's Stan model is ported to Rust and compiled to WebAssembly, so no Stan install is
needed. It includes ports of Stan's L-BFGS optimizer and a Newton optimizer, the linear, flat
and logistic densities, and the uncertainty simulator. - Fitting runs 2 to 6 times faster than an earlier version of this library, with bit-identical
results. In the benchmarks, the median warm fit is faster than Python Prophet 1.4.0 for linear
(5.1 ms vs 23.5 ms) and flat (1.6 ms vs 7.9 ms), and for logistic (12.8 ms vs 20.6 ms). The one
benchmarked fit that is slower is logistic with real growth-rate changes (151 ms vs 120 ms). - Uncertainty simulation emits one row at a time with flat memory, so it is not limited by rows
times samples. - The package bundles the notices and license texts for the code it adapts: Prophet (MIT), Stan,
Eigen, nalgebra and Arm optimized-routines, and the Rust crates in the binary.
Verification against Python Prophet
- Compatibility fixtures generated from Python Prophet 1.4.0 are checked in CI. They are
deterministic across CPU implementations. - Benchmark suite of 100+ cases that run both libraries on the same input and compare every
forecast row. Saved baselines cover linear, flat and logistic growth, with default-settings
cases, seasonality, events, regressors, uncertainty, cross-validation, model search and holdout
evaluation. Forecasts must match; internal fit differences are reported but do not fail a case. - Uncertainty benchmarks compare every interval bound with Python's simulation, allowing for
Monte Carlo error.
Documentation
- Docs site (VitePress, deployed to GitHub Pages) with an introduction, a five-minute Effect
primer, a getting-started guide, data preparation, reading forecasts, tracing, and examples for
trends, flat and capped growth, seasonality, events, regressors, uncertainty, cross-validation,
choosing settings, saving models and error handling. Every code sample is a runnable script that
CI type-checks and runs. - Benchmark pages for every case, with inputs, both libraries' forecasts side by side and
timings, plus overview and feature pages. - Python pages: how close the results are, a "Coming from Python" translation guide, and
"What's different". - A README with install, quick start, features and tracing.
Packaging
- ESM package with bundled type declarations for Node.js 22.19 or newer.
effect^4.0.0is a
peer dependency, so your app shares one copy. - The WebAssembly binary ships inside the package. A package test installs the built tarball and
exercises the public API. - Published to npm from GitHub releases using trusted publishing with provenance.
Not included
These Python Prophet features are not implemented in this release:
- Country holiday calendars (
add_country_holidays) - Full Bayesian fitting (
mcmc_samples) - Warm starts
- Forecasting regressors with their own models
- Monthly horizons and custom metrics in cross-validation diagnostics
- Browser and bundler builds (Node.js only for now)
Different from Python on purpose
- An immutable functional API with plain data (
{ timestamp, value }) instead of a mutable
Prophetobject and pandas dataframes. - Strict UTC timestamps; missing targets are rejected rather than dropped.
- No
make_future_dataframe: you supply the future rows. - No plotting.
- Uncertainty uses Prophet's per-path simulation instead of its default vectorized shortcut, and
requires a seed. - Inputs that cannot define a trend, such as every row sharing one timestamp, return an error where
Python returnsNaNforecasts.