ai_math_runningのブログ

最近はAI関係の記事が多い予定です。一応G検定持ってる程度の知識はあります。

ドルコスト平均法はまやかしか?

今、増田を中心に投資話で盛り上がっていて、私もいくつか書いたりしましたが、その中で、こっちにちゃんと書こうと思った話があったので。
種銭が少なくても貧乏な頃から投資を始めてよかったと思う理由2つ

これ自体はとても良い話なんですが、一部、気になる記述が。

ドルコスト平均法はまやかしです。

まやかしじゃないんですけどね。これを理解するために、ちょっとシミュレーションしてみましょう。
いえ、大したものじゃないです、Excelでもできるものですが、ちょっとはてなでコード記述してみたかったので。

シミュレーションの設定

ドルコストとそうじゃない買い方を比較して、ドルコスト平均法の優秀性を示すのが目的です。
なので、基本100円の金融商品を100つ、1万円で買うのを30年続けるという設定で、その金融商品の価格が100円をベースに標準偏差10でばらつく、という事にして、

  1. 普通の買い方:ずっと100個買い続ける
  2. ドルコスト平均法:10000円で買えるだけ買う

というのを比較します。

(本来なら価格は変動しながら年4%で上昇させたい所ですが、その場合「普通の買い方」の設定が非常に面倒になるので。ここでは比較だけが目的なので、価格は上昇させずに変動だけさせます。)

これは、平均100、標準偏差10の正規分布乱数を30年分(12ヶ月 x 30 = 360)出力させて、それを元に計算すればシミュレーションできます。1回だけなら偶然かもしれないので、100回分、乱数を出力させて、それぞれ集計して、それがどういう分布するかを見てあげれば感じはつかめると思います。

シミュレーションの実際

では、計算始めましょう。python(軟弱なのでjupyterで)でやります。まずおまじない。

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

次に、価格の設定。正規分布乱数を360 x 100 個出力(集計しやすいように行列形式で)して、それを元に1回の購入個数、購入金額を計算していきます。

price_1 = np.random.normal(100, 10, (360, 100))
N_num = 100 * np.ones([360, 100])
N_cost = N_num * price_1
DC_num = 10000 // price_1
DC_cost = DC_num * price_1

これで各回の購入個数、購入金額が求まったので、集計してグラフで見てみましょう。

購入個数の集計

30年間、この設定で購入を続けた時の合計個数を計算します。ランダムなので100回やって、それぞれどういう値になるかをプロットしてみます。

N_num_sum = np.sum(N_num, axis=0)
DC_num_sum = np.sum(DC_num, axis=0)

plt.plot(range(0, 100), N_num_sum)
plt.plot(range(0, 100), DC_num_sum)
plt.show()
青:普通の買い方 / オレンジ:ドルコスト平均法

普通の買い方は毎回100個なので、合計36000個は何度シミュレーションしても固定です。ドルコストでは、価格の変動によって買う量が変わるので、シミュレーションごとに変わってきていますが、概して普通の買い方より多く買っていることになっています。

購入金額の集計

それでかかった金額を集計して、同様にプロットします。

N_cost_sum = np.sum(N_cost, axis=0)
DC_cost_sum = np.sum(DC_cost, axis=0)

plt.plot(range(0, 100), N_cost_sum)
plt.plot(range(0, 100), DC_cost_sum)
plt.show()
購入金額集計 青:普通の買い方 / オレンジ:ドルコスト平均法

今度はドルコスト平均法の方がほぼ固定ですね。10000円で買える量を買っているので当然です。でも個数を整数にして切り捨ててるのでちょっと変動しています。360万円より少し下なのは切り捨てている影響ですね。一方、「普通の買い方」は価格変動すると買う量は変わらないので購入金額がその分、大きくぶれます。

平均購入価格

かかった金額の集計結果を、購入個数の総計で割ってやると、購入価格の平均が出せます。それもプロットしてみましょう。

N_price = N_cost_sum / N_num_sum
DC_price = DC_cost_sum / DC_num_sum

plt.plot(range(0, 100), N_price)
plt.plot(range(0, 100), DC_price)
plt.show()
平均購入価格 青:普通の買い方 / オレンジ:ドルコスト平均法

