P / 01 — Forecasting · Open source

demand-sense Forecasting Engine.

SKU-level retail demand forecasting with LightGBM — leakage-safe feature engineering, rolling-origin backtesting and honest baselines, packaged as a tested, runnable Python library. Every number on this page comes from the repo's seeded benchmark.

LightGBM Tweedie Rolling-origin backtest pandas Python
38.4%
WAPE (7-day horizon)
−44.7%
Error vs seasonal-naive
146K
Rows backtested
12
Tests incl. leakage checks
01 / Context

Why another forecasting repo?

Most forecasting demos train once, score once, and report a suspiciously good number. Production forecasting lives or dies on three things this project treats as first-class: leakage-safe features (every lag is shifted by at least the forecast horizon), rolling-origin evaluation (retrain at every cutoff, exactly how forecasts are consumed), and baselines that fight back (seasonal-naive and a 28-day moving average are scored on every fold).

The bundled simulator generates two years of daily SKU × store sales with weekly and annual seasonality, price elasticity, promo uplift, weather sensitivity and negative-binomial noise — with known ground truth, so the pipeline's correctness is assertable in CI rather than eyeballed.

02 / Results in data

The benchmark, visualised.

Charts below render the actual output of demand-sense --skus 40 --stores 5 --folds 4 --horizon 7 — a 4-fold rolling-origin backtest over 146,200 rows (seeded, deterministic).

Forecast vs actual — final holdout week

Total daily units across all 200 SKU × store series, 25–31 Dec 2025 (the last backtest fold). LightGBM tracks the holiday-week swing the naive baseline overshoots.

source: rolling_backtest(keep_predictions=True), fold 4 of 4

Error by model (WAPE, lower is better)

Mean weighted absolute percentage error across all 4 folds.

44.7% relative improvement over seasonal-naive

What the model actually uses

LightGBM gain-based feature importance, share of total.

recent demand level + promo flag dominate — as they should
pip install -e ".[dev]" && pytest
12 passed in 1.69s
demand-sense --skus 40 --stores 5 --folds 4 --horizon 7
LightGBM WAPE 38.4% vs seasonal-naive 69.5% (44.7% relative improvement)
03 / Design

How it works.

  • Tweedie objective (variance power 1.2) — retail demand is right-skewed and intermittent; squared loss fumbles the zero-inflation.
  • Horizon-aware lags: predicting h days ahead shifts every lag and rolling window by at least h, so the model never peeks inside the gap. A dedicated test asserts this.
  • Rolling-origin backtest: cutoffs walk through the panel; the model retrains at each fold and is scored on the following 7 days only.
  • Simulator as test oracle: tests assert that promo uplift is recovered, weekday seasonality exists, and LightGBM beats seasonal-naive — regressions fail CI.
  • Swap in real data by replacing generate_sales() with any panel of date, sku_id, store_id, price, promo, temp_c, units.