🎓 レベル:標準 | 重要度:A(必須)
📎 前提:安全在庫と発注点(発注点 ROP・安全在庫 )・経済的発注量EOQ(発注量 Q) | 応用:第6章 サプライチェーン(在庫集約・共同発注)
要点(BLUF)
- 「いくつ発注するか」(経済的発注量EOQ)と「ばらつきにいくら備えるか」(安全在庫と発注点)が決まったら、最後はいつ・どうやって発注をかけるか。代表的な2方式があります。
- 定量発注方式(連続監視・):在庫を常時監視し、在庫ポジションが発注点 に下がった瞬間に定量 (≒EOQ)を発注。発注のタイミングは不定期、量は一定。
- 定期発注方式(定期監視・):一定間隔 ごとに在庫を見て、目標在庫 まで足りない分を発注。発注のタイミングは一定、量は毎回変わる。
- 決定的な違いは保護期間です。連続監視は危険を察知した瞬間に発注できるのでリードタイム だけ守ればよい。定期は次の発注機会まで手出しできないので、 を守る必要がある。だから定期のほうが安全在庫が 倍多く要ります。
1. 2つの方式:監視のしかたが違う
両方式の違いは「何を固定し、何を動かすか」に尽きます。
| 定量発注方式 | 定期発注方式 | |
|---|---|---|
| 監視 | 連続(常時) | 定期( ごと) |
| 発注の引き金 | 在庫ポジション | 時間( 経過) |
| 発注量 | 一定 (≒EOQ) | 可変( まで補充) |
| タイミング | 不定期 | 一定間隔 |
| 保護期間 | ||
| 向く場面 | 重要・高額品(個別管理) | 多品目の共同発注・棚卸が定期 |
flowchart TB
C0["定量発注方式 (Q,r):連続監視"] --> C1["在庫を常時監視"]
C1 --> C2{"在庫ポジションが r 以下か"}
C2 -->|"はい"| C3["定量 Q を発注(EOQ相当)"]
C2 -->|"いいえ"| C1
C3 --> C4["保護期間=リードタイム L"]
P0["定期発注方式 (P,S):定期監視"] --> P1["T 日ごとに在庫を確認"]
P1 --> P2["目標在庫 S まで発注(量は毎回変わる)"]
P2 --> P3["保護期間=L+T(次の発注機会まで守る)"]
P3 --> P1
2. なぜ定期は「L+T」を守るのか
ここが本稿の核心です。安全在庫は「補充が届くまで在庫が尽きないように」積むもの(安全在庫と発注点)。守るべき期間=保護期間が方式で変わります。
- 連続監視 :在庫ポジションが に達したまさにその瞬間に発注できます。だから守るのは、その発注が届くまでのリードタイム ぶんの需要だけ。発注点は 。
- 定期監視 :在庫を見るのは ごと。いまレビューで まで補充しても、次に手を打てるのは 日後で、その注文が届くのはさらに 日後= 日後。つまり、いま設定した在庫 は、次の補充が届くまでの 日間の需要を一手に支えなければなりません。レビューとレビューの狭間は無防備——だから保護期間が に伸びます。
保護期間が から に伸びると、リードタイム需要のばらつきは 。安全在庫も同じ比で増えます。
安全在庫の比は需要のばらつき にもサービス水準 にもよらず、保護期間の比の平方根だけで決まります。これが「定期は連続より在庫が要る」ことの定量的な正体です。
3. 達成サービス・在庫・発注頻度を比べる(コード)
需要は1日平均 ・標準偏差 、リードタイム 日、定期の発注間隔 日、目標 CSL=95%。発注量 (≒EOQ)にすると連続監視の発注間隔も 日になり、発注頻度をそろえた公平比較ができます。各方式の発注サイクルを多数シミュレートして保護期間需要が発注点/目標在庫を超える割合(達成欠品率)を測り、平均在庫はサイクル在庫+安全在庫で示します。保護期間を取り違えて のままにした「素朴な定期」も並べます。
import numpy as np
import pandas as pd
from scipy.stats import norm
mu_d, sigma_d = 50.0, 12.0 # 日次需要 N(μ_d, σ_d)
L, T = 4, 14 # リードタイム L 日/定期発注の間隔 T 日
z = norm.ppf(0.95) # 目標CSL=95%
Q = 700 # 定量発注量(≒EOQ)
D = mu_d * 365 # 年間需要
# 定量(Q,r):保護期間 L。 安全在庫 SS=z·σ_d·sqrt(L)、発注点 r=L·μ_d+SS
SS_cont = z * sigma_d * np.sqrt(L)
r_point = L * mu_d + SS_cont
# 定期(P,S):保護期間 L+T。 安全在庫 SS=z·σ_d·sqrt(L+T)、目標在庫 S=(L+T)·μ_d+SS
SS_peri = z * sigma_d * np.sqrt(L + T)
S_level = (L + T) * mu_d + SS_peri
# 素朴な定期:保護期間を取り違え sqrt(L) のまま → 安全在庫が不足
S_naive = (L + T) * mu_d + SS_cont
print(f"定量(Q,r): 保護 L={L}日, SS=z·σ_d·sqrt(L) = {SS_cont:.2f}, r={r_point:.2f}")
print(f"定期(P,S): 保護 L+T={L+T}日, SS=z·σ_d·sqrt(L+T) = {SS_peri:.2f}, S={S_level:.2f}")
print(f"安全在庫比 SS_定期/SS_定量 = {SS_peri / SS_cont:.4f} (理論 sqrt((L+T)/L) = {np.sqrt((L + T) / L):.4f})")
print()
# 発注サイクルを多数シミュレート:各サイクルで保護期間の需要を合計し、
# 発注点 r(定量)/目標在庫 S(定期)を超えたら欠品 → 達成欠品率を測る
rng = np.random.default_rng(20)
n = 400000
DL = rng.normal(mu_d, sigma_d, (n, L)).sum(axis=1) # 定量:保護 L 日の需要
DLT = rng.normal(mu_d, sigma_d, (n, L + T)).sum(axis=1) # 定期:保護 L+T 日の需要
so_cont = np.mean(DL > r_point)
so_peri = np.mean(DLT > S_level)
so_naive = np.mean(DLT > S_naive)
# 平均在庫=サイクル在庫+安全在庫、発注頻度=年間需要/1回発注量
rows = [
{"方策": "定量(Q,r) 保護L", "安全在庫": SS_cont,
"平均在庫": Q / 2 + SS_cont, "発注/年": D / Q, "達成欠品率": so_cont},
{"方策": "定期(P,S) 保護L+T", "安全在庫": SS_peri,
"平均在庫": mu_d * T / 2 + SS_peri, "発注/年": 365 / T, "達成欠品率": so_peri},
{"方策": "定期(素朴) √Lのまま", "安全在庫": SS_cont,
"平均在庫": mu_d * T / 2 + SS_cont, "発注/年": 365 / T, "達成欠品率": so_naive},
]
print(pd.DataFrame(rows).to_string(index=False, float_format=lambda x: f"{x:.2f}"))
print("\n目標欠品率は 5%(CSL=95%)。定量・定期(正しいSS)はともに約5%を達成。")
print("定期は保護期間 L+T のぶん安全在庫が 2.12 倍・平均在庫も多い。")
print("√L のまま(素朴)だと保護期間を取り違え、欠品率が約22%に跳ね上がる。")
出力:
定量(Q,r): 保護 L=4日, SS=z·σ_d·sqrt(L) = 39.48, r=239.48
定期(P,S): 保護 L+T=18日, SS=z·σ_d·sqrt(L+T) = 83.74, S=983.74
安全在庫比 SS_定期/SS_定量 = 2.1213 (理論 sqrt((L+T)/L) = 2.1213)
方策 安全在庫 平均在庫 発注/年 達成欠品率
定量(Q,r) 保護L 39.48 389.48 26.07 0.05
定期(P,S) 保護L+T 83.74 433.74 26.07 0.05
定期(素朴) √Lのまま 39.48 389.48 26.07 0.22
目標欠品率は 5%(CSL=95%)。定量・定期(正しいSS)はともに約5%を達成。
定期は保護期間 L+T のぶん安全在庫が 2.12 倍・平均在庫も多い。
√L のまま(素朴)だと保護期間を取り違え、欠品率が約22%に跳ね上がる。
出力の意味:安全在庫は定量 39.48 個に対し定期は 83.74 個と 2.12 倍——理論値 にぴたり一致します。シミュレーションでは、定量も「正しい SS の定期」もともに達成欠品率 約5%(0.05)で目標 CSL=95% を満たしました。発注頻度は両方とも年26.07回でそろえてあるのに、定期は平均在庫が多い(389.48 → 433.74 個)——これが「定期は管理が楽だが在庫が増える」のコストです。圧巻は最下行の素朴な定期:保護期間が に伸びることを見落として のまま(安全在庫 39.48)にすると、達成欠品率が0.22=約22%に跳ね上がります。在庫を 433.74 → 389.48 と削って一見お得に見えて、実は5サイクルに1回以上品切れ——「定期では保護期間 を守る」を外すと、サービスが崩壊することが数値で分かります。
4. 在庫推移を重ね描きする(コード)
最後に、両方式の在庫の動き方の違いを目で見ます。同一の擬似需要系列に対して定量 と定期 を日次でシミュレートし、手持ち在庫ののこぎり波を重ねます。定量は発注点 を割るたびに定量 を不定期に、定期は** 日ごとに量を変えて**発注する様子に注目してください。
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
from scipy.stats import norm
rng = np.random.default_rng(33)
mu_d, sigma_d = 50.0, 12.0
L, T = 4, 14
z = norm.ppf(0.95)
Q = 700
r_point = L * mu_d + z * sigma_d * np.sqrt(L) # 定量の発注点
S_level = (L + T) * mu_d + z * sigma_d * np.sqrt(L + T) # 定期の目標在庫
days = 120
demand = np.maximum(rng.normal(mu_d, sigma_d, days), 0.0) # 同一の需要系列
def simulate(policy):
net = S_level # 同じ初期在庫から開始
pipeline = {}
hist, orders = [], []
for t in range(days):
if t in pipeline:
net += pipeline.pop(t)
net -= demand[t]
IP = net + sum(pipeline.values())
if policy == "continuous":
if IP <= r_point: # 発注点で定量 Q を不定期に発注
pipeline[t + L] = pipeline.get(t + L, 0.0) + Q
orders.append(t)
else:
if t % T == 0: # T 日ごとに S まで(発注量は可変)
q = max(S_level - IP, 0.0)
if q > 0:
pipeline[t + L] = pipeline.get(t + L, 0.0) + q
orders.append(t)
hist.append(max(net, 0.0))
return np.array(hist), orders
oh_c, ord_c = simulate("continuous")
oh_p, ord_p = simulate("periodic")
print(f"定量(Q,r): 平均在庫 {oh_c.mean():.1f} 個, 発注回数 {len(ord_c)} 回(不定期・定量{Q}個)")
print(f"定期(P,S): 平均在庫 {oh_p.mean():.1f} 個, 発注回数 {len(ord_p)} 回({T}日ごと・発注量可変)")
fig, ax = plt.subplots(figsize=(11, 5.5))
ax.plot(oh_c, color="#1f77b4", lw=1.8, label="定量(Q,r) 在庫")
ax.plot(oh_p, color="#d62728", lw=1.8, label="定期(P,S) 在庫")
ax.axhline(r_point, ls="--", color="#1f77b4", alpha=0.7, label=f"発注点 r={r_point:.0f}")
ax.plot(ord_c, oh_c[ord_c], "v", color="#1f77b4", ms=8)
ax.plot(ord_p, oh_p[ord_p], "v", color="#d62728", ms=8)
for t in ord_p:
ax.axvline(t, color="#d62728", ls=":", alpha=0.25)
ax.set_xlabel("日"); ax.set_ylabel("手持ち在庫(個)")
ax.set_title("在庫推移:定量=発注点で不定期に定量発注/定期=一定間隔で量を変えて発注")
ax.legend(loc="upper right"); plt.tight_layout(); plt.show()
出力:
定量(Q,r): 平均在庫 412.3 個, 発注回数 8 回(不定期・定量700個)
定期(P,S): 平均在庫 473.3 個, 発注回数 9 回(14日ごと・発注量可変)
出力の意味:この120日窓では定量が8回・定期が9回の発注(おおむね14日に1回でそろう)。定期のほうが平均在庫が高い(412 → 473 個)のは、第3節で見た「保護期間 ぶんの厚い安全在庫」を抱えるからです(窓が短いので絶対値は第3節の定常値とは少しずれますが、定期>定量の大小は一致)。図を見ると性格の違いが一目瞭然——青い定量は、在庫が発注点 (青い破線)を割るたびに同じ高さ()だけ跳ね上がり、谷の深さ(残量)に応じて山の間隔が伸び縮みします(不定期・定量)。赤い定期は、赤い点線の等間隔(14日ごと)に発注し、そのときの在庫の減り具合で山の高さがまちまち(一定間隔・可変量)。「定量は山の高さが一定で間隔が可変/定期は間隔が一定で高さが可変」——これが2方式の見分け方です。
⚠️ よくある誤解
- 「定期発注は安全在庫が少なくて済む」ではない:逆です。定期はレビュー間隔 のあいだ無防備なので保護期間が に伸び、安全在庫は 倍多く要ります。定期の利点は在庫の節約ではなく運用の手軽さ(発注日が決まっている・棚卸とそろう・複数品目をまとめられる)です。
- 「保護期間は定期でも でよい」ではない:第3節の素朴な定期が示すとおり、 のまま組むとサービスが崩壊(欠品率 約22%)。定期の安全在庫は必ず で。発注点だけ で設計するのは連続監視の話です。
- 「定量発注はいつでも優れている」ではない:定量は常時監視が前提で、リアルタイムに在庫を追える仕組み(POS・WMS)が要ります。多数の品目を同じ便でまとめて発注したい(共同発注で発注コストを割り勘にしたい)なら、発注日をそろえられる定期が有利——在庫増を運用効率で取り返します。どちらが良いかは品目の重要度・監視コスト・共同発注の有無しだいです。
- 「 と で尽き」ではない:両者を組み合わせた 方式(定期に見て、 を割っていたら まで発注)や、 など発展形があります。需要が断続的だったり発注コストが大きい場合に有利なことがあり、これらは発展トピックです(要最新確認)。
関連ノート
- 安全在庫と発注点(発注点 ROP・安全在庫 。本稿は保護期間を に拡張)
- 経済的発注量EOQ(発注量 =定量発注の発注ロット)
- 第6章 サプライチェーン(在庫集約・リスクプーリング・共同発注で発注方式を選ぶ)
- 第9章 確率的在庫モデル( など発展的な発注方策・単一期)
- オペレーションズ・マネジメント 全体目次