Demand forecasting & reorder simulation for an online retailer
SKU-level demand forecasts feeding a reorder/safety-stock simulator — the £ cost of forecast error made visible.
The problem
[PLACEHOLDER: business framing — an online retailer ordering stock without a forecast: stockouts on winners, cash frozen in losers. 2 short paragraphs.]
The data
Two years of a real UK online retailer: 1,067,371 raw transaction rows → 1,003,246 after cleaning (cancellations −19,494, fees/adjustments −4,699), 4,897 SKUs over 106 weeks, £19.6M revenue. The seasonal spike is Christmas — most of this catalogue is giftware.
[PLACEHOLDER: one paragraph on why this dataset is a good mirror — messy, seasonal, long-tailed, exactly what an ERP export looks like.]
Approach
Method, in brief — the analysis is fully scripted and reproducible with one command:
- Weekly grain, SKU level; every series densified so zero-demand weeks count as demand signal, not gaps.
- ABC segmentation by revenue share crossed with demand pattern (smooth vs intermittent).
- Modeling universe: the 2,487 SKUs still commercially alive (≥60 weeks of history, sold in the last 12) — 78% of total revenue.
- Four models — Naive, 4-week moving average, AutoETS, Croston — backtested with a rolling-origin walk-forward: 6 origins × 4-week horizon, expanding window. No random splits on time series.
- Error metric: WMAPE (weekly SKU series are zero-heavy; plain MAPE would be meaningless).
- The reorder replay sizes safety stock on a separate calibration window — the 24 weeks before the evaluation — so no error from a scored week ever informs the policy.
[PLACEHOLDER: short narrative on the modeling choices and what a client version would add (regressors: promotions, price changes, web traffic).]
Results
On the segment that matters most (A-smooth — 940 SKUs driving the bulk of revenue), the best models cluster at WMAPE 0.65 vs 0.74 for naive: a ~12% error reduction. The honest fine print: the 4-week moving average ties AutoETS on WMAPE — but AutoETS wins on bias (−6% vs −9%), and bias is what inflates or starves stock. Croston, the textbook model for intermittent demand, loses on exactly that segment (0.94, bias −41%).
The retailer’s top-revenue product — a three-tier cake stand, £331k over the two years — shown over its final year: actual weekly units vs the AutoETS backtest forecast (dashed) across the six evaluation origins. A live view of what a 4-week-ahead forecast gets right and what it smooths over.
From forecast to reorder decisions
The 24 evaluation weeks replayed with a weekly order-up-to policy on the 763 A-smooth SKUs; each point is a safety-stock factor z. Safety stock is sized on forecast errors from the 24 weeks before the replay window, never on the weeks being scored. Forecast alone (z=0) fills 64.7% of demand and loses £1.12M of sales; z=1.5 lifts service to 85.7% holding ~£178k of average stock; z=2.5 reaches 89.9% at £283k. Note the flattening: buffers sized on January–June errors come up short in a replay window (late June to early December) that runs into the Christmas ramp. The curve’s shape — not any single point — is the deliverable: it lets an owner pick the service level they can finance, and shows where extra stock stops buying service.
Try it: pick your own service level
Move the safety factor and the replay re-runs in your browser — the same policy, data and code path that produced the chart above, reproducing its numbers exactly. Then pick a product to see what that choice means week by week: when stock ran out, and how much demand walked away.
Loading the simulator…
[PLACEHOLDER: one paragraph translating the curve into a decision conversation with a merchant.]
Limitations & what didn’t work
Real caveats from this build — the parts a sales pitch would hide:
- Survivorship by design: the universe keeps only SKUs still selling; a production system must also decide when a product is dead (that’s a policy, not a forecast).
- No seasonal model was tested in this build. With two years of data each SKU has at most one prior Christmas to learn from; seasonality is the first thing a client version with longer history should add.
- Croston lost on intermittent demand — the method exists for exactly that pattern, and a 4-week moving average beat it throughout. Textbook defaults are hypotheses, not answers.
- An earlier version of this simulation leaked. Safety stock was sized on forecast errors from the same weeks the policy was then scored on, which flattered every point of the curve — at z=2.5 it showed 96.8% service where the leak-free replay gets 89.9%. Fixed by sizing on an earlier calibration window; the numbers above are the corrected ones.
- Sizing buffers on a calm period under-protects the peak. The calibration weeks carry smaller errors than the replay weeks that run into Christmas, so service flattens below 90% even at z=2.5. A production policy would size safety stock by season, or on a window that includes the previous peak.
- Sales ≠ demand: the data records what sold, not what was demanded during stockouts (censored demand). Fill rates in the simulation are therefore optimistic at the margin.
- Holding cost proxy: on-hand stock is valued at selling price (the dataset has no purchase costs); a client version would use real unit economics and add lead times, MOQs and pack sizes.
[PLACEHOLDER: closing sentence for this section — why declared limits are part of the deliverable.]
What this would mean for your business
[PLACEHOLDER: client-facing closing — fewer stockouts on winners, less cash frozen in losers, a tradeoff curve you can actually steer; CTA to services/contact.]