Order-up-to \((R, S)\)¶
The order-up-to policy is the standard rule for periodic replenishment. Every \(R\) periods it looks at the inventory position and orders enough to bring it back up to a target level \(S\).
The rule¶
At every decision period \(t\):
After the order, the inventory position equals \(S_t\) (unless it was already above). The picture shows the typical saw-tooth: the position climbs back to \(S\) at every review, and the shelf refills \(L\) periods later.
Choosing \(S\)¶
A decision at \(t\) must cover demand until the next order arrives, a window of \(H = L + R\) periods (derivation). With a target probability \(\alpha\):
It is often useful to split \(S\) into expected demand and a buffer:
For independent normal periods, \(\mathit{SS} = z_\alpha \sqrt{\sum_h \sigma_h^2}\), and for identical periods with standard deviation \(\sigma\) this is the textbook \(z_\alpha \sigma \sqrt{L + R}\) (Silver, Pyke and Thomas, 2017). Forecast targets covers every way of computing \(S\).
Orders replace demand¶
With backorders and an inventory position at or below \(S\) before each review, the order replaces what was sold since the last review:
Orders therefore pass demand variability straight through to the supplier, one reason the \((R, S)\) policy is easy to plan around.
In Stockcast¶
import numpy as np
import pandas as pd
from stockcast.policies import OrderUpToPolicy
opening_date = pd.Timestamp("2026-01-05")
target = pd.DataFrame({
"unique_id": ["tea_250g"],
"S": [46.0],
"S_end": [opening_date + pd.Timedelta(days=6)],
})
policy = OrderUpToPolicy(
lead_time=2,
review_period=4,
freq="D",
service_level=0.95,
allow_backorders=False,
date_column="S_end",
).fit(
target,
target_column="S",
forecast_origin=opening_date,
)
policy.get_target_metadata()
{'representation': 'direct_protection_period_target', 'target_probability': 0.95, 'protection_horizon': 6, 'target_source': 'external_direct', 'forecast_origin': '2026-01-05T00:00:00', 'forecast_frequency': 'D', 'target_end_date': '2026-01-11T00:00:00'}
Constructor¶
| Argument | Meaning |
|---|---|
lead_time |
\(L\), integer \(\ge 0\) |
review_period |
\(R\), integer \(\ge 1\); or pass schedule= for other calendars |
freq |
\(\Delta\), the length of one period, such as "D"; optional when fit reads it from per-period forecast dates |
service_level |
\(\alpha\), or None for planner targets |
allow_backorders |
True or False |
schedule |
any DecisionSchedule |
sku_column, date_column |
column names of the tables given to fit and predict (defaults "unique_id", "date") |
Fitting¶
fit accepts one of two modes, described in
Forecast targets:
- direct:
target_column; - independent normal:
mean_columnandstd_column, one row per step.
Both date their rows with the policy's date_column (default "date", set
in the constructor next to sku_column): the last period each row covers. The origin follows from it, so forecast_origin is
optional (and checked when you give both). The window protection_horizon
defaults to \(L + R\) and the probability target_probability to the
service_level; pass them only to have them checked.
Special cases¶
| Setting | Behaviour |
|---|---|
review_period=1 |
Order every period: a base-stock policy. \(H = L + 1\). |
lead_time=0 |
Orders arrive immediately, before demand. \(H = R\). |
schedule=ExplicitSchedule(...) |
Irregular reviews; each decision needs a target for its own window (see Decision schedules). |
policy_schedule={...} in run |
Fresh targets at later decisions, e.g. rolling forecasts. |
Notes¶
- \((R, S)\) is simple, robust, and widely used. With lost sales it is a strong heuristic rather than the exact optimum; the optimal lost-sales policy is more complex (Janakiraman and Roundy, 2004).
- Orders happen at every review in which demand occurred. If each order has a fixed cost, compare it with \((R, s, S)\), which skips small orders.
References¶
- Silver, E. A., Pyke, D. F., and Thomas, D. J. (2017). Inventory and Production Management in Supply Chains (4th ed.). CRC Press.
- Janakiraman, G., and Roundy, R. O. (2004). Lost-sales problems with stochastic lead times: convexity results for base-stock policies. Operations Research, 52(5), 795–803. doi:10.1287/opre.1040.0130
See also: Notebook 04: weekly forecast to order · Notebook 04c: cumulative protection target · Notebook 04d: rolling targets