xellstorm
JA
アプリを開く

需要が不確実なとき、何個発注すべきか?

例題 · 発注量 · 2026年10月更新

需要が66.7%の確率で下回る量、つまり臨界比(クリティカルフラクタイル)の量を発注します。需要の平均が1,000個(標準偏差200)、1個は10で売れ、原価は4、売れ残れば1で処分できる場合、それは1,086.1個で、期待利益は5,345.5です。サンプルファイルをモンテカルロで探索すると、その最適値に最も近い刻みの1,090個が選ばれます。

臨界比は、もう1個売れる確率にその利益を掛けた値が、売れ残る確率にその損失を掛けた値とちょうど釣り合う点です。販売を逃したときに失う利益が売れ残り1個の損失より大きいと、その点は需要の中央値(需要が半分の確率で超える水準)より上になります。この例の需要は正規分布なので、中央値は平均に等しく、金額はExcelファイルの通貨単位です。探索は発注量600〜1,600個を10個刻みで調べ、1,090個での平均利益は5,345 ± 31(95%区間、5,000シーズンのシミュレーション)、需要が在庫を超えるのはシーズンの32.6%です。

モデル

これはニュースベンダー問題です。販売シーズンの前に1回だけ発注し、需要は可能性の範囲としてしかわからず、売れ残りはシーズン末に安く処分し、発注量を超える需要は失われます。ExcelファイルのシートはModelの1枚だけで、A列にラベル、B列に値が入っています。

この例の数値(金額はExcelファイルの通貨単位)
発注量、B11,000個(決定変数)
価格、B2販売1個あたり10
原価、B3発注1個あたり4
処分価格、B4売れ残り1個あたり1
需要、B6正規分布、平均1,000個、標準偏差200

4つの数式が、発注量と需要からシーズンの結果を求めます。販売数(Sold)は=MIN(B1,B6)、売れ残り数(Leftover)は=MAX(B1-B6,0)、利益(Profit)は=B2*B8+B4*B9-B3*B1で、売上と処分収入の合計から発注全体の原価を引いたもの、販売機会損失(Lost sales)は=MAX(B6-B1,0)で、発注量では満たせなかった需要です。ここでの欠品とは、販売機会損失が出るシーズン、つまり需要が発注量を上回るシーズンのことです。アドインの関数は使っていません。

ダウンロードできるファイルには、これらの数式、1,000個の発注量、需要セルの固定の仮の値が入っています。需要分布、2つの出力(ProfitとLost sales)、欠品の目標、最適化の設定はxellstorm側にあり、サンプルを開くと読み込まれます。Excelファイル自体は、ふつうに作ったままです。

正規分布では原理上、需要がマイナスになりえますが、ゼロは平均より標準偏差の5倍下にあり、その確率は約3.5×10⁶分の1です。5,000回のシミュレーションで引いた需要の最小値は200個です。需要は連続値として引くため、販売数、売れ残り、下のゴールシークで求める発注量は、1個未満の端数になることがあります。実際に発注するときは整数に丸めてください。

平均需要より多く発注するのはなぜか?

発注の最後の1個を考えます。売れれば、価格から原価を引いた10 − 4 = 6が得られます。売れ残れば、原価から処分価格を引いた4 − 1 = 3を失います。1個を加えて得になるのは、売れる確率×6が、売れ残る確率×3を上回る間、つまり売れる確率が3 / (6 + 3) = 33.3%を上回る間です。発注量が平均需要と同じ1,000個のとき、次の1個が売れる確率は半々なので、それより多く発注すると得になります。得にならなくなるのは、需要が発注量を下回る確率が66.7%になる点です。

シミュレーションでは、同じ計算をシーズンごとに確かめられます。同じ5,000シーズンのシミュレーションで、1,000個ではなく1,090個を発注すると、需要が1,090個に達するシーズン(32.6%)では、利益がちょうど540(90 × 6)増え、需要が1,000個以下にとどまるシーズン(50%)では、ちょうど270(90 × 3)減ります。その間のシーズンでは、差はこの2つの間に入ります。平均では、発注を増やすと1シーズンあたり63.5多く稼げ、これは下の理論式が示す値(63.5)と一致します。

理論値:臨界比

