An open, configurable benchmark for comparing retail-demand forecasting methods across demand regimes. The same holdout and scoring pipeline supports seasonal-naive, Croston/SBA/TSB, a compact PatchTST-inspired model, and zero-shot Chronos-Bolt.
The default run uses a seeded synthetic panel so anyone can exercise the pipeline without accepting a dataset license or downloading model weights. Real M5 data is supported as an opt-in data source.
Evidence status: this repository does not commit a canonical leaderboard. Benchmark numbers depend on the dataset, effective configuration, dependency versions, and model availability. Run the commands below to create
metrics.csv, summaries, andrun_metadata.json; publish results only together with those artifacts. See Reproducibility.
Retail catalogues mix dense, seasonal products with intermittent and zero-heavy demand. A single catalogue-wide score can hide materially different behavior. This project makes that segmentation explicit by reporting metrics by:
- demand-volume bucket;
- Syntetos-Boylan class derived from ADI and CV-squared; and
- individual series and model.
The repository is useful as a research scaffold and teaching implementation. It is not a production demand-planning system and does not establish that one model family wins without a documented run.
The fastest reproducible path runs the classical models and requires no PyTorch, Hugging Face access, or external data:
git clone https://github.com/Madhvansh/Retail-Sales-Forecasting-Engine.git
cd Retail-Sales-Forecasting-Engine
python -m venv .venv
# Linux/macOS: source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
python -m scripts.run_benchmark \
--classical-only \
--source synthetic \
--max-series 50 \
--horizon 28
python -m scripts.generate_report --results results/metrics.csvGenerated files are described in results/README.md. They are ignored by Git by default so a result cannot be mistaken for a maintained reference benchmark.
Install the supervised model path:
python -m pip install -e ".[deep,dev]"
python -m scripts.run_benchmark --no-chronos --max-series 50 --epochs 3Install both the supervised and foundation-model paths:
python -m pip install -e ".[deep,foundation,dev]"
python -m scripts.run_benchmark --max-series 50 --epochs 3Chronos weights are fetched from Hugging Face when first used. If the package or weights are unavailable, the wrapper explicitly labels its seasonal-naive fallback as chronos_bolt[fallback=seasonal_naive]; fallback rows are not Chronos results.
The in-repository transformer is PatchTST-inspired. It uses patching and a Transformer encoder, but is not an exact reproduction of the paper's official implementation or training recipe.
Place the Kaggle M5 CSV files in data/raw/, then run:
python -m scripts.run_benchmark --source m5 --classical-onlyOr configure Kaggle credentials and use:
python -m scripts.download_dataM5 data is not redistributed here. The current harness evaluates bottom-level series with a single holdout and reports an unweighted mean of per-series scaled errors. It does not implement the official hierarchical, sales-weighted M5 WRMSSE leaderboard calculation. See Metrics.
Each benchmark writes:
| Artifact | Purpose |
|---|---|
metrics.csv |
one row per series and effective model |
summary_overall.csv |
mean metrics by model |
summary_winners_volume.csv |
lowest-WQL model by volume bucket |
run_metadata.json |
UTC time, command, commit, effective config hash, dataset size, model labels, runtime, and package versions |
Use the exact model labels in the artifacts. In particular, never relabel the explicit Chronos fallback as a foundation-model result.
For each series, the final horizon values are held out. Global models train only on histories with that window removed. The pipeline reports MASE, RMSSE, WQL, and calibration coverage, then stratifies the resulting rows.
The synthetic generator is a controlled smoke-test dataset, not a substitute for real-world validation. It deliberately spans several demand profiles and therefore encodes modeling assumptions that can influence rankings.
More detail:
The repository also contains a FastAPI endpoint, a Streamlit dashboard, report generation, and container definitions:
python -m pip install -e ".[serve]"
uvicorn app.api:app --port 8000
streamlit run app/dashboard.py
docker compose upThe API currently exposes classical inference; it is a demonstration service, not an authenticated or production-hardened deployment.
src/data/ panel containers, M5 loader, synthetic generator, classification
src/models/ common interface, classical models, PatchTST-inspired model, Chronos wrapper
src/evaluation/ metrics, stratification, and plots
src/pipeline/ holdout benchmark orchestration
scripts/ benchmark, data download, and report CLIs
app/ FastAPI and Streamlit examples
tests/ unit and integration tests
docs/ method, model, metric, deployment, and reproducibility notes
Contributions, replications, failure reports, and new baselines are welcome. Please read CONTRIBUTING.md, the Code of Conduct, and Security Policy. Reusable research outputs can cite the repository using CITATION.cff.
MIT (c) 2025 Madhvansh.