シミュレーターの方法論

パス、パーセンタイル、高度なツールを理解するための技術的透明性。

最終更新:2026年5月

1. 概要:シミュレーターの役割

My FIRE Simulator は、数千の月次パス(モンテカルロまたは歴史データ)、設定可能な税金と引出戦略で、経済的自立(FIRE)プランを投影します。数値コアは C++ で、ブラウザ内の Web Worker で WebAssembly (WASM) として実行されます。メインプランの数値は計算のために当社サーバーに送信されません

プライバシー・バイ・デザイン:プラン保存、リンク共有、AI アドバイザー利用時のみ、Supabase やプライバシーポリシーに記載のサービスへデータを送信します。

本ページはエンジンのロジックを理解・心の中で検証したいユーザー向けです。専門的な金融アドバイスに代わるものではありません。

2. ブラウザ内アーキテクチャ

メインシミュレーターの技術フロー:

  1. UI(HTML + JavaScript):フォームを読み取り、フェーズ・税金・ポートフォリオを検証し、設定 JSON(store.js)を構築。
  2. Web Workersimulation_worker.js):JSON を受け取り、UI をブロックせず適切な WASM に委譲。
  3. WASM モジュール(C++ からコンパイル):メインシミュレーション、逆目標、ヒートマップ、SWR 探索。
  4. 結果:パーセンタイル、Chart.js グラフ、年次表、相続ヒストグラムをクライアントで描画。

ランディングのクイック計算機(目標を計算)は例外:WASM なしの決定的複利 JavaScript のみで即時応答。

3. メインシミュレーションエンジン

ソース:src-wasm/simulate.cpp → Worker WASM。既定で 5,000 回の独立反復(payload の iterations)、同一設定・異なるランダムパス。

時間粒度

定義されたホライズンで月次に進行。毎月、フェーズに応じた拠出・引出、ポートフォリオリターン、インフレ、手数料、税金、設定時のストレスイベントを適用。

統計出力

In custom mode the engine generates a monthly return using Geometric Brownian Motion (GBM). The random number generator is a Mersenne Twister (mt19937) seeded from hardware (std::random_device):

R_monthly = exp( (μ − σ²/2) × Δt  +  σ × √Δt × Z ) − 1

where:
  Δt = 1/12   (monthly step)
  Z  ~ N(0, 1) (standard normal distribution)
  μ  = expected annual portfolio return
  σ  = annual portfolio volatility

Monthly return — historical mode (block sampling)

In historical mode, each simulated year draws a consecutive block from the JST series. Annual returns are converted to monthly and combined by portfolio weights:

R_month_eq   = (1 + R_annual_eq)^(1/12) − 1
R_month_bond = (1 + R_annual_bond)^(1/12) − 1
R_month_fx   = (1 + R_annual_fx)^(1/12) − 1

R_portfolio = w_stocks × R_month_eq  +  w_bonds × R_month_bond  +  w_crypto × R_crypto_lognormal

If NOT hedged (unhedged currency):
  R_final = (1 + R_portfolio) × (1 + R_month_fx) − 1

Statistical outputs

Interpolated percentile calculation

We do not assume normality of final capital. Percentiles are computed with order statistics directly on the 5,000-result vectors:

index  = (N − 1) × p / 100
lower  = ⌊index⌋
frac   = index − lower

percentile = arr[lower] × (1 − frac) + arr[lower + 1] × frac

(partial sort via std::nth_element, O(N) complexity)

4. データソース:カスタム vs 歴史

カスタム(純モンテカルロ)

正規分布(平均 mu、ボラティリティ sigma)によるランダム月次リターンと一定インフレ。

歴史(ブロックサンプリング)

public/js/data/historical_series.js(Jordà–Schularick–Taylor、現代期 1950–2020)を使用。連続年ブロックで実質リターンを協調。

Available regions: US, Europe (Germany proxy pre-1999), Japan, United Kingdom. Default period: modern era 1950–2020. Panic button: extends to 1870+ including world wars and the Great Depression.

Block sampling algorithm

To preserve autocorrelation between consecutive years, the engine draws blocks of N years (configurable as blockSize, default 5). Each block starts at a random year in the series and advances sequentially, wrapping around:

At block start:
  start_index = random in [0, series_length − 1]

Within block (consecutive years):
  current_index = (start_index + offset) % series_length

When block years exhausted → new random index

Currency hedge (Hedged): when enabled, the fx impact is ignored. Otherwise, return is adjusted: (1 + R_portfolio) × (1 + R_fx) − 1.

5. ポートフォリオ、ボラティリティ、グライドパス

カスタムモードでは UI が Markowitz 型ヒューリスティックで musigma を推定(calculatePortfolioStats)。

グライドパスは月次でウェイトを補間。ストレスイベントは選択年にショックを適用。

Correlationρ
Stocks – Bonds0.05
Stocks – Crypto0.20
Bonds – Crypto0.05

Portfolio variance formula

μ_portfolio = w_s × μ_s + w_b × μ_b + w_c × μ_c

