All posts

Noël Vranckx • • 8 min read

What time-series foundation models mean for demand planners

A forecasting model that has never seen your sales history can now beat you on some items. Here’s how to find out which ones, in one afternoon.

Illustration of an old barograph on a shelf whose pen traces a wavy line on its drum, the line continuing past the drum as a terracotta dotted fan of possible paths, beside bundles of rolled charts

*A new kind of forecasting model has never seen your data, and on some items it will still beat your forecast. The real question is which items, and how you find out before you trust it.*

How much of your forecast accuracy comes from your model, and how much from the history you fed it?

Now a harder one. Would your forecast beat a model that has never seen your data at all?

Until recently that was a silly question. A forecasting model learnt from your own history, and without it the model knew nothing.

Time-series foundation models break that assumption. Pretrained on huge collections of time series, they forecast your items without any training on your data. The jargon is “zero-shot”, and every demand planner should test one.

What time-series foundation models are

Think of a language model, but for numbers instead of words. During pretraining, it sees a vast number of series and learns what trends, seasons, spikes and slow decline look like. Show it 36 months of bike sales, and it recognises the shape and continues it.

Three families matter today:

  • Chronos-2 (Amazon). Released on 20 October 2025, open source under the Apache-2.0 licence, with 120 million parameters. It’s the one I use in the example below.
  • TimesFM (Google Research). Version 2.5 has 200 million parameters and reads up to 16,000 past data points. Version 3.0 arrived in August 2026, but its weights are licensed for non-commercial, non-production use only.
  • Moirai 2.0 (Salesforce). Small and fast, but released under a non-commercial licence “for research purposes only”. Salesforce uses a proprietary version for its own business.

What’s new in Chronos-2 is that it no longer looks at one series at a time. It can forecast related series together and use outside factors, such as prices or promotions, including ones you already know for the future. Forecasters call these covariates.

Like the others, it forecasts ranges: a 10%, 50% and 90% level, not just one number. Amazon says it produces over 300 forecasts per second on one cloud GPU, and it also runs on an ordinary CPU.

Amazon reports that Chronos-2 ranks first among pretrained models on the public benchmarks fev-bench and GIFT-Eval. Google says TimesFM 3.0 tops all three major benchmarks. Both claims are self-reported, and benchmarks in this field have a leakage problem.

The most interesting real-world test comes from retail. Researchers from Alibaba’s Taobao and Tmall Group and Cornell University compared all three with Alibaba’s production system. On monthly demand for 70,000 to 100,000 grocery SKUs, zero-shot Chronos-2 came in just behind it.

Fine-tuned on Alibaba’s data, Chronos-2 beat the production system by about 3.5%; fine-tuned TimesFM and Moirai didn’t. I could only read a detailed summary of that paper, so treat the exact figures with care.

What they mean for demand planning

Don’t ask whether the model is better than yours. Ask where knowing nothing about your business helps, and where it hurts. Here’s how I split it:

SituationZero-shot modelYour own history and knowledge
New launches, short historyStrong: it knows what launch curves look likeWeak: there’s little history to learn from
Long tail of slow moversGood enough, with zero effort per itemNobody has time to look at them
Stable seasonal runnersSolid, often close to what you haveYour current model is usually good here too
Promotions and dealer eventsBlind, unless you feed it the calendarStrong: you know what’s planned
Known one-off eventsBlindStrong: a price rise, a lost customer, a strike
Structural breaksContinues the old patternYou know the market has changed

The model wins where history is thin or nobody is paying attention. You win where the future differs from the past for reasons written in someone’s calendar.

Where I’d use it first:

  • A free challenger. Run it next to your statistical engine every month and see which one was closer.
  • New product forecasts. Give it the launch item together with its closest predecessors, so it can borrow from them.
  • The long tail. Put thousands of spare parts on a baseline that nobody has to tune.
  • Ranges for S&OP. Discuss capacity and stock risk with the 10% and 90% levels, not one number.

The only way to know where it helps you is a backtest on your own data. Here’s one, step by step.

Worked example: a backtest at a fictional bicycle maker

Upshift is a fictional bicycle maker with road and gravel bikes, each as a regular and an e-bike version. It has 2 plants, 5 distribution hubs and about 180 SKUs, including spare parts. All numbers below are illustrative.

Step 1: prepare the history

Build one row per SKU per month, with a zero where nothing sold. Use orders rather than shipments, because shipments hide stockouts. Label each SKU: core bike, new launch (under a year of history), long-tail part or promoted item.

Step 2: hold out the last year

Cut the history at 1 September 2025. The model sees everything before that date and forecasts the next 12 months, which have already happened.

Step 3: build a simple baseline

The seasonal naive forecast says this September will look like last September, or repeats the last month for newer items. Any new model must beat it.

