Skip to content

Releases

v1.0.0

Choose a tag to compare

@jer-k jer-k released this 07 Nov 23:19
cc63777

The first stable release, covering everything Python Prophet 1.4.0 does except plotting. From now
on, breaking changes to the public API wait for a new major version. Each kind of bad input now fails with its own typed error instead of one
InputValidationError, so code that catches that error or reads its input field must move to
the new errors.

Changed

  • Typed input errors. InputValidationError and ValidationInput are removed. Each kind of
    input has its own error, with a fixed list of reason values: ObservationError,
    PredictionInputError, OptionsError, FutureTimestampsError, UncertaintyOptionsError,
    EvaluationPlanError, MetricOptionsError, SearchOptionsError and HoldoutInputError.

    • Every input error keeps issues and message. Errors about rows also name the first
      rejected row with rowIndex, field and name, and the others give its location in path.
    • Rejected shapes have reason: "invalid-shape", and an empty history "empty".
    • When the input has several kinds of problems, the error reports the first kind found and
      every problem of that kind.
    • SearchOptionsError names a failing candidate with candidateIndex and keeps the original
      error in cause, which isn't saved when a report is encoded.
    • The InputError union and isInputError match any of them, for example with
      Effect.catchIf.
    • Holdout reports record a candidate's input error as its error and reason. Saved reports
      that recorded an InputValidationError no longer decode.

    See Input errors.

Fixed

  • Automatic changepoints now match Prophet when a candidate lands exactly between two rows.
    NumPy's linspace divides before it multiplies, and Effect Prophet multiplied first, so the two
    could round to different rows and move a changepoint by one. On one 30-row history this changed
    the trend by about 0.82; it now matches Python's.
  • predictUncertainty and predictWithIntervals given around 150,000 rows or more crashed with
    RangeError: Maximum call stack size exceeded. They now fail with a PredictionError whose
    reason is "simulation-limit", like any request over the 10,000-row limit.
  • decodeEvaluationReport froze the caller's own selected.options object, so editing it
    afterwards threw. It now returns a frozen copy.

Documentation

  • The tracing guide,
    README and home page now say that the attributes Effect Prophet sets contain no user data. A
    failed span still carries its error, and exporters such as OtlpTracer send its message and
    stack trace, which can name your fields.
  • Benchmark pages no longer compare speeds when the two libraries do different work: Bayesian
    predict, uncertainty with MAP or Bayesian fits, and evaluation cases. They show "Not compared:
    different work" with a note, and keep both raw times.
  • Regressors explains the units of
    additive and multiplicative coefficients, and that mode defaults to seasonalityMode.
  • The seasonality and events guides no longer say an individual event takes its own mode.
    holidaysMode sets one mode for every event.
  • Coming from Python maps
    mcmc_samples to mcmc, and What's different
    notes that cross-validation has no counterpart to extra_output_columns.
  • The Bayesian guide and the Python differences page separate mcmc option limits, which fail
    with an OptionsError, from the limit on kept values, which fails with
    FittingError("sampling-limit").

Verification against Python Prophet

  • A new changepoint fixture checks a history whose automatic changepoint candidate falls on a
    rounding tie.
  • Refreshed benchmarks time logistic Bayesian fits at 4–5 times as long as Python's native
    CmdStan, not the 3–4 times reported for 0.7.0: that run timed Python's slowest logistic case
    while the machine was sleeping. The
    Bayesian guide now says so. Linear
    and flat fits still take about as long as Python's.

Full Changelog: v0.7.0...v1.0.0

v0.7.0

Choose a tag to compare

@jer-k jer-k released this 05 Nov 16:29
6fca765

Full Bayesian fitting, like Python's mcmc_samples, for the main model and for regressors
forecast by their own models. Code that only fits MAP models works as before at runtime, but code
that reads optimizer fields from a FittedProphet must now narrow it first.