σ²_portfolio = w_s² × σ_s²  +  w_b² × σ_b²  +  w_c² × σ_c²
             + 2 × w_s × w_b × σ_s × σ_b × ρ_sb
             + 2 × w_s × w_c × σ_s × σ_c × ρ_sc
             + 2 × w_b × w_c × σ_b × σ_c × ρ_bc

Glidepath (portfolio transition)

When enabled, stock/bond/crypto weights are linearly interpolated month by month between user-defined control points. At each month t, the engine recalculates mu and sigma with the Markowitz formula above using that month's interpolated weights.

Stress events

Stress events apply a multiplier factor to the return in the chosen month: stressFactor = 1 − drop. A 40% drop equals stressFactor = 0.6, simulating a point-in-time market crash.

6. 税制と資本バケット

動的税制は src-wasm/simulate.cpp にあり、完全な月次ループ(needsDynamicCalc)が必要なときのみ実行されます:固定以外の引出、歴史ソース、税金、累進区分、FIFO。ペイロード:generalCapitaltaxFreeCapitaldeferredCapitaltaxStrategyaverage | fifo)、withdrawalOrdertaxBrackets[]flatTaxRatelatentGainsPct(一般バケットの初期税務コスト基準)。

英語の識別子:本ドキュメントの 内の技術名はすべて英語です。実際の JSON(store.js)と C++ はスペイン語のレガシーキーを使用します(例:ドキュメントの generalCapital = コードの capGeneral)。

3 つの資本バケット

引出順序(withdrawalOrder

平均コスト(taxStrategy: "average"

一般バケットの集計 generalCostBasis。引出時の課税益比率 ratio = (時価 − コスト) / 時価。単一税率または taxBrackets の累進。annualGainYTD は毎年リセット。目標ネットに対する必要総引出を求解。

gain_ratio   = (marketValue − costBasis) / marketValue
taxable_gain = grossWithdrawal × gain_ratio

Flat tax:    tax = taxable_gain × flatTaxRate
Brackets:    For each bracket with (max, rate):
               capacity = bracket.max − annualGainYTD
               chunk    = min(remainingGain, capacity)
               tax     += chunk × bracket.rate

Engine solves gross needed for a target net withdrawal:
  gross = net / (1 − gain_ratio × marginal_rate)

FIFO(taxStrategy: "fifo"

general のみ。deque のロット { cost, units }、月次で更新する indexPrice。FIFO で消費;120 ロット超で最古 12 を統合。

Monthly index price update:
  indexPrice *= (1 + R_portfolio) × (1 − brokerFee)

For each lot consumed (FIFO order):
  lot_marketValue = units × indexPrice
  cost_per_unit   = original_cost / original_units
  gain            = (indexPrice − cost_per_unit) × units_sold
  tax            += apply_brackets(gain)
国別テンプレートは教育用近似です。実際の税法で確認してください(ウォッシュセール、控除などは未モデル)。

7. 引出戦略

withdrawalStrategyfixed(既定)、guytonvpw。計画引出は cashFlowPhases[].val の負の値で渡されます。

固定(fixed

withdrawal = baseWithdrawals[t] × withdrawalInflationFactoradjustFlowsForInflation 時は年次で (1 + 年インフレ) を乗算(古典的インフレ連動引出)。

Guyton–Klinger(guyton

gkThresholdgkAdjustment。初回引出で initialGKWithdrawalRate。毎年 1 月:資本が年初以上のときのみインフレ調整;引出率が初期比の上下限を超えたら withdrawalInflationFactor を増減。

initialWithdrawalRate = plannedAnnualWithdrawal / totalCapital  (1st withdrawal only)

Each January:
  1. Prosperity rule:
     If totalCapital ≥ capitalAtYearStart → apply inflation to spending
     Otherwise → freeze spending (no inflation bump)

  2. Guardrail rules:
     currentRate = annualSpending / totalCapital
     If currentRate > initialRate × (1 + threshold) → factor × (1 − adjustment)  [cut]
     If currentRate < initialRate × (1 − threshold) → factor × (1 + adjustment)  [raise]

VPW(vpw

vpwRate;生存資本に対する年金:pmtRate = vpwRate / (1 − (1+vpwRate)−remainingYears);月次 = totalCapital × pmtRate / 12。税務は isVPWMeta

remainingYears = (totalMonths − t + 1) / 12

If vpwRate > 0:
  pmtRate = vpwRate / (1 − (1 + vpwRate)^(−remainingYears))

If vpwRate = 0:
  pmtRate = 1 / remainingYears

Monthly_withdrawal = totalCapital × pmtRate / 12

8. 高度なツール

「高度なツール」の 3 機能(controllers/simulation.js)はメインフォームを読みません。専用ペイロードで Worker(goalsheatmapswr)を呼び出します。

目標(simulate_goals.cpp

ヒートマップ(simulate_heatmap.cpp

SWR — 安全引出率

監査:simulate_goals.cppsimulate_heatmap.cppsimulation_worker.jshandleSWR)。

9. サーバー側で行われること

現在の UI にメール通知はありません。

10. 限界

Every simulation simplifies reality. It is important to know the model's assumptions:

シミュレーターを開く