Step 4: run Chronos-2 and score both

The score is WAPE, the weighted absolute percentage error. Add up all the gaps between forecast and actual, over or under, and divide by total actual sales. A WAPE of 20% means that for every 100 units sold, the forecast was 20 units off.

Here’s the full backtest with Amazon’s `chronos-forecasting` package, for a CSV with the columns item_id, timestamp, units and segment.

# pip install chronos-forecasting "pandas[pyarrow]"
import pandas as pd
from chronos import Chronos2Pipeline

# One row per SKU per month (timestamp = first day of the month),
# every month present, zero if nothing sold
sales = pd.read_csv("monthly_sales.csv", parse_dates=["timestamp"])

cutoff = "2025-09-01"  # hold out the last 12 months
history = sales[sales["timestamp"] < cutoff][["item_id", "timestamp", "units"]]
actuals = sales[sales["timestamp"] >= cutoff]

# Chronos-2, zero-shot: no training on our data
pipeline = Chronos2Pipeline.from_pretrained("amazon/chronos-2", device_map="cpu")
forecast = pipeline.predict_df(
    history,
    prediction_length=12,
    quantile_levels=[0.1, 0.5, 0.9],
    id_column="item_id",
    timestamp_column="timestamp",
    target="units",
)
forecast = forecast.rename(columns={"0.5": "chronos"})

# Seasonal naive: same month last year, else the last known month
naive = history.assign(timestamp=history["timestamp"] + pd.DateOffset(years=1))
naive = naive.rename(columns={"units": "naive"})
last_month = history.groupby("item_id")["units"].last()

result = actuals.merge(
    forecast[["item_id", "timestamp", "chronos", "0.1", "0.9"]],
    on=["item_id", "timestamp"],
)
result = result.merge(naive, on=["item_id", "timestamp"], how="left")
result["naive"] = result["naive"].fillna(result["item_id"].map(last_month))

def wape(df, column):
    return (df[column] - df["units"]).abs().sum() / df["units"].sum()

for segment, group in result.groupby("segment"):
    print(f"{segment:<14} naive {wape(group, 'naive'):.0%}   "
          f"Chronos-2 {wape(group, 'chronos'):.0%}")

I score the 50% level, the middle of the range, because it suits a measure of absolute errors. Here’s what a result could look like (illustrative):

SegmentSKUsSeasonal naive WAPEChronos-2 WAPE
Core bikes4024%20%
New launches1258%34%
Long-tail parts11071%62%
Promoted items1831%36%

Step 5: read it by segment, not in total

What to notice:

  • New launches gain the most. The naive forecast has little to go on, while the model recognises a launch curve.
  • Core bikes gain a little. Against a decent engine, expect a near tie, which still makes a useful second opinion.
  • Long-tail parts are bad either way. WAPE is harsh on items that sell 0, 0, 3, 0. Here the 90% level and the stocking policy matter more than the middle.
  • Promoted items are where it loses. The naive forecast copies last spring’s dealer promotion spike to the month. The model smooths it into a gentle bump.

Step 6: give it the calendar

This is where Chronos-2 differs from its predecessors. Add a column with planned promotion intensity to the history, and pass the same column for the 12 future months as `future_df`. The model treats it as a known future covariate.

In the Alibaba study, one carefully built promotion-intensity number helped, while a simple holiday label made things worse. Start with the one covariate you know drives demand.

For the planner, the baseline for launches, runners and the long tail now comes almost free. Your hours go to the right-hand column of the table.

What it can’t do, and the traps

  • Benchmarks may flatter it. Public test sets leak into training data. As Marcel Meyer and colleagues put it, “one model’s training set is another model’s test set”.
  • It can’t see your calendar. Promotions, price changes and lost customers are invisible unless you feed them in. Badly built covariates can hurt.
  • A range needs reading. The 90% level is not a safety stock. Check how often actual sales fell outside the 10% to 90% band: about one month in five is right.
  • It’s a baseline, not a planning process. Consensus, S&OP and accountability stay with people. And better accuracy doesn’t automatically mean better inventory, as the Alibaba researchers note.
  • Mind your data and the licence. Open weights on your own machine keep sales data in-house; a hosted service means it leaves. TimesFM 3.0 and Moirai 2.0 weights are not for commercial use.

A test for this month

This month, export three years of monthly orders for your top 200 SKUs and your last 20 launches. Run the backtest above, and add your current forecast as a third column. That column will teach you the most.

For decades, a good forecast needed years of your own history. Now a decent baseline is there on day one. The planner’s edge moves to what no history contains: what’s planned, what’s changing and why.

So tell me: in which segment of your portfolio would you expect a model that has never seen your data to beat you?

Sources

Pass it on

Know a colleague who should read this? Post it where they will see it, or send it to them directly.

More posts