Skip to content

Repository files navigation

Middle-Mile Demand Forecasting Simulator

A production-style demand forecasting system for logistics lane volume prediction — built to reflect the architecture of real-world supply chain forecasting pipelines.

The core design choice: demand in a middle-mile network is not a time-series problem — it's a supervised regression problem. Volume is driven by upstream shipment flows, lead time variability, event calendars, and operational decisions that pure time-series models cannot capture. This repo demonstrates why that framing change matters.


What This Repo Does

Layer What's implemented
Data Synthetic daily demand for 5 logistics lanes (27 months), with shipment flows, lead times, event signals, and realistic seasonality
Baselines Moving Average (7-day), Holt-Winters Exponential Smoothing
ML Models XGBoost, LightGBM — multivariate supervised regression
Feature Engineering Lag features, rolling stats, lead time distributions (mean + P95), upstream outflow, event proximity signals
Evaluation MAPE / RMSE / MAE at daily granularity + weekly (cycle-level) aggregation
Multi-lane Runs independently per lane; comparable summary across all lanes

Why Supervised Regression Over Time-Series

Approach What it captures What it misses
ARIMA / Prophet Trend, seasonality, simple holidays Cross-lane signals, lead time impact, event pre-buildup
XGBoost / LightGBM All of the above + operational features Requires feature engineering; less interpretable

The moment you add cross-series signals (upstream outflow, lead time variance), you need a supervised framework. Prophet and ARIMA break when features span multiple series.


Results (Test Period: Oct 2024 – Mar 2025)

Daily MAPE by Lane

Lane Moving Avg Holt-Winters XGBoost LightGBM
BLR-DEL 23.67% 55.93% 14.23% 13.99%
BLR-MUM 28.98% 33.94% 10.62% 10.76%
DEL-HYD 26.72% 39.91% 14.30% 14.68%
DEL-KOL 24.92% 22.85% 12.18% 12.55%
MUM-CHE 30.33% 31.48% 11.43% 11.25%

Weekly (Cycle-Level) MAPE — the metric that drives inventory decisions

Lane Moving Avg Holt-Winters XGBoost LightGBM
BLR-DEL 16.53% 50.56% 9.52% 9.20%
BLR-MUM 23.07% 29.84% 6.68% 7.42%
DEL-HYD 18.37% 34.32% 6.89% 7.36%
DEL-KOL 18.91% 18.46% 6.60% 7.61%
MUM-CHE 25.40% 28.03% 5.05% 5.40%

XGBoost and LightGBM reduce daily MAPE by ~50% over baselines. Weekly MAPE drops further — cycle-level planning benefits most from the ML models.


Feature Engineering

Features are grouped into five families — mirroring a production pipeline:

1. Calendar      : day-of-week (sin/cos encoded), month (sin/cos), week-of-year, is_weekend
2. Lag features  : volume at t-1, t-2, t-3, t-7, t-14, t-21
3. Rolling stats : rolling mean and std at 3/7/14-day windows (shift-1 to avoid leakage)
4. Lead time     : current lead_time_days, 3-day rolling mean, P95 over 14 days
5. Event signals : is_event, days_to_next_event, days_since_last_event,
                   pre_event flag (≤3 days), post_event flag (≤2 days)
6. Upstream flow : upstream_outflow lag-1, 3-day rolling mean

Why P95 lead time?

Mean lead time understates reliability risk. P95 tells the model "this lane is structurally unreliable" — which should inflate safety stock signals. This is a feature that time-series models structurally cannot use.

Why event proximity features?

Demand starts building 2–3 days before a sale event (customer anticipation, pre-positioning) and dips slightly after (post-event hangover). days_to_next_event and days_since_last_event give the model this structure explicitly.


Project Structure

middle-mile-forecasting-simulator/
├── generate_data.py        # Synthetic data generation with event calendar
├── forecast.py             # Feature engineering + models + evaluation pipeline
├── daily_demand.csv        # Input: 4,105 rows × 5 lanes × 27 months
├── forecast_results.csv    # Output: actuals + predictions per model per lane
├── model_comparison.csv    # Output: MAPE/RMSE/MAE summary table
├── requirements.txt        # Dependencies
└── README.md

Quickstart

# Install dependencies
pip install -r requirements.txt

# Generate fresh synthetic data (optional — daily_demand.csv already included)
python generate_data.py

# Run all models across all lanes
python forecast.py

# Run a specific model on a specific lane
python forecast.py --model xgb --lane BLR-DEL
python forecast.py --model lgb --lane MUM-CHE

# Run only baselines
python forecast.py --model ma
python forecast.py --model hw

Design Decisions & Tradeoffs

Log-transform on target Volume is right-skewed; training on raw volume causes the model to over-optimise for high-volume days. Log1p transform stabilises variance across scales and lanes.

Walk-forward split (not random) Random train/test split causes data leakage in time-series — future data leaks into training. Fixed temporal split (80/20 chronological) is the correct evaluation protocol for forecasting.

Lag features shift by 1 to avoid leakage Rolling stats are computed on volume.shift(1) — the model never sees the current day's volume when predicting it.

Why both XGBoost and LightGBM? They often have similar accuracy but different failure modes (XGBoost handles outliers more conservatively; LightGBM captures finer seasonal patterns via leaf-level splits). In production, an ensemble of both reduces variance.


Extending This Simulator

Swap in your own data by matching the daily_demand.csv schema:

Column Type Description
date date Daily date
lane str Origin-Destination identifier
volume int Daily shipment volume
lead_time_days float Transit time for the lane
upstream_outflow int Shipment volume from upstream FC
day_of_week int 0=Mon … 6=Sun
month int 1–12
week_of_year int ISO week number
is_event int 1 if date falls in a sale event window
days_to_next_event int Days until next event (capped at 30)
days_since_last_event int Days since last event ended (capped at 30)

Requirements

pandas>=2.0
numpy>=1.24
scikit-learn>=1.3
xgboost>=2.0
lightgbm>=4.0
statsmodels>=0.14

Related Projects


Built to mirror production forecasting architecture — not a tutorial.

About

Multi-lane demand forecasting simulator — XGBoost/LightGBM vs baselines, with shipment flow, lead time, and event signal features

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages