The Inventory Forecasting module estimates future replenishment needs by projecting inventory forward for each product and forecast period based on a seasonally adjusted exponentially weighted moving-average demand forecast model.
This article explains the algorithm using formulas only.
Forecast period setup
Let:
• P = selected number of forecast periods
• L = selected forecast period length
• H = selected history range in months
• D = selected demand decay factor (monthly)
• ADM = average days per month (30.4375)
For each future period Pₙ, the algorithm defines:
• PeriodStartₙ
• PeriodEndₙ (exclusive)
• PeriodDaysₙ = Days(PeriodStartₙ, PeriodEndₙ)
• ForecastPeriodMonthsₙ = PeriodDaysₙ / ADM (display only)
Historical daily demand
The history window covers:
• HistoryStartDate = EndDateExclusive − H months
• HistoryDayCount = Days(HistoryStartDate, EndDateExclusive)
For each product and warehouse, historical demand is grouped by calendar day:
• DailyQtyd = total historical demand on day d
The monthly decay factor D is converted to a daily equivalent:
• DailyDecayFactor = D^(1 / ADM)
Each historical day is weighted by recency:
• Weightd = DailyDecayFactor^(DaysAgod − 1)
where DaysAgod = Days(d, EndDateExclusive).
Weighted daily quantity:
• WeightedDailyQty = Σ(DailyQtyd × Weightd)
Weight total across the full history window:
• WeightTotal = (1 − DailyDecayFactor^HistoryDayCount) / (1 − DailyDecayFactor)
• (= HistoryDayCount when DailyDecayFactor = 1)
Weighted daily demand rate:
• WeightedDailyDemand = WeightedDailyQty / WeightTotal (units / day)
Overall average monthly demand (used only as the seasonality baseline):
• OverallAverageMonthlyDemand = (Σ DailyQtyd / HistoryDayCount) × ADM
Seasonality
For each future period, the algorithm slices the period into calendar-month segments and computes a demand-weighted seasonal average.
For each calendar month M overlapped by period Pₙ:
• SeasonalAverageForMonthM = average of HistoricalSalesByCalendarMonth for month M, starting from the item's first sale date
• DaysInSlice = days that period Pₙ falls within month M
Period-level seasonal average monthly demand:
• SeasonalAverageMonthlyDemandₙ = Σ(SeasonalAverageForMonthM × DaysInSlice) / Σ(DaysInSlice)
Seasonality factor:
• SeasonalityFactorₙ = SeasonalAverageMonthlyDemandₙ / OverallAverageMonthlyDemand
• (= 1 when OverallAverageMonthlyDemand ≤ 0)
Forecast demand
Base forecast before seasonality (daily rate × period days):
• ForecastDemandBeforeSeasonalityₙ = WeightedDailyDemand × PeriodDaysₙ
Forecast after seasonality before rounding:
• ForecastDemandAfterSeasonalityBeforeRoundingₙ = WeightedDailyDemand × SeasonalityFactorₙ × PeriodDaysₙ
Final forecast demand:
• ForecastDemandₙ = ROUND(ForecastDemandAfterSeasonalityBeforeRoundingₙ, 0)
Known future demand and supply
For each period:
• NonShippedSOQtyₙ = approved sales order demand expected in period n
• NonAllocatedWOQtyₙ = production-related demand expected in period n
• NonReceivedPOQtyₙ = approved purchase order supply expected in period n
• NonReceivedWOQtyₙ = approved production supply expected in period n
The expected date is set in the respective Purchase/Sales Orders in the Latest Expected Date field. For the Production Orders, this is stored under the Due Date field.
Demand to cover
For each period:
• DemandToCoverₙ = ForecastDemandₙ + NonShippedSOQtyₙ + NonAllocatedWOQtyₙ
Product-level aggregation
For each product and period, the algorithm aggregates across all selected inventory locations:
• CurrentStockLevelₙ = Σ(current stock across selected locations)
• StockAlertQtyₙ = Σ(stock alert level across selected locations)
• ForecastDemandₙ = Σ(forecast demand per location)
• DemandToCoverₙ = Σ(demand to cover per location)
• NonReceivedPOQtyₙ = Σ(incoming PO quantity)
• NonReceivedWOQtyₙ = Σ(incoming WO quantity)
Rolling inventory projection
First period
• StartingQty₁ = CurrentStockLevel₁
Projected quantity before planned purchase:
• ProjectedBeforePurchase₁ = StartingQty₁ + NonReceivedPOQty₁ + NonReceivedWOQty₁ − DemandToCover₁
Planned purchase quantity:
• PlannedPurchaseQty₁ = MAX(0, StockAlertQty₁ − ProjectedBeforePurchase₁)
Projected quantity after planned purchase:
• ProjectedAfterPurchase₁ = ProjectedBeforePurchase₁ + PlannedPurchaseQty₁
Subsequent periods
For each period n > 1:
• StartingQtyₙ = ProjectedAfterPurchaseₙ₋₁
Projected quantity before planned purchase:
• ProjectedBeforePurchaseₙ = StartingQtyₙ + NonReceivedPOQtyₙ + NonReceivedWOQtyₙ − DemandToCoverₙ
Planned purchase quantity:
• PlannedPurchaseQtyₙ = MAX(0, StockAlertQtyₙ − ProjectedBeforePurchaseₙ)
Projected quantity after planned purchase:
• ProjectedAfterPurchaseₙ = ProjectedBeforePurchaseₙ + PlannedPurchaseQtyₙ
Final displayed metrics per period
For each product and period, the module displays:
• Forecast Demand = ForecastDemandₙ
• Demand to Cover = DemandToCoverₙ
• Starting Quantity = StartingQtyₙ
• Projected Quantity = ProjectedBeforePurchaseₙ
• Total Stock Alert Level = StockAlertQtyₙ
• Planned Purchase Quantity Needed = PlannedPurchaseQtyₙ
Summary formula chain
For each period n:
• ForecastDemandₙ = ROUND(WeightedDailyDemand × SeasonalityFactorₙ × PeriodDaysₙ, 0)
• DemandToCoverₙ = ForecastDemandₙ + NonShippedSOQtyₙ + NonAllocatedWOQtyₙ
• ProjectedBeforePurchaseₙ = StartingQtyₙ + NonReceivedPOQtyₙ + NonReceivedWOQtyₙ − DemandToCoverₙ
• PlannedPurchaseQtyₙ = MAX(0, StockAlertQtyₙ − ProjectedBeforePurchaseₙ)
• ProjectedAfterPurchaseₙ = ProjectedBeforePurchaseₙ + PlannedPurchaseQtyₙ
And for n > 1:
• StartingQtyₙ = ProjectedAfterPurchaseₙ₋₁