Added

  • Full Bayesian fitting. fit(rows, { mcmc: { samples, seed } }) samples the posterior with
    a port of Stan 2.37.0's adaptive NUTS sampler, like Python's mcmc_samples, for flat, linear
    and logistic growth. It works with regressors forecast by their own models, and in
    crossValidate, searchModels, evaluateHoldout, forecast and anomaly detection. chains
    and warmup default to Python's 4 and samples / 2.

    • Forecasts use the posterior means. predictWithIntervals runs ceil(samples / draws)
      futures per draw and adds each component's range over the draws, and
      getRegressorCoefficients adds each coefficient's 80% range.
    • Saved models keep every draw, and fitSummary.diagnostics reports divergences, tree-depth
      hits, R-hat, effective sample sizes and step sizes.
    • New models are "flat-mcmc", "linear-piecewise-mcmc" and "logistic-piecewise-mcmc". A new
      FittingError reason, "sampling-limit", bounds the chains, draws and kept values.

    See Full Bayesian fitting.

  • Sampled regressor models. A regressor's predictor options take mcmc, like
    mcmc_samples in Python's regressor_predictor, so the model that forecasts a regressor can
    sample its posterior too, with its own seed, whether or not the main model samples. Its draws
    widen the main model's ranges, and saved models keep them. See
    Forecasting a regressor.

  • A new effect-prophet.wasm.componentRanges span, and mcmc.* attributes on the engine's fit
    and simulation spans. See the tracing guide.

  • Docs for agents and tools. The docs site publishes a Markdown copy of every page,
    llms.txt, llms-full.txt and a sitemap.

  • Did the optimizer finish? Checking the fit
    shows how to tell when L-BFGS stopped well short of the optimum, which both libraries can do on
    some histories. The warm-start caveat in
    Saving and loading models now
    explains why logistic refits can break after many new rows.

Changed

  • FittedProphet now includes posterior models, whose fitSummary describes the sampler rather
    than an optimizer, and so does RegressorModel["model"], for sampled regressor models. Code
    that reads optimizer fields such as fitSummary.objective from any fitted model must first
    check isMcmcModel(model), or use the new FittedMapProphet type. isLogisticModel and
    FittedLogisticProphet cover logistic models fitted either way.
  • simulation on uncertainty, cross-validation and anomaly results is now SimulationIdentity,
    which adds posteriorSimulationIdentity for posterior models. Holdout reports accept it as
    simulation.algorithm, and their model can be a posterior summary.

Verification against Python Prophet

  • Full Bayesian fitting benchmarks on flat, linear and logistic growth, including a regressor
    forecast by its own model, optimized or sampled, against Python Prophet's mcmc_samples. The
    two samplers' chains can't match draw for draw, so forecasts must agree within 0.15 of the
    narrowest 80% range and every range bound within the variation expected from the posterior's
    draws. Both libraries must keep the same number of draws, and divergences and R-hat are
    reported. Linear and flat fits take about as long as Python's, and ranges from a posterior are
    9–83 times faster, but logistic fits take 3–4 times as long as Python's native CmdStan.

Full Changelog: v0.6.0...v0.7.0

v0.6.0

Choose a tag to compare

@jer-k jer-k released this 02 Nov 15:29
df876b3

Forecasts in the browser, regressors forecast by their own models, and mean absolute scaled
error. Existing code works as before; only a damaged calendar file reports a different error
reason.

Added

  • Browser and bundler support. The same package and import now work in browsers. Vite (build
    and dev server), webpack and Rspack need no configuration; esbuild needs the engine binary
    copied next to the bundle. Browsers download the WebAssembly engine once per page, and each
    country holiday calendar is its own chunk, loaded the first time it's used. Tested in Chromium,
    Firefox and WebKit, which give exactly the same forecasts as Node.js. Node.js still loads the
    engine synchronously, so Effect.runSync keeps working there. See
    Browsers and bundlers.
  • Regressors forecast by their own models. Set predictor: true, or options, on a regressor,
    like Python's regressor_predictor, and fit fits a model to that regressor's history.
    predict uses its forecast in every row after the history, so future rows need no value for
    it. Intervals include each regressor model's own uncertainty, as in Python, and saved models
    keep these models. When one of them fails, FittingError and PredictionError name it in a
    new optional regressor field. See
    Forecasting a regressor.
  • Mean absolute scaled error (MASE). scaledErrorMetric divides each forecast's error by a
    naive rule's average error on the rows its round trained on, repeating either the previous row
    or the value a set time earlier. It's a metric definition, so performanceMetrics,
    comparePerformance and searchModels accept it. Rounds it can't scale fail with the new
    MetricScaleError. Python Prophet has no scaled metrics. See
    Scaled errors.
  • New spans for regressor models and scaledErrorMetric. See the
    tracing guide.