このルールには臨界比(クリティカルフラクタイル)という名前があります。最適な発注量Q*は、需要がその水準以下に収まる確率が(価格 − 原価) / (価格 − 処分価格)になる点で、ここでは(10 − 4) / (10 − 1) = 0.667です。正規分布の需要では、Q* = 平均 + z × 標準偏差で、z = 0.4307は、標準正規分布で66.7%が下側にある点です(Excelでは=NORM.S.INV(6/9))。よって、Q* = 1,000 + 0.4307 × 200 = 1,086.1個です。

期待利益も式で書けます。任意の発注量Qについて、z = (Q − 平均) / 標準偏差とすると、期待利益は(価格 − 処分価格) × (平均 − 標準偏差 × L(z)) − (原価 − 処分価格) × Qです。L(z) = φ(z) − z × (1 − Φ(z))は標準正規損失関数で、φは標準正規分布の密度、Φはその累積分布です(Excelでは=NORM.S.DIST(z,FALSE)-z*(1-NORM.S.DIST(z,TRUE)))。標準偏差 × L(z)は、期待される販売機会損失です。Q*では、(価格 − 原価) × 平均 − (価格 − 処分価格) × 標準偏差 × φ(z) = 5,345.5となり、欠品の確率は1 − 0.667 = 33.3%です。代わりに平均需要の1,000個を発注すると、期待利益は5,281.9です。

シミュレーションで発注量を探す

この式が使えるのは、モデルがここまで単純で(商品1つ、発注1回、価格固定)、需要分布の分位点と期待販売機会損失に式がある場合に限られます。シミュレーションに必要なのは需要を引く方法だけで、この例では、同じ答えが得られることを確かめます。サンプルとともに読み込まれる最適化の設定では、発注量(B1)を決定変数とし、600〜1,600個を10個刻みで、101通りの候補をすべて試して、Profitの平均を最大化します。制約が1つあり、欠品の確率(Lost salesが0を超える試行の割合)を50%以下にします。各候補は1,000回の試行でシミュレーションし、上位3つは5,000回で再実行します。どの実行でも、需要の乱数は同じものを使います。この同じ乱数のおかげで、候補どうしの違いは発注量だけによるもので、乱数の運には左右されません。

発注量ごとの平均利益発注量600〜1,600個を10個刻みで、シミュレーションしたシーズン1,000回の平均利益を発注量ごとに示します。帯は95%区間、破線は理論上の期待利益です。探索では曲線が1,100個でピークになり、5,000回の試行による再実行では1,090個が選ばれ、平均利益は5,345です。3,5004,0004,5005,0005,5006008001,0001,2001,4001,600最適1,090破線:理論値
発注量(個)ごとの1シーズンあたりの平均利益。発注量ごとにシミュレーションしたシーズン1,000回(実線、95%区間の帯つき)と、正規分布の式による理論上の期待利益(破線)。点線は、5,000回の試行による再実行で勝った発注量です。
最良の発注量、5,000回の試行で再実行(平均利益と95%区間)
発注量(個)平均利益理論上の期待利益欠品の確率
1,0905,345 ± 315,345.432.6%
1,1005,344 ± 315,344.030.9%
1,1105,341 ± 325,340.929.1%

再実行で選ばれるのは1,090個です。平均利益は5,345 ± 31で、その発注量での理論値は5,345.4、欠品はシーズンの32.6%(理論上は32.6%)です。理論上の最適値1,086.1に最も近い刻みであり、理論上の期待利益5,345.5はこの区間の内側にあります。

上位3つの発注量の区間はほぼ完全に重なりますが、勝者は明確です。各区間は、その候補の平均に含まれるノイズをxellstormが推定したもので、試行を20個のバッチに分けたときの平均のばらつきから求めます。xellstormの既定であるラテンハイパーキューブサンプリングは、各実行の乱数を需要分布に均等に散らすので、1回の実行の平均は区間が示すよりもさらに安定します。ほかの3通りのシードで再実行しても、1,090個での平均利益は、この実行の値から0.2以内にとどまります。

決め手になるのは候補どうしの差です。同じ乱数がすべての候補を一緒に押し上げ、押し下げるので、差は区間よりずっと安定しています。シーズンごとに比べると、1,090個は1,100個を1.43上回ります(95%区間は0.47〜2.39)。区間はゼロを含まないので、偶然の範囲を超えて良いものの、差はわずかです。期待利益の理論上の差は1.43です。頂点付近では利益曲線が平らなので、1刻みずれても損失はほとんどありません。範囲の両端の600個と1,600個では、期待利益は3,585と4,199に下がります。

