Returns you haven’t seen yet: forecasting returns as a chain of forecasts
This post is a marimo notebook with its own layout, so it lives on its own page.
Warehouse receipts depend on the returns customers start this week, which depend on what sold last month and what sells this month. The post treats that as a chain of forecasts and builds it on numpyro_forecast: sales is an ordinary numpyro_forecast model written with Horizon and predict, and each return stage is a time-to-event model that speaks the same protocol. One forecast call then carries sales uncertainty through the fitted return stages, draw by draw, under explicit weather assumptions.
The chain is scored on four held-out weeks against four baselines: a weekday average, a settled and a naive return rate times lagged sales, and a SARIMAX with lagged sales and return initiations. It lands within 2% of the month, and its daily error is 44% lower than the best baseline’s.
What if July’s promotion is canceled? The post keeps the fitted model and weather assumptions fixed, changes the promotion calendar, and forecasts again. It shows the lost sales, the change in warehouse workload over time, and a distribution for how many fewer receipts to expect over the next four weeks.
The figures run in your browser, with no Python server: inspect the model’s stages and source, move the history slider, follow a sale day’s returns through both clocks, choose a baseline to compare, or inspect the promotion scenario and its effect on receipts. All forecasts are computed ahead of time; the controls only change the view.
ttenet is the small demo package that wires the stages together: a reference implementation of the idea, meant to be read, run and adapted rather than a maintained library. The notebook behind the page is examples/retail_returns_blog.py. Running it refits the model and recomputes every figure:
git clone https://github.com/kylejcaron/ttenet && cd ttenet
git checkout 3d0a7b0e3ff3f40cf889bfd028fd5d43146b223d
uv sync --python 3.13 --all-extras # JAX has no Python 3.15 wheels yet
uv run marimo run examples/retail_returns_blog.py