こんにちは、東北投信という投資関連のウェブサイトを運営しています。
https://blog.tacos-heaven.xyz/
今回は、東北投信で記事を作成する際に利用している、__モンテカルロシミュレーション__ツールの作成について解説します。__モンテカルロシミュレーションとは、乱数を用いたシミュレーション方法__のことで、東北投信では__投資信託の運用成績をランダムに発生させる方法__として利用しています。
「投資信託の運用成績が乱数シミュレーションで完全に再現できるか」には限界がありますが、投資信託への理解を深めるためにはとても便利です。今回は簡単に「正規分布」で乱数を発生させる方法について解説します。
##乱数を発生させる数式
乱数を発生させる数式はエクセルのセルに用意します。式は以下の通り。
=NORM.INV(RAND(),リターン,リスク)
NORM.INV(確率,平均,標準偏差)
NORM.INV 関数の書式には、次の引数があります。
確率 必ず指定します。 正規分布における確率を指定します。
平均 必ず指定します。 対象となる分布の算術平均 (相加平均) を指定します。
標準偏差 必ず指定します。 対象となる分布の標準偏差を指定します。
ここでは確率の部分に、0~1の間で数値を乱数生成するRAND関数を与えることで、投資の成績に代用します。
正規分布する乱数の発生の解説はこちらが役立ちます。
今回は毎年の運用成績をこの数式で発生し、運用成績を累積させます。例えば50年間の運用をシミュレーションするならば、このNORM.INV関数も50個(50年分)用意し、毎年の利回りとして運用している金額に掛け算するわけです。
実際に毎年の運用成績を乱数で作ったものがこちらです。
以下はmyINDEX様にて公開されている、TOPIXの毎年の成績です。
なんとなく似ているように感じませんか?
##計算回数を増やす
ここまでの話は__1回の運用を乱数で再現しただけなので、統計データとしては不十分__です。そこで、計算回数を増やすことで、統計的に利用できるようにします。
特に根拠はありませんが、筆者作成のツールでは__1万回__の計算を行なっており、2回目以降の再計算を行なうためにVBAの出番となります。
計算の流れは、
- 最初に運用年数、リターン、リスク、積立額などをインプットする
- 計算開始する
- NORM.INV(RAND(),リターン,リスク)にて、1回の運用の計算を行なう
- VBAで必要なセルから必要なデータを別のセルにコピーする
- シートを再計算し、新たな乱数を与える
- 再び1回の運用計算を行なう(以後、4→5→6の繰り返し)
- 1万回計算を行なったら、1万個のデータから最小値・最大値・平均値・中央値などを取得する
- 終わり
です。
VBAで行なうことはデータのコピーと簡単な統計処理ぐらいなので、正直簡単です。実際構文自体もセルの読み込みのほか、For文ぐらいしか使っていません。
For i = 1 To 繰り返し回数
Worksheets("シート名").Calculate 'シートの再計算
Worksheets("シート名").Cells(セル書込位置, セル書込位置).Value = i
Worksheets("シート名").Cells(セル書込位置, セル書込位置).Value = Cells(セル読込位置, セル読込位置).Value
Next
Set Rng = Range(セルスタート位置, セル終了位置)
平均値:WorksheetFunction.Average(Rng)
最大値:WorksheetFunction.Max(Rng)
最少値:WorksheetFunction.Min(Rng)
中央値:WorksheetFunction.Median(Rng)
これで膨大なデータ群ができますので、あとは好きにデータ処理を行ないます。
ちなみに、2012年のCore i7マシンにて1万回の乱数計算を行なうと大体10秒ぐらいかかります。計算毎に画面の描画を伴うと時間の浪費に繋がるので、Application.ScreenUpdatingを使うことで高速化可能です。
Application.ScreenUpdating = False '画面に描画しない
Application.ScreenUpdating = True '画面に描画する
##今後の課題
投資信託の運用成績は「対数正規分布」に近いとも言われます。
このあたりも考慮した話も記事にしたいと思ってます(ファイル自体は作ったので、あとは記事ネタに使うだけ)