ちいつる
A-04リファレンス

モンテカルロ法 実装ガイド

資産形成シミュレーションの裏側にある計算根拠を、実装コード付きで公開する。

触ってみるボタンを押して200本のパスを試行してみてください

薄い線の1本1本が「あり得た未来」だ。1回ごとの結末はてんでばらばらなのに、中央の太い線(中央値)と上下の帯(10/90パーセンタイル)はどの試行でもほぼ同じ位置に落ち着く。試行を重ねるほど、確率的な答えは安定していく。

モンテカルロ法の基本原理

「将来はどうなるか」を1本の予測線で出す代わりに、乱数を使って何百〜何千通りもの未来を計算し、その分布を見る手法がモンテカルロ法である。1回の試算では「平均的にはこうなる」しか言えないが、多数の試行を重ねることで「悪いケースでもこの範囲に収まる可能性が高い」という確率的な答えが得られる。

触ってみる試行回数のスライダーを動かしてみてください
試行回数(打つ点の数)
500点

正方形の面積に対する四分円の面積の比は π/4。点を増やすほど「円内に入った割合×4」がπに近づく。

「乱数で点を打つだけ」の単純作業でも、数を重ねるとπという確定値に収束していく。モンテカルロ法の原理は、この最小の例にすべて詰まっている。

触ってみるスライダーで試行回数を変え、収束の様子を見てください
試行回数 N(対数軸)
200回
推定値3.3950
真値との差-0.1050
誤差の目安 ±1.96σ/√N±0.2367

推定値は真値のまわりをふらつき続ける。ただしそのブレ幅は試行回数の平方根に反比例して(1/√N)縮み、精度を10倍にするには試行を100倍にしなければならない。帯がじりじりとしか狭まらないのは、大数の法則が課すこのコストのためだ。

資産形成シミュレーションへの応用

毎年のリターンを固定値ではなく「平均リターン±ブレ幅」を持つ乱数として発生させ、これを想定年数分繰り返して最終資産額を1つ得る。これを1,000回試行すれば、1,000通りの最終資産額が得られ、その分布から「中央値」「悪いケース(下位10%)」「良いケース(上位10%)」を提示できる。

触ってみる目標額とブレ幅を動かして達成確率を確かめてください
目標資産(初期100)
300
ブレ幅(ボラティリティ)
15%
達成確率53.6%
中央値327
悪いケース(下位10%)114

モンテカルロ法の真価は「平均でいくら増えるか」ではなく「目標額に届く確率は何%か」「最悪でもどのくらい残るか」を数字で言えること。ブレ幅を上げると中央値はさほど動かなくても、下振れの裾が伸びて達成確率が下がるのが分かる。

触ってみる横軸のパーセンタイルをドラッグして値を読んでください

下位 10% の未来は 111 以下(1000通り中 約100通り)

1,000通りの結果を小さい順に並べ替えると、「下位10%」「中央値」といったパーセンタイルはこの並びの何番目かを読むだけになる。ファンチャートの上下の帯も、各時点でこの並び替えをしてパーセンタイル点を抜き出したものだ。

乱数分布の選び方(正規・対数正規)

年間リターンには正規分布を使うことが多いが、資産額そのもの(掛け算で増えていく量)は対数正規分布に従わせる方が、マイナス資産のような非現実的な値を避けられる。ボックス・ミュラー法などで正規乱数を生成し、複利計算に組み込むのが実装の定石である。

触ってみるブレ幅を大きくして分布の形を比べてみてください
期待リターン
5%
ブレ幅(ボラティリティ)
30%
正規分布(グレーの曲線)対数正規分布(青の曲線)資産がマイナスになる確率: 正規 0.02% / 対数正規 0%

ブレ幅を大きくすると、正規分布(グレー)は左裾が資産ゼロのラインを越え、「マイナスの資産」にまで確率を割り当ててしまう。対数正規分布(青)はどれだけブレても0の壁を越えない。両者を場面で使い分けるのは、この違いがあるからだ。

触ってみる生成ボタンを押して正規乱数が積み上がる様子を見てください
生成した z: 0

JavaScriptのMath.random()が返すのは0〜1の一様乱数だけ。その2つを三角関数で組み合わせると、正規分布に従う乱数が2つ生まれる(ボックス・ミュラー法)。均一に散らばった左の点から、右のベル型がせり上がっていくのが見えるだろうか。

実装コードとパフォーマンス最適化

1,000試行×30年分のループはJavaScriptでも数十ミリ秒程度で収まるが、UIをブロックしないようrequestIdleCallbackやWeb Workerへ逃がす選択肢もある。試行回数を増やすほど分布は滑らかになるが、1,000〜2,000回程度で体感上は十分収束する。

触ってみる横軸の u をドラッグして、単独サンプルと対の平均を見比べてください

eˣ を 0〜1 で積分した真値(約 1.72)を、たった1回や2回の評価で当てにいく

単独サンプル f(u)2.270誤差 0.552
対の平均 (u, 1−u)1.734誤差 0.016

評価回数はそのままで、対にするだけ。多数回まわすと推定のばらつきは約 80% 縮む。

u を動かすと、単独サンプル f(u) は1から e(約2.72)まで大きく振れる。ところが u と 1−u を対にして平均すると、その値は真値のすぐそばに貼りついたまま動かない。片方が上振れすれば相方が下振れして誤差を打ち消すからだ。だから評価回数を増やさなくても、推定のばらつきだけが小さくなる。これがアンチセティック変数法である。

触ってみるシードを固定したまま「もう一度生成」を何度か押してください
シード付き乱数
シード値
42
この試行の指紋99e 72c da3 ab7
前回と重なった点

シードが同じなら、新しい点は前回の輪にすべて重なり指紋も一致する。

シード付き乱数のまま生成をくり返すと、新しい点は前回の輪の上へ一粒残らず重なり、指紋もぴたりと一致する。同じ入力なら同じ乱数列が返るので、モンテカルロの試行を丸ごと再現できるわけだ。システム乱数に切り替えると点は毎回どこか別の場所へ散り、同じ配置は二度と戻らない。バグの再現やテストにシードが欠かせないのは、このためだ。

結果の可視化パターン

分布は「ファンチャート」(時間経過に沿って上位/中央/下位のバンドを塗り分けた面グラフ)で見せると直感的に伝わる。数千本の線をそのまま描画するより、パーセンタイル(10/50/90%点など)だけを抽出して帯として描く方が視覚的にも軽い。

触ってみる密度/線の表示を切り替え、本数も変えてみてください
パスの本数
1500本

数千本の線をそのまま重ねると(線で描く)、中央は真っ黒に潰れて密度の違いが読めない。同じデータを通過回数のヒートマップにする(密度で描く)と、パスがどこを濃く通るかが色の濃淡で浮かび上がる。線を1本も捨てずに、むしろ情報量を増やす描き方だ。

AIに投げるプロンプト例

資産形成シミュレーションにモンテカルロ法を組み込みたいです。 以下の要件で実装方針を提案してください。 - 毎年のリターンを対数正規分布の乱数で発生させる - 1,000試行×30年分を計算し、10/50/90パーセンタイルを算出する - 結果をファンチャート(帯グラフ)で可視化する - UIをブロックしないための計算タイミングの工夫も含めて教えてほしい

次はこれ