Skip to content

Trends and changepoints ​

The trend is the long-term direction of your data. Real trends rarely stay perfectly straight: a launch, a price change or a new competitor can make growth speed up or slow down. The points where the trend changes direction are called changepoints.

Verified against Python Prophet

Linear trends match Python Prophet 1.4.0. The linear growth benchmarks show every case side by side.

The default ​

With no options, the model places 25 possible changepoints evenly across the first 80% of your history and uses only the ones the data supports. Most changepoints end up with almost no effect.

ts
fit(history);

Making the trend more or less flexible ​

changepointPriorScale controls how easily the trend can bend:

  • Smaller (e.g. 0.01): a smoother trend that ignores short bumps.
  • Larger (e.g. 0.5): a trend that follows changes closely, but may overreact to noise.

The default is 0.05. Choosing settings shows how to compare values on your own data.

Example ​

ts
import { Effect } from "effect";
import { fit, predict, prophetFittingBackendLayer } from "effect-prophet";

const date = (day: number) => new Date(Date.UTC(2025, 0, 1 + day)).toISOString();

// Sales grow slowly, then speed up after a product launch on day 60.
const history = Array.from({ length: 120 }, (_, day) => ({
  timestamp: date(day),
  value: day < 60 ? 50 + day * 0.2 : 62 + (day - 60) * 1.5,
}));

const nextWeek = Array.from({ length: 7 }, (_, offset) => date(120 + offset));

// Let the model look for changes on its own, with more freedom to bend.
const automatic = fit(history, {
  map: {
    changepoints: { mode: "auto", count: 25, range: 0.9 },
    changepointPriorScale: 0.5,
  },
});

// Or tell it exactly when the trend changed.
const explicit = fit(history, {
  map: {
    changepoints: { mode: "explicit", timestamps: [date(60)] },
  },
});

const forecasts = await Effect.runPromise(
  Effect.gen(function* () {
    const automaticForecast = yield* predict(yield* automatic, nextWeek);
    const explicitForecast = yield* predict(yield* explicit, nextWeek);

    return { automaticForecast, explicitForecast };
  }).pipe(Effect.provide(prophetFittingBackendLayer)),
);

console.log(
  "automatic:",
  forecasts.automaticForecast.map((row) => row.value.toFixed(1)).join(", "),
);

console.log("explicit: ", forecasts.explicitForecast.map((row) => row.value.toFixed(1)).join(", "));
txt
automatic: 152.0, 153.5, 155.0, 156.5, 158.0, 159.5, 161.0
explicit:  152.0, 153.5, 155.0, 156.5, 158.0, 159.5, 161.0

Both models pick up the faster growth after day 60.

Automatic changepoints ​

{ mode: "auto" } takes two optional settings:

SettingDefaultMeaning
count25How many candidate changepoints to place
range0.8How far into the history they may go. 0.9 means the first 90%.

Keeping range below 1 stops the trend from overreacting to the last few days of data.

Changepoints you already know about ​

If you know when something changed, list the dates with { mode: "explicit", timestamps: [...] }. Each date must fall within your history.

Other trend shapes ​

Inspired by Prophet from Meta. Not affiliated with Meta.