Min-Max発注方式のMaxはどうやって決めるのか?Pythonでシミュレーションしてみた

2024年5月18日

Photo by Tra Nguyen on Unsplash

◆仕事や勉強の息抜きに。。。

Min-Max発注方式とは?

いつ発注するかという観点で言うと、発注方式は大きく2つに分けられます。

発注点を切ったら発注する方式と、定期的に発注する方式です。

Min-Max方式は前者の一種です。

 

前者の代表例には前記事で紹介した定量発注方式があります。

【定量発注方式】PythonのInventorizeライブラリで在庫シミュレーションしてみた

 

これは発注点を切ったら予め決められた一定数量を発注する方式でしたが、Min-Max方式では発注点を切ったら予め決められたMaxと在庫量との差を発注します。

ですので、Min-Max方式では発注点Maxをいかに決めるかが肝になります。

 

ちなみに発注点のことをミニマムの在庫量と見做しているため、Min-Max方式と呼ばれます。

 

具体例で発注点とMax量を計算する

それでは前回の記事【定量発注方式】PythonInventorizeライブラリで適正在庫シミュレーションしてみたで使ったのと同じ需要実績データから発注点を計算してみましょう。

あるアイテムについて次のような需要実績データがあるものとします。

 

この時、最初の45日間を見たデータとして需要の平均と標準偏差を求め、残りの75日間をまだ見ぬデータとしてシミュレーションするものとします。

 

最初の45日間のデータから発注点は次のように計算することができます。

リードタイム3許容欠品率5%とします。

 

許容欠品率から安全係数を求める方法については、下記の記事を参照下さい。

安全在庫の計算に必要な安全係数の二通りの求め方をわかりやすく解説!

 

このように発注点は5,262個に決まりましたが、Max量はどうやって決めるのでしょうか?

これには決まったやり方はありませんが、一つのやり方は発注点(Min量)にEOQ(経済的発注量)を加える方法です。

このようにMax量を決めれば、発注点を切ったら毎回ほぼEOQプラスαの量を発注することになります。

(発注量がプラスαになるのは発注点を切ってから気づくまでにタイムラグがあるため。これについては次章でも触れます)

しかしEOQより少し多い量を発注することになり、折角EOQを計算したのにその恩恵が少し減ってしまいます。

従って、このようにMax量を設定するくらいなら定量発注方式にした方が良いでしょう。

 

もう一つのやり方は、発注点(Min量)に平均需要×a日分を足す方法です。

このaをいくつにするかは、調達リードタイム発注コストが関係してきます。

調達リードタイムより大きな値にすることは当然ですが、どのくらい大きくするかは発注コストが関係してくるためです。

発注コストが高い場合にはaをそれだけ大きくします。

 

自動発注システムでもMax量の設定はaを入力できるようになっていたり、Max量そのものの値を入力できるようになっていることが多いようです。

 

Pythonで在庫シミュレーションする

次にMin-Max方式で発注を行った場合に、日々の在庫推移がどのようになるかを在庫シミュレーションしてみましょう。

これもinventorizeライブラリで一瞬にしてできてしまいます。

 

使う関数はsim_min_max_normalです。

指定する引数は需要データ、平均、標準偏差、リードタイム、サービス率(=1-許容欠品率)、Maxです。

需要データはまだ見ぬ75日間の需要データをリストとして渡します。

残りはMax量だけまだ決めていなかったので、まずは発注点+EOQとします。

 

発注点は前記事【定量発注方式】PythonのInventorizeライブラリで適正在庫シミュレーションしてみたでもやりましたが、inventorizeライブラリのreorderpoint関数を使って求められます。

引数としては平均、標準偏差、リードタイム、サービス率(=1-許容欠品率)を指定します。

import inventorize as inv
inv.reorderpoint(
  dailydemand = 1103.133,
  dailystandarddeviation = 685.2797,
  leadtimein_days = 3,
  csl = 0.95
)

EOQも前記事でやったようにinventorizeライブラリのeoq関数で求められ、6,689個になります。

 

需要データがtest_df['Item_A]に入っていて、平均、標準偏差、リードタイム、サービス率、発注点、EOQがそれぞれavsdld1-soropeoqに入っているとすると、次のように一瞬にして在庫シミュレーションができてしまいます。

result = inv.sim_min_max_normal(
  test_df['Item_A'],
  av,
  sd,
  ld,
  1-so,
  rop + eoq
)
result

前半に在庫シミュレーションの結果が、後半にその統計値がまとめられています。

 

前半の在庫シミュレーション結果をcsvファイルにexportして中身を見てみましょう。

result[0].to_csv('result_minmax_1.csv')

 

初期在庫は発注点である5,262個から始まっています。

従ってこの時点で発注点をヒットしているので、発注量を決めます。

Max量は発注点+EOQなので11,950個です。

従って発注量は11,9505,2656,685個です。

(上の表では6,688個になっていますが、これは端数処理の誤差です)

そして発注行為自体は次の日に行います。

これは定期発注方式や定量発注方式の場合と同じで、inventorizeライブラリの特徴です。

納品も発注の3日後にされていますね。

 

在庫にはinventory_levelinventory_positionがあり、前者は手持ち在庫で後者は輸送中のパイプライン在庫を合わせた総在庫です。

後者が発注点をヒットした時点で発注に入るので、2度目の発注は総在庫が4,225個になった8日目です(発注行為は9日目)。

 

このように在庫シミュレーションがなされますが、発注量を見てみるとすべてEOQである6,689個を少し上回る量になっています。

75日間の発注回数は12回です(下のH79参照)。

 

またこの時のサービスレベル96%在庫充足率(Fill rate98%です。

毎回EOQを発注する定量発注方式ではどうでしょうか?

同様に計算してみると次のようになります。

 

発注回数は13回で、サービスレベルは99%、在庫充足率(Fill rate)も99%です。

つまりMax量を発注点+EOQにしたMin-Max方式は発注回数は多少減るものの、欠品率が高まっています。

しかもEOQより少し多く発注するため、物流コストも増えることが予想されます。

つまりMax量を発注点+EOQにしたMin-Max方式では定量発注方式に敵わないということです。

 

最適なMax量はどう決めればよいのか?

次にMax量を発注点+平均需要×5にしてシミュレーションしてみましょう。

シミュレーション結果を同様に処理してみると次のようになります。

 

欠品率が下がりました。

発注間隔が少し短くなった分EOQより少ない数量で発注するため、輸送コスト(発注コスト)の増加が懸念されますが、輸送コストが高くない場合には問題ありません。

商品価格に輸送費も含まれているケースがこれに相当します。

 

それではMax量をもっと少なくしたらどうなるでしょうか?

発注点+平均需要×4にしてシミュレーションしてみましょう。

 

欠品率が上昇しました。

これではMax量が少なすぎということです。

 

今回の例ではMax量は発注点+平均需要×5が良さそうな感じですが、もちろんこれは需要パターンにより異なります。

重要なのはMax量を決めるのに定石はないということです。

過去のデータでシミュレーションして良さそうな値を決め、実際の欠品率を見ながら微調整をかけていくやり方が現実的と言えます。