色々とぶれますが、ドルコスト平均法の方が一円くらい安く買えているのが分かると思います。
これで、ドルコスト平均法の優秀さは出せているのですが、一応、損益も見てみましょう。

損益の集計
N_PL = price_1[359, :] * N_num_sum - N_cost_sum
DC_PL = price_1[359, :] * DC_num_sum - DC_cost_sum

plt.plot(range(0, 100), DC_PL - N_PL)
plt.show()
ドルコスト平均法と普通の買い方の収支の差

収支は、価格が上昇しているとしていないので、場合によっては黒字だったり赤字だったりしますが、どの場合も、ドルコスト平均法の方が収支は優れています。(比較が目的なので、これで良いんです。実際の収支が気になる人は、DC_PL, N_PLをプロットしてみてください。

年4%で増えている場合のシミュレーション

収支が悪いと誤解されそうなので、ちゃんと年4%で上昇している場合を計算してみましょう。価格に等差数列をかけて、新たな価格を作って、同じように計算します。こちらはドルコスト平均法だけです。それで収支がどのようになるか、を見てください。

price_2 = price_1 * np.tile(np.geomspace(1, 1.04**30, 360), (100, 1)).T
DC_num2 = 10000 // price_2
DC_cost2 = DC_num2 * price_2

DC_num2_sum = np.sum(DC_num2, axis=0)
DC_cost2_sum = np.sum(DC_cost2, axis=0)
DC_PL2 = price_2[359, :] * DC_num2_sum - DC_cost2_sum
plt.plot(range(0, 100), DC_PL2)
plt.show()
ドルコスト平均法での収支

30年後の株価で集計しているので、そのばらつきでかなり変動するのですが、とりあえず最低でも150万円、上手くいくと500万、平均で350万くらいの黒字になっていますね。

売却時もドルコスト平均法的に計算

で、これは満期時に全て換金する設定なので、その時の株価に影響を受けてしまう訳ですね。そのリスクが大きいんじゃないかっていう人も多いと思うので、それに対しての回答を。実はブコメで答え書いてる人が居たんですよね。

投資いいよ派に聞きたいこと

「利確タイミング」とか「出口戦略」と言う人よく見かけるけど、なぜ『必要な時に必要な分だけ売却する』って考えに至らないの?銀行口座の預金も“必要な時に必要なだけおろす”やん、それと同じよ。

2022/08/30 15:48
b.hatena.ne.jp

その通りなんですよね!
必要な時に少しずつ換金する事で、換金するタイミングのリスクを分散できるんです。何も一度に換金しなくても良い訳で、必要なだけ換金するというスタイルでオーケーなのです。
という事で、その効果についてもシミュレーションしてみましょう。

設定

株価はこの後も同じように変動しながら上昇し続ける、という設定。それで、毎月10万ずつ換金(10万必要という設定なので、10万を下回らない個数売る)、積み立ての10倍積み立てるので10分の1くらいの期間:3年になりそうですが、2倍くらいになってるので6年くらいは引き出せるかな。無くなるまで換金する、一応マージンとって10年間計算します。それで売却した合計から積み立てた合計を引いて収支計算します。

import copy
price_3 = np.random.normal(100, 10, (120, 100)) * np.tile(np.geomspace(1.04**30, 1.04**40, 120), (100, 1)).T
remain_n = copy.deepcopy(DC_num2_sum)
DC_num3 = 100000 // price_3 + 1
for i in range(120):
    DC_num3[i, :] = np.minimum(remain_n, DC_num3[i, :])
    remain_n -= DC_num3[i, :]

DC_SA = price_3 * DC_num3
DC_SA_sum = np.sum(DC_SA, axis=0)
DC_PL3 = DC_SA_sum - DC_cost2_sum
plt.plot(range(0, 100), DC_PL2)
plt.plot(range(0, 100), DC_PL3)
plt.show()
収支 青:満期で全額換金 / オレンジ:満期後10万円ずつ換金

換金を分散させるだけで、収支が高いレベルで安定する事が分かると思います。
ちなみに受け取り金額は

plt.plot(range(0, 100), DC_SA_sum)
plt.show()
受け取り金額の総額

かなり安定して高い金額を受け取れる事が分かると思います