Skip to content

Restock

polars_ts.applications.perishables.restock

Forecast-to-order translation for perishables restocking.

The deliverable of the application: "how many units of SKU X to order for the next N days". Implements an order-up-to policy with a service-level safety stock, netted against current inventory, and — the perishables twist — a shelf-life cap so orders never exceed what can sell before spoiling. Over-forecast is waste, under-forecast is stockouts; the policy makes that trade-off explicit.

RestockPolicy dataclass

Ordering policy parameters for perishables replenishment.

Parameters

service_level Target cycle service level (probability of no stockout during the protection period), e.g. 0.95. lead_time_days Days between placing an order and receiving it. review_period_days Days between consecutive ordering opportunities. shelf_life_days Sellable days after receipt; when set, orders are capped so total stock never exceeds forecast demand within shelf life. moq Minimum order quantity — nonzero orders are raised to this. pack_size Case/pack multiple — orders are rounded up to it.

protection_days property

Days of demand an order must cover (lead time + review period).

z_score property

Standard-normal quantile for the target service level.

demand_std(df, target_col='y', id_col='unique_id', window=91, time_col='ds')

Estimate per-SKU daily demand standard deviation.

A fallback uncertainty estimate when backtest forecast-error residuals are not available; computed over each SKU's trailing window of history.

Parameters

df Gap-free canonical sales frame. target_col, id_col, time_col Canonical column names. window Trailing days to use; None uses full history.

Returns

pl.DataFrame Columns [id_col, "sigma"].

recommend_orders(forecast, policy=None, on_hand=None, sigma=None, target_col='y_hat', id_col='unique_id', time_col='ds')

Translate per-day forecasts into order quantities per SKU.

Implements an order-up-to-S policy: the base stock covers forecast demand over the protection period (lead time + review period) plus a safety stock z * sigma * sqrt(protection_days) for the target service level. The order is the gap between S and current inventory, capped at forecast demand within shelf life (minus stock already on hand) so perishables are not ordered into spoilage, then raised to the MOQ and rounded up to the pack size.

Parameters

forecast Per-day forecast frame [id_col, time_col, target_col] starting the day after the order is placed; must cover at least the protection period (and shelf life, when capping is enabled). policy Restock policy; defaults to RestockPolicy(). on_hand Optional [id_col, "on_hand"] current sellable inventory (units on order may be included here); missing SKUs default 0. sigma Optional [id_col, "sigma"] daily forecast-error standard deviation (see :func:demand_std); missing SKUs default 0, i.e. no safety stock. target_col, id_col, time_col Column names in forecast.

Returns

pl.DataFrame One row per SKU with columns [id_col, "forecast_demand", "safety_stock", "order_up_to", "on_hand", "shelf_life_cap", "order_qty"].