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"].