探索そのものでは、1,100個が1位になり、平均利益は5,370.3で、1,090個の5,369.9を上回りました。探索で使うのは5,000回の試行のうち最初の1,000回で、これらはたまたま需要がやや多く、平均1,003.7個(全体では1,000.0個)でした。そのため頂点付近の大きめの発注量の利益が持ち上がり、ピークが1刻み上に動きます。5,000回での再実行で決着がつき、再実行で勝者が入れ替わった場合は、xellstormがその旨を表示します。

制約と、欠品を減らす費用

欠品の制約は、ここでは効いていません。制約が除外するのは1,000個以下の発注量です(1,000個では、探索の試行の51.6%で在庫が尽きます)。正規分布の需要では、平均どおりの発注量だと半分の確率で在庫が尽きます。最適な発注量では、欠品の確率はすでに32.6%に下がっています。

発注量ごとの欠品の確率発注量ごとに、需要が発注量を上回ったシミュレーションシーズン1,000回の割合を示します。帯は95%区間、破線は理論上の確率、点線は制約の上限50%です。最適な発注量1,090個での確率は32.6%(試行5,000回)で、ゴールシークで欠品の確率が10%になるのは1,256.25個です。0%25%50%75%100%6008001,0001,2001,4001,600上限50%最適1,090破線:理論値1,256で10%
欠品の確率(需要が発注量を上回る確率)と発注量の関係。発注量ごとにシミュレーションしたシーズン1,000回(実線、95%の帯つき)、理論上の確率(破線)、最適化の上限50%(点線)、欠品の確率を10%にするゴールシークの答え。

シーズンの32.6%で欠品が起きるのが多すぎるなら(たとえば、空の棚を見た客が戻ってこない場合)、許容できる確率を決め、ゴールシークで発注量を探します。xellstormのゴールシークは、統計量が目標に届くまで、発注量の範囲を半分ずつ狭めます。1回の評価につき5,000回の試行で、7回の評価の後に1,256.25個が見つかり、このとき試行のちょうど10%で在庫が尽きます。理論値は、超えられない確率が90%となる需要水準で、1,000 + 200 × NORM.S.INV(0.9) = 1,256.3個です。

発注量1,000個(平均需要)、1,090個(平均利益が最大)、1,256.25個(欠品の確率10%)を、同じ5,000シーズンのシミュレーションで比較
発注量(個)1,0001,0901,256.25
平均利益5,2825,3455,146
P10利益3,6953,4252,926
欠品の確率50%32.6%10%
売れ残り数の平均(個)80133266
販売機会損失の平均(個)80439

欠品の確率を32.6%から10%に下げるには、166個多く発注することになり、そのうち133個は平均的なシーズンで売れ残ります。その代わり、1シーズンあたりの平均利益が199(3.7%)減ります(2つの発注量の期待利益の理論上の差は199.4)。P10利益、つまり90%のシーズンが達する水準も、3,425から2,926に下がります。需要の弱いシーズンでは、発注が多いほど売れ残る在庫が増えるためです(P50、P80、P90を参照)。平均需要どおりに発注すると、3つの中でP10が最も高くなりますが、シーズンの50%で在庫が尽きます。欠品を減らす価値があるかどうかは事業上の判断で、シミュレーションはその代償を数字にします。

試してみる

  1. xellstormでモデルを開きます。需要分布、出力のProfitとLost sales、目標(Lost salesが0を超える確率、つまり欠品の確率)、最適化の設定はすべて設定済みです。インストールも登録も不要で、Excelファイルはブラウザー内で計算します。
  2. 実行します。保存された発注量1,000個、サンプルのシード(7)、5,000回の試行では、平均利益は5,282、欠品の確率は50%です。
  3. 「Optimize」ステップを開きます。発注量(Model!B1)が決定変数のセルで、範囲は600〜1,600、刻みは10です。目的はProfitの平均の最大化、制約はLost salesが0を超える確率を50%以下に保つことです。「Optimize」を押すと、アプリは各発注量を1,000回の試行で評価し、上位3つを5,000回で再実行し、勝者と次点を試行ごとに比べ、発注量ごとの平均利益を95%の帯つきでグラフにします。
  4. 欠品の確率が10%になる発注量を求めるには、「Goal seek」を選びます。統計量を「Probability」、Lost salesの条件を「>」としきい値0、目標を0.1に設定します。発注量の「Step」欄は空にし(最適化の設定では10が入っています)、「Trials per evaluation」を5,000にして、「Seek goal」を押します。
  5. 「Set as fixed cells」を押してシミュレーションを再実行すると、選んだ発注量での全結果が出ます。「Add as scenario」を押すと、保存済みの発注量と同じ乱数で比較できます。