Changed

  • Country holiday calendars are loaded as JSON modules, once per process, instead of being read
    from disk on every fit. Each use still checks the file's format version and contents. The
    byte-count and SHA-256 checks against the bundled catalog are gone, and a calendar file that
    isn't valid JSON now fails with snapshot-unavailable instead of corrupt-snapshot.

Verification against Python Prophet

  • New fixtures check regressor models' forecasts against regressor_predictor, and that
    their draws widen future intervals as much as Python's do.
  • New benchmarks for regressors forecast by their own models, on flat and linear growth,
    checked against Python Prophet for forecasts, uncertainty ranges and cross-validation.
  • Twelve-fold cross-validation and model search benchmarks, one for each growth. Python
    Prophet is timed sequentially and with cross_validation's parallel="threads" and
    parallel="processes", which must give the same forecasts and scores as running sequentially.
    Effect Prophet still runs folds one at a time, and is faster than either parallel mode.
  • MASE benchmarks on flat and logistic growth. Python Prophet has no MASE, so the Python side
    registers it with register_performance_metric. Each fold's scale must match, and overall
    scores may differ only as much as the two libraries' forecasts do.

Full Changelog: v0.5.1...v0.6.0

v0.5.1

Choose a tag to compare

@jer-k jer-k released this 31 Oct 23:39

A maintenance release. The package is built with new tooling, and existing code works as before.

Changed

  • The published type declarations are now built with tsrs
    instead of TypeScript 7.0. They describe the same types; only the order of some union members
    differs.
  • The code is now checked with effect-tsrs, which
    reports Effect-specific mistakes and simpler ways to write the same code. The source, docs
    examples and benchmarks were updated to pass with no errors, warnings or suggestions, and CI
    keeps them there. Behavior is unchanged.
  • The tracing guide example provides its
    layers in one Effect.provide call.
  • The Handling errors example handles both
    errors in one Effect.catchTags call.

Full Changelog: v0.5.0...v0.5.1

v0.5.0

Choose a tag to compare

@jer-k jer-k released this 30 Oct 01:43
b942f35

Helpers for the steps around a forecast: list the dates to forecast, check how well a model fits,
score forecasts by month or with your own metrics, and try every combination of settings. Existing
code works as before.

Added

  • makeFutureTimestamps lists the dates to forecast after a history or a timestamp, like
    Python's make_future_dataframe. The history's own dates come first unless you pass
    includeHistory: false. It takes pandas' h, D, W, W-MON to W-SAT, MS and ME, and
    matches pandas on month ends, leap years and time of day. See
    Future rows.
  • residuals predicts each measurement with a fitted model and returns actual, predicted
    and residual per row, ready to chart. It never refits. See
    Checking the fit.
  • Monthly horizons. performanceMetrics and comparePerformance take
    horizon: "calendar-month" to group forecasts by calendar months from their cutoff, like
    Python's performance_metrics(monthly=True). Scores then carry horizonMonths instead of
    horizonMs. See
    Grouping by calendar month.
  • Custom metrics, like Python's register_performance_metric. Pass your own definition next to
    the built-in names in performanceMetrics or comparePerformance, or as the objective of
    searchModels. See
    Your own metrics.
  • makeParameterGrid expands base options and lists of values into every combination, as
    candidates for searchModels, and checks each one before the search starts. See
    Trying every combination.
  • seasonalityPriorScale and holidaysPriorScale, like Python's seasonality_prior_scale and
    holidays_prior_scale. Both default to 10 and set the prior for every seasonality, or every
    event, country holiday and regressor, that doesn't set its own priorScale. As in Python,
    regressors follow holidaysPriorScale. See
    Choosing settings.
  • maximumSearchCandidates (32) is exported.

Changed

  • rows, horizons and rolling metric reports include a horizon field, "duration" or
    "calendar-month", saying which unit their horizons use.
  • Error fields accept new values: InputValidationError.input can be "parameter-grid", and
    EvaluationMetricError.metric can be a custom metric's name, with a new "zero-denominator"
    reason and score, quantile and finalize stages. Update exhaustive checks on these fields.
  • parseEventCalendar, parseRegressorDefinitions and parseCountryHolidays take an optional
    default prior scale for entries without their own. Called alone, they still default to 10.

Fixed

  • The fit span for a flat trend now counts one parameter per changepoint in parameter.count,
    matching what the engine solves for. changepoint.count stays 0, because a flat trend never
    bends.

