Forecast retail demand when stockouts hide lost sales
For demand planning lead · Compare approaches
TL;DR — what you’ll learn
- Never feed raw point-of-sale unit sales directly into a replenishment forecast without first separating true zero-demand days from stockout-censored days (`On_Hand_Sellable == 0`).
- When a fast-moving SKU sells zero units for `4 days` during a `14-day` window because the shelf was empty (`150 units sold across 10 in-stock days`), treating those 4 stockout days as zero demand depresses the daily velocity estimate by `28.6%` (`from 15.00 to 10.71 units/day`).
- Store the raw observed sales (`150 units`) and the explicitly labelled lost-sales estimate (`60 imputed units`, total uncensored demand `210 units`) in separate database columns so planners and finance can audit the exact forecast uplift (`₹17,400.00` protected margin).
- Validate your demand-planning pipeline with three acceptance tests: stockout-day censoring detection, capped imputation under promotion/stockout overlap, and phantom-inventory zero-velocity alerting.
Topics: retail demand forecasting stockouts · lost sales demand forecast · censored retail demand · stock availability history

Illustrative e-commerce returns grading and warehouse inventory reconciliation desk; not a client facility.
All quantities, amounts, product codes and events are illustrative teaching examples.
A beauty and personal-care retailer replenish its flagship Vitamin-C face serum (SKU-SERUM-VITC-30ML, MRP ₹680.00, landed cost ₹390.00, unit gross margin ₹290.00) every two weeks across its top regional distribution hub. Over the first 10 days of a 14-day review cycle, the SKU sells steadily at 15 units per day (150 units total), exhausting the hub's entire sellable stock by Tuesday evening (Day 10). For the remaining 4 days of the cycle (Days 11 to 14), Available-to-Sell (ATS) is 0 units and recorded POS/web sales are 0 units per day while awaiting the next vendor delivery. On Sunday night, the ERP's automated replenishment job divides total 14-day sales (150 units) by 14 calendar days to compute a trailing velocity of 10.71 units/day (150 units forecast for the next 14-day cycle). Because the algorithm treats 4 days of empty shelves as 4 days of zero customer interest, it under-orders by 60 units (150 ordered vs 210 true demand), guaranteeing that the SKU will stock out again on Day 10 of the next cycle and forfeiting ₹17,400.00 (60 x ₹290.00) in gross margin every fortnight.
The operational decision for a demand planning lead across retail chains and e-commerce merchants is how to combine daily inventory availability snapshots—grounded in accurate location-level inventory state tracking and open-to-buy and replenishment planning discipline—with a clearly labelled stockout-imputation rule so lost sales are corrected without inventing unverified demand (Shopify Help Center — Inventory states (Available, On hand, Committed, Incoming, Unavailable), Shopify Retail Blog — Open-to-buy (OTB) planning and inventory budgeting guide). By linking this control to promotion demand forecast pilot controls and retail metric definition contracts, demand planning lead teams prevent downstream inventory, customer-promise, and financial breaks before stock or cash moves.
Why unadjusted stockouts create a downward replenishment spiral
In retail demand planning, point-of-sale (POS) and order-capture tables record fulfilled transactions, not unconstrained customer demand. Whenever sellable inventory drops to zero (or drops below the minimum display fixture quantity in a store), demand is right-censored: customers who wanted to buy the product either abandon the purchase or switch to another item, leaving zero trace in the sales ledger.
When a forecasting model ingests raw historical sales without joining daily closing inventory states, three operational failures compound across cycles:
- The self-reinforcing stockout death spiral: A
4-daystockout in a14-daywindow reduces measured velocity by4 / 14 = 28.57%(from 15.00 to 10.71 units/day). If the planner orders150 unitsfor the next 14-day window and true demand remains15.00 units/day, the SKU stocks out after10 daysagain. If a supplier delay extends the next stockout to6 days, naive velocity drops further to90 / 14 = 6.43 units/day, progressively starving your best-selling SKU of open-to-buy budget. - Opaque manual overrides that corrupt data provenance: To fight the downward bias, merchandisers often overwrite historical sales numbers directly in the planning spreadsheet (
changing Day 11–14 sales from 0 to 20). Months later, finance and inventory planners cannot tell which historical numbers were actual cash-register sales (150 units) and which were planner guesses. - Unrecognised 'phantom stockout' days: In physical stores, an ERP ledger may show
2 unitson hand (On_Hand = 2) when those2 unitsare actually damaged in the backroom or mis-shelved. The shelf is physically empty (0 units sold for 4 consecutive days), yet a naiveOn_Hand == 0filter fails to flag the stockout because the book balance is non-zero.
To correct stockout bias transparently while preserving auditability, enforce four explicit equations in your demand-planning data contract:
Naive Biased Daily Velocity (V_naive) = Total_Observed_Sales / Total_Calendar_Days = 150 / 14 = 10.714 units/dayIn-Stock Uncensored Daily Velocity (V_instock) = Observed_Sales_On_Available_Days / Available_In_Stock_Days = 150 / 10 = 15.00 units/dayExplicitly Labelled Lost-Sales Estimate (Q_lost_est) = Censored_Stockout_Days x V_instock = 4 x 15.00 = 60.00 unitsReconstructed Baseline Cycle Demand (D_adj) = Observed_Sales (150) + Q_lost_est (60) = 210 units (protecting 60 x ₹290.00 = ₹17,400.00 margin)
Crucially, Observed_Sales (150) and Q_lost_est (60) must live in separate columns (actual_qty vs imputed_lost_sales_qty) with an explicit imputation_method_code so any planner can compare the zero-demand assumption against the imputed estimate side by side.
Scroll horizontally to see all columns.
| Demand series & planning metric | Treats stockout days as zero demand (Naive) |
Explicitly labelled stockout imputation (Governed) |
Database field & audit label | Guardrail against over-forecasting |
|---|---|---|---|---|
Observed fulfilled sales (Days 1–10) |
150 units (15.0/day for 10 days) |
150 units (15.0/day for 10 days) |
actual_fulfilled_qty = 150 (Immutable ledger fact) |
Never alter or overwrite raw POS/OMS sales records |
Stockout window (Days 11–14, ATS = 0) |
0 units treated as true zero customer demand |
4 days flagged as Censored_Stockout = TRUE; imputed at 15.0/day = 60 units |
imputed_lost_sales_qty = 60 (Method: Trailing_InStock_Mean) |
Cap imputed rate at trailing 28-day non-promo baseline velocity |
| Calculated daily demand rate | 10.71 units/day (150 / 14 days, -28.6% bias) |
15.00 units/day (150 / 10 in-stock days) |
uncensored_daily_velocity = 15.00 |
Require at least 7 in-stock days in window; else fall back to prior 4-week rate |
| Next 14-day cycle replenishment forecast | 150 units (10.71 x 14) — stocks out again on Day 10! |
210 units (15.00 x 14 = 150 actual + 60 imputed) |
forecast_base_qty = 150, forecast_stockout_uplift = 60 |
Display both numbers in OTB approval screen so buyer sees the +60 unit uplift |
Financial gross-margin impact (₹290.00/unit) |
Loses 60 units x ₹290.00 = ₹17,400.00 margin per cycle |
Protects ₹17,400.00 gross margin (₹40,800.00 revenue) |
estimated_margin_at_risk_inr = ₹17,400.00 |
Track post-replenishment sell-through to verify the extra 60 units actually sell |
By keeping 150 actual units and 60 imputed lost-sales units visible as two distinct components of the 210-unit forecast, the demand planning lead eliminates stockout bias without sacrificing data integrity.
Worked illustrative example: comparing zero-demand treatment vs labelled estimation across a 4-day stockout
Illustrative example (hypothetical scenario): Examine the 14-day replenishment review for SKU-SERUM-VITC-30ML (MRP ₹680.00, Landed Cost ₹390.00, Gross Margin ₹290.00/unit) after the distribution hub runs out of stock for the final 4 days of a 14-day cycle.
Step 1: Establish the baseline operational and commercial parameters
- Observed 14-day sales and inventory log:
- Days 1 to 10 (In-stock period,
ATS > 0): The SKU sells[14, 16, 15, 15, 17, 14, 15, 16, 14, 14]units across the 10 days =150 unitsobserved sales (Observed Revenue = 150 x ₹680.00 = ₹1,02,000.00;Observed Gross Margin = 150 x ₹290.00 = ₹43,500.00). - Days 11 to 14 (Stockout period,
ATS = 0): Closing and intraday sellable stock is0 unitsfor 4 consecutive days. Recorded POS/web sales =[0, 0, 0, 0]=0 units.
- Days 1 to 10 (In-stock period,
- Option A — Treating stockout days as true zero demand (Naive ERP average):
- Daily velocity calculation:
V_naive = 150 units / 14 calendar days = 10.7143 units/day. - Next 14-day replenishment forecast:
10.7143 x 14 days = 150 units(working capital cost = 150 x ₹390.00 = ₹58,500.00). - Operational consequence in next cycle: Because true customer demand is still
15.00 units/day, ordering150 unitsguarantees the hub will run out of stock again at the end of Day 10 (150 / 15.00 = 10.0 days), leaving Days 11 to 14 empty for a second consecutive fortnight.
- Daily velocity calculation:
Step 2: Reconcile states, exceptions, and financial impact
- Option B — Censoring stockout days and applying a clearly labelled estimate (Governed workflow):
- In-stock velocity calculation: Exclude the
4 censored days(ATS == 0) from the denominator:V_instock = 150 units / 10 in-stock days = 15.00 units/day(applying day-of-week seasonal weights if weekend traffic differs, which here averages15.00 units/day). - Labelled lost-sales estimate (
Days 11–14):Q_lost_est = 4 censored days x 15.00 units/day = 60 units(Label: IMPUTED_STOCKOUT_TRAILING_MEAN). - Reconstructed 14-day demand and next-cycle order:
D_adj = 150 actual units + 60 imputed units = 210 units(15.00 units/day x 14 days). - Commercial and working-capital comparison: Ordering
210 unitsinstead of150 unitsrequires an incremental working-capital outlay of60 units x ₹390.00 = ₹23,400.00(total PO cost = ₹81,900.00vs₹58,500.00), which generates60 units x ₹680.00 = ₹40,800.00in incremental revenue and60 units x ₹290.00 = ₹17,400.00in protected gross margin during the 14-day cycle.
- In-stock velocity calculation: Exclude the
Scroll horizontally to see all columns.
| Forecasting parameter | Days 1–10 (In Stock) |
Days 11–14 (ATS = 0) |
Option A: Zero-Demand (Naive) |
Option B: Labelled Estimate (Governed) |
Commercial variance (Option B - Option A) |
|---|---|---|---|---|---|
| 1. Recorded / Imputed unit volume | 150 units (actual) |
0 actual / 60 imputed |
150 units total |
210 units (150 act + 60 est) |
+60 units (+40.0% order uplift) |
| 2. Effective denominator days | 10 in-stock days |
4 stockout days |
14 calendar days |
10 uncensored days |
-4 censored days removed from velocity denominator |
| 3. Computed daily demand rate | 15.00 units/day |
0.00 vs 15.00/day |
10.71 units/day (-28.6% bias) |
15.00 units/day (unbiased) |
+4.29 units/day velocity correction |
4. Next 14-day replenishment PO cost (₹390/u) |
₹58,500.00 (150u) |
₹23,400.00 (60u) |
₹58,500.00 (150 units) |
₹81,900.00 (210 units) |
+₹23,400.00 incremental inventory investment |
5. Expected 14-day gross margin (₹290/u) |
₹43,500.00 (150u) |
₹17,400.00 (60u) |
₹43,500.00 (stocks out Day 10) |
₹60,900.00 (full 14-day cover) |
+₹17,400.00 gross margin (+₹40,800.00 revenue) captured |
Verified scenario calculation summary
Observed_10_Day_Sales = 10 days * 15.00 units/day = 150 units (₹1,02,000.00 revenue; ₹43,500.00 gross margin)Naive_14_Day_Daily_Velocity (V_naive) = 150 units / 14 calendar days = 10.7143 units/day (-28.57% downward bias)Uncensored_InStock_Velocity (V_instock) = 150 units / 10 in-stock days = 15.00 units/dayImputed_4_Day_Lost_Sales (Q_lost_est) = 4 stockout days * 15.00 units/day = 60 unitsReconstructed_14_Day_Forecast (D_adj) = 150 observed units + 60 imputed units = 210 units (15.00 * 14)Protected_Cycle_Gross_Margin = 60 incremental units * ₹290.00 margin/unit = ₹17,400.00 (on ₹23,400.00 incremental PO cost and ₹40,800.00 incremental revenue)
Showing the open-to-buy approver that the 210-unit recommendation consists of 150 verified POS sales plus 60 explicitly labelled stockout-imputed units (4 days x 15/day) gives finance complete confidence to approve the extra ₹23,400.00 purchase order.
Stockout-adjusted demand forecasting workflow: roles, exception handling, and system choice
To eliminate stockout bias from your replenishment forecasts while keeping every imputed unit auditable, implement a four-step planning cadence:
- Nightly end-of-day and intraday availability snapshot logging (Owner: Data Engineering / Inventory Systems). Capture a daily
SKU-Location Availability Snapshotrecording openingATS, closingATS, and hours in stock. Markis_stockout_censored = TRUEwheneverATS == 0(or< minimum display threshold) for more than 6 selling hours. - Automated dual-series demand calculation (Owner: Demand Planning Lead). Calculate both
V_naive(10.71/day) andV_instock(15.00/day) for every replenishment SKU. Store the imputed lost sales (60 units) in a dedicatedimputed_lost_sales_qtyfield tagged with the imputation rule (Trailing_InStock_Mean_DayOfWeek). - Cap and exception review for long or promotional stockouts (Owner: Category Merchandise Planner). If a SKU has been out of stock for more than
50%of the review window (>7 of 14 days) or stocked out during a one-off flash sale, route the imputation to the planner's exception queue rather than extrapolating a short promotional spike across 14 days. - Post-replenishment forecast accuracy tracking (Owner: Commercial Finance + Demand Planning). In the cycle following an imputed uplift (
when 210 units are stocked), measure actual realized sales against the210-unitforecast to verify that the imputed demand (60 units) converted into real cash sales rather than excess aged stock.
Choosing the right tool: You do not need machine-learning black boxes to fix stockout bias. A deterministic SQL view or planning-sheet formula that joins daily closing ATS to daily sales, excludes ATS == 0 days from the velocity denominator, and displays Actual Sales (150) alongside Imputed Lost Sales (60) solves 90% of retail stockout under-forecasting.
Operational governance and audit controls for sustained compliance
To prevent this workflow from eroding after the initial implementation sprint, embed four recurring governance checkpoints into your weekly retail operations cadence:
- Version-locked rule and threshold tables: Store every tolerance band, status-transition rule, and exception-routing map in a versioned configuration table rather than ad-hoc personal spreadsheets. Any threshold change requires sign-off from demand planning lead and commercial finance, recording the effective timestamp and the cohort of SKUs or locations affected.
- Automated daily orphan and stale-state sweep: Run a scheduled morning query that flags records stuck in an intermediate state (
Pending Verification,In Transit,Awaiting Confirmation, orHeld for Review) beyond their agreed service-level cutoff. Route aged exceptions directly to the named role owner before customer promises or period-close cutoffs are breached. - Separation of operational execution from financial write-off authority: Staff who execute physical picks, catalogue edits, or customer service actions should never have unilateral system permission to clear reconciliation variances or post financial write-offs. Require dual sign-off once cumulative weekly adjustments on a SKU, store, or vendor exceed your materiality floor.
- Monthly root-cause retrospective tied to source-system hygiene: Aggregate exception logs by upstream root cause—such as missing supplier identifiers, delayed webhook deliveries, or uncalibrated store stock counts—and require the responsible upstream team to remediate the top three recurring defects before the next monthly cycle.
Observable acceptance tests for your retail systems
Before relying on this workflow in production, execute three deterministic acceptance tests (ACT-R029-01 to ACT-R029-03) in your staging environment or controlled worksheet:
Scroll horizontally to see all columns.
| Test ID | Scenario setup | Action executed in system | Expected pass criteria | Failure indicator |
|---|---|---|---|---|
ACT-R029-01 |
Load a 14-day sales and inventory test dataset for SKU-SERUM-VITC-30ML with 15 units/day sold on Days 1–10 (ATS > 0) and 0 units sold on Days 11–14 (ATS = 0). |
Run the replenishment demand-forecast calculation job. | System flags Days 11–14 as Censored_Stockout, computes V_instock = 15.00 units/day, stores actual_qty = 150 and imputed_lost_sales_qty = 60 in separate columns, and recommends a 210-unit base forecast. |
System divides 150 by 14 (10.71/day) or overwrites the raw actual_qty column from 150 to 210. |
ACT-R029-02 |
Simulate a 2-day promotional flash sale (45 units/day on Days 1–2) followed by an immediate 12-day stockout (Days 3–14, ATS = 0) where regular baseline velocity is 15 units/day. |
Execute the stockout imputation engine. | Guardrail detects <7 in-stock days and promotional flag on Days 1–2, caps the imputed rate for Days 3–14 at the non-promo baseline (15.00/day), and routes the SKU for planner review. |
Engine blindly extrapolates the 45/day promo spike across all 12 stockout days (+540 units), creating severe overstock. |
ACT-R029-03 |
Set a store's book On_Hand = 2 units for a fast-moving SKU (historical velocity 15/day) while recording 0 units sold for 4 consecutive days (phantom inventory). |
Run the daily zero-velocity anomaly detector. | System flags a Suspected_Phantom_Stockout exception (`Pois(0 sales |
λ=15/day) < 0.001`), holds automated downward forecast decay, and triggers a store cycle count. |
Putting stockout-aware demand forecasting into practice
To stop empty shelves from tricking your replenishment system into ordering less of your bestsellers, implement these four steps:
- Start archiving daily closing Available-to-Sell (
ATS) by SKU and location: Even if your ERP only stores current stock by default, schedule a nightly midnight table snapshot so your forecast knows exactly which historical days had zero stock. - Split your forecast review screen into
Observed SalesandImputed Stockout Demand: Never hide lost-sales adjustments inside a black-box number; show buyers150 actual + 60 stockout estimate = 210 total. - Add a minimum display threshold (
e.g., 2 units) to your store stockout flag: In physical retail, the last 1 or 2 units are often damaged or misplaced; censor store days when on-hand stock falls below a sellable fixture floor. - Audit post-imputation sell-through after every stockout recovery: Verify that SKUs given a stockout forecast uplift actually sell at the imputed rate once stock is restored.
Discuss this workflow
If recurring stockouts on your top SKUs are depressing your replenishment forecasts and open-to-buy budgets, NextEdge Labs can help you implement an auditable stockout-imputation pipeline.
References
Sources checked 15 October 2026. Vendor documentation supports platform facts; the worked examples and diagrams are original.
- Shopify Help Center — Inventory states (Available, On hand, Committed, Incoming, Unavailable)Explains how retail inventory is partitioned into available, committed, incoming, and unavailable states across locations.
- Shopify Retail Blog — Open-to-buy (OTB) planning and inventory budgeting guideExplains how merchandise planners align open-to-buy budgets with demand forecasts, safety buffers, and replenishment commitments.