普通のExcelでもできますか?

この例のとおりの単純なケースなら、できます。需要が正規分布なら、=NORM.INV((B2-B3)/(B2-B4), 1000, 200)で臨界比による発注量1,086.1がそのまま求まります。需要が偏っている場合は、NORM.INVをその分布の逆関数(LOGNORM.INV、GAMMA.INV、または過去の販売実績に対するPERCENTILE.INC)に置き換えます。ただし、複数の商品が予算や倉庫を共有する、最小発注単位がある、値引き価格が残りの量で決まる、といった場合には、このルール自体が使えなくなります。シミュレーションならそれらを扱えますが、シミュレーションしたモデルをExcelのみで最適化するのは面倒です。再計算のたびに新しい乱数が引かれるため、データテーブルやソルバーは候補ごとに違う乱数で発注量を比べ、ノイズを追いかけてしまいます。すべての候補を固定した1組の乱数で評価する作業は、xellstormが引き受けます。Excelでのモンテカルロシミュレーションで、一般的な方法を紹介しています。

よくある質問

ニュースベンダーモデルとは?

ニュースベンダーモデルは、需要がわからない段階で、1回の販売期間に向けてどれだけ在庫を持つかを決める古典的な問題です。売れ残りは原価を下回る価格で処分し、在庫を超える需要は失われます。最適な発注量は需要の臨界比、つまり需要がその量を下回る確率が(価格 − 原価) / (価格 − 処分価格)になる量です。名前は、新聞売りが毎朝何部仕入れるかを決める場面に由来します。季節商品、生鮮食品、イベントの収容人数、単発の生産ロットでも、同じ問題が起こります。繰り返し補充する在庫については、コストと欠品のバランスをとる発注点はどれかをご覧ください。

最適な発注量が平均需要を下回るのはどんなときですか?

売れ残り1個のコストが、販売を逃したときに失う利益より大きいとき、つまり原価から処分価格を引いた額が、価格から原価を引いた額より大きいときです。このとき臨界比は2分の1を下回り、正規分布のような対称な需要分布では、最適な発注量は平均を下回ります。薄利で、売れ残りの価値がゼロの場合は発注量が下がり、利幅が大きく、処分価格が高い場合は上がります。

なぜすべての発注量を同じ乱数で評価するのですか?

すべての発注量を同じ需要のシミュレーションで評価する(同じ乱数を使う)と、候補どうしの違いは発注量だけから生じます。この例では、上位3つの発注量の95%区間はほぼ完全に重なっていますが、上位2つのシーズンごとの差の区間は0.47〜2.39で、ゼロを含みません。通常のモンテカルロサンプリングで候補ごとに新しい乱数を引くと、探索はノイズを追いかけてしまいます。この2つの発注量の差を同じ精度で測るには、同じ乱数を使う場合の約2,000倍の試行が必要です。

需要が正規分布でない場合は?

需要が正規分布でなくても臨界比は成り立ちますが、発注量はその分布の分位関数から求める必要があり、上の期待利益のような式は使えなくなります。シミュレーションに必要なのは分布そのものだけです。xellstormでは、需要セルに対数正規分布、ガンマ分布、PERT分布、ポアソン分布、負の二項分布など別の分布を選ぶか、「Distributions」ステップで過去の販売実績に分布を当てはめるか、Excelファイルの数式で他の不確かな入力から需要を計算するようにして、同じ最適化を実行します。

関連ページ

xellstormは、Excelモデル向けのブラウザー型モンテカルロシミュレーションツールです。アドインは不要で、Excelファイルがパソコンの外に出ることはありません。