Loading forecast, risk scores and inventory position…
Decisioning view — where every SKU sits
Stockout risk (up) vs overstock risk (right). Bubble size = rupees at stake. Hover for detail; the four quadrants map directly to actions.
Reorder nowMarkdown / clearWatch / volatileHealthy
Rupee impact by category
Sales at risk from stockouts (red) and capital locked in overstock (purple), ₹ lakh.
Top priorities right now
Ranked by value at stake.
Total weekly demand — history and seasonality
All SKUs, units per week. Demand peaks in March and troughs in October, ~50% swing. December weeks show forecast vs actual.
Reorder list
SKUs likely to run out before a replenishment lands. Quantity = demand over lead time + 4-week review + safety stock − position.
Markdown / clearance list
SKUs holding well beyond 8 weeks of forecast demand. Locked capital = excess units × unit cost.
All SKUs — full risk table
Click a header to sort. Respects the filters above.
SKU forecast
ActualFORESIGHT forecast80% intervalSeasonal-naive baseline
Select SKU
Filtered by category / search above.
What-if: change the inventory position and see the risk move
Same formula as the batch scoring — transparent and instant. Reset returns to the client's latest snapshot.
Rolling-origin backtest — WAPE by fold
Six forecast origins in 2025, each scored on the next 8 weeks it had never seen. Lower is better.
WAPE by horizon (weeks ahead)
Accuracy degrades gently with distance; the model stays ahead of the baseline at every horizon.
WAPE by category
What drives the forecast
Share of LightGBM gain. Recent level (lags/rolling means) and last year's same week dominate; promotions and calendar refine it.
How to read the accuracy honestly
Data-quality log — every issue found and how the pipeline handled it
Generated automatically by
src/pipeline.py; nothing was fixed by hand.Pipeline summary
Scoring service — inputs & outputs
Returns the 8-week forecast (mean, 80% interval, seasonal-naive) and the risk assessment for one SKU or a batch. Optional overrides re-score with a different inventory position.
GET /api/health
GET /api/score?sku=SKU012
GET /api/score?sku=SKU012&lead_time_days=21&on_hand=30
GET /api/score?sku=SKU012,SKU020,SKU026
GET /api/score?all=true
POST /api/score {"skus":["SKU012","SKU020"],
"overrides":{"lead_time_days":14}}
Errors are explicit JSON with HTTP 400/404/405 — never a crash: unknown SKU, non-numeric override, empty request, bad JSON body.
Live response
Click “Try it live”.