Verification against Python Prophet

  • New fixtures check makeFutureTimestamps against make_future_dataframe, monthly and custom
    metrics against performance_metrics, and the global prior scales against Python's constructor
    options.
  • New benchmarks score cross-validation by calendar month and with custom metrics against the
    same work in Python, on identical forecast rows, and rank a model search by a custom metric.
  • New benchmarks fit country holidays, events, a seasonality and a regressor with small global
    prior scales, with and without per-component overrides.

Full Changelog: v0.4.0...v0.5.0

v0.4.0

Choose a tag to compare

@jer-k jer-k released this 25 Oct 23:33
c6e109e

Shortcuts for everyday jobs: forecast in one call, get ranges with every forecast, flag unusual
values, and start a refit from an earlier model. Existing code works as before.

Added

  • forecast fits a history and predicts your future rows in one call. The result is exactly
    what fit and then predict return. The model isn't returned, so call fit and predict
    yourself when you want to reuse or save it.
  • predictWithIntervals returns each forecast with its value and trend ranges, so you no
    longer call predict and predictUncertainty and match up their rows yourself.
  • detectAnomalies checks new measurements against a model you already fitted and says
    whether each is below, within or above its range. The model isn't refitted, so it suits
    monitoring: train on last quarter, check this week. Ranges default to 99% wide.
  • anomalies fits a history and returns the timestamps whose values fall outside their own
    99% range, like Prophet.anomalies in prophet-ruby. The flagged values also shape the fit, so a
    large outlier can hide smaller ones; see Finding anomalies.
  • Warm starts, like Python's warm_start_params. warmStartParameters(model) reads a fitted
    model's parameters, and passing them as map.warmStart starts the next fit from there. As in
    Python, the changepoint and coefficient values are used only when their counts still match.
    crossValidate and searchModels use the warm start for every fold.
  • A warm start isn't always faster, and a logistic refit after many new rows can settle on a much
    worse fit, in Python too. Updating a model with new data
    shows how to check for that.
  • Tracing spans for each new operation, and attributes on the fit span saying whether a fit was
    warm-started.
  • defaultIntervalWidth (0.8) and defaultAnomalyIntervalWidth (0.99) are exported.

Verification against Python Prophet

  • New fixtures check warm starts against Python's warm_start_params, for linear, flat,
    logistic and multiplicative models and for refits whose changepoint or coefficient counts no
    longer match.
  • New benchmarks check anomalies against the same steps written with Python Prophet, on
    linear, flat and logistic histories with known outliers. Both libraries must flag every one.
  • New benchmarks check warm starts against Python's fit(df, init=warm_start_params(m)):
    refit a history from an earlier fit after a day, a week or a month of new rows, for linear,
    flat and logistic growth, and time the refit beside a fresh fit.

Full Changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@jer-k jer-k released this 23 Oct 20:43
e7bca57

A correctness release: broader checks against Python Prophet 1.4.0, and the fixes they turned up.
Evaluation scores now match Python's exactly, which removes a few options and fields, so read
Removed before upgrading.

Added

  • FittingError has a memory-limit reason for models too large for WebAssembly's 4 GiB of
    memory.

Changed

  • Flat growth fits the way Python does. Every flat model uses Prophet's Stan optimizer and
    accepts map.changepoints and map.changepointPriorScale. Models saved by earlier versions
    still load and predict.
  • Large Fourier orders fit quickly, and models with more than 2048 parameters, which used to
    fail, now fit as they do in Python.
  • Histories the model can fit exactly, such as noiseless data, fit with a noise scale near
    zero, as in Python, instead of failing.
  • Standardized regressors use exactly the mean and standard deviation Python computes.
  • performanceMetrics matches Python's performance_metrics exactly, so some scores change,
    most of all rolling scores. rows scores are sorted by horizon, as in Python.
  • mape fails with zero-actual when an actual is within 1e-8 of zero, not only at exactly
    zero.
  • decodeEvaluationReport rejects holdout reports saved by earlier versions, because their scores
    are recomputed when decoded.

Fixed

  • Regressors that are not standardized no longer fail validation when their values are too large
    to average.

Removed

  • The noise-collapse reason of FittingError, which no fit returns any more.
  • The mapeZeroActual option of performanceMetrics, searchModels and evaluateHoldout, with
    the includedCount and excludedCount score fields. To skip zero actuals, leave those rows out
    before scoring.
  • rowCount on rolling metric points, which always equals the report's windowRows. They now
    have their own RollingMetricPoint type.
  • The empty-bucket reason of EvaluationMetricError, which can no longer happen.

Verification against Python Prophet

  • Property-based tests run in every CI build and check that hostile input produces typed
    errors, never crashes.
  • A weekly differential comparison fits hundreds of newly generated inputs with both
    libraries and reports every case where Effect Prophet fits worse, with a seed that replays it.
    Cases where Python's own result is unstable are reported separately. Run it locally with
    npm run differential.
  • New fixtures cover regressor standardization, large Fourier orders and evaluation metrics.

Full Changelog: v0.2.0...v0.3.0

v0.2.0

Choose a tag to compare

@jer-k jer-k released this 15 Oct 20:04
919b069

Added

  • Country holiday calendars, like Python Prophet's add_country_holidays. Add
    countryHolidays: { country: "US" } to fit and the model learns an effect for each of that
    country's public holidays, alongside any events you add yourself. Calendars for 250 countries
    are included and work offline, for the years 1995–2060.
  • Some calendars have known gaps, such as India's Hindu holidays after 2035. These are rejected by
    default; pass coverage: "allow-known-gaps" to use the calendar anyway.
  • inspectCountryHolidays lists a country's holiday dates and any known gaps for the years you
    ask about, without fitting a model.
  • A saved model keeps the holiday dates it was trained with, so upgrading Effect Prophet never
    changes the forecasts of a model you already saved.
  • CountryHolidayError reports every calendar problem, such as an unknown country, a year
    outside 1995–2060 or a known gap, with a reason you can check.
  • Tracing spans for loading and resolving country calendars.

Changed

  • Faster predictions and model saving, for every model.
  • The npm package grows from about 350 KB to about 1.28 MB, for the bundled calendars.

Benchmarks

  • New benchmarks for country holiday calendars, checked against Python Prophet, with controls
    that measure what the calendars themselves cost.
  • npm run benchmark:compare now summarizes what changed between two runs and flags possible
    speed regressions.

Full Changelog: v0.1.1...v0.2.0

v0.1.1

Choose a tag to compare

@jer-k jer-k released this 15 Oct 00:52
a3089a0

Documentation only. The published code and WebAssembly binary are unchanged from 0.1.0.

Changed

  • The README now says effect (^4.0.0) is a peer dependency that you install yourself, so your
    app and this library share one copy. It previously called it the only dependency.
  • The README's tracing example notes that it continues the quick start, which defines fit,
    predict, history and nextWeek.
  • Minor README wording fixes.

v0.1.0

Choose a tag to compare

@jer-k jer-k released this 13 Oct 23:52
4ea7c74

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 capacity and optional floor, 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. parseEventCalendar validates calendars up front.
  • Regressors: extra numeric factors with prior scale, additive or multiplicative mode, and
    standardization (auto, always, never). getRegressorCoefficients reports 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 global seasonalityMode and holidaysMode and per-component
    overrides.
  • Target scaling: Prophet's absmax and minmax modes. 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: predictUncertainty simulates future trend changes and observation
    noise per path, as Python's vectorized=False does, 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: planRollingOrigin previews the folds and crossValidate
    runs them, with point or interval forecasts, explicit or generated cutoffs, and a configurable
    horizon, period and initial window.
  • Metrics: performanceMetrics computes 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: crossValidateBaseline and comparePerformance score simple rules (last
    observation, training mean, seasonal naive) on the same folds and compare them with a model.
  • Model search: searchModels fits and cross-validates candidate settings, ranks them by a
    chosen metric, and either records or stops on candidate failures.
  • Holdout evaluation: evaluateHoldout selects settings on a development set and then
    evaluates once on a final holdout. Reports can be saved with encodeEvaluationReport and
    restored with decodeEvaluationReport. Plain arrays are accepted for both partitions.

Saving models

  • encodeFittedModel and decodeFittedModel turn 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_json format is not supported.

Effect integration

  • Everything returns an Effect with typed errors. Fitting runs through a
    prophetFittingBackendLayer that you provide.
  • Typed errors with a reason field: InputValidationError (with issue paths),
    FittingError, PredictionError, ModelSerializationError and 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.predict and others)
    and on engine calls (effect-prophet.wasm.fit and .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.0 is 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
    Prophet object 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 returns NaN forecasts.