Technical Notes: How the Retirement Monte Carlo Calculator Works
Scope and modeling overview
Objective: Estimate the probability that a retirement portfolio sustains withdrawals over a fixed horizon.
Engine: Yearly-step Monte Carlo with independent Gaussian shocks per asset/fund. No serial correlation, fat tails, or regime shifts are modeled in the base version.
Portfolio construction: User-specified funds with weights, expected arithmetic returns, and annualized volatilities. Optionally rebalanced annually to target weights; otherwise, weights drift.
Withdrawals: Applied once per year after the portfolio return is realized for that year. Three withdrawal policies are supported.
Notation
t = 1, 2, …, T: year index; T = time horizon (years)
Vt: portfolio value at end of year t (after withdrawal)
V0: starting portfolio value
wi: target weight of fund i (sum wi = 1)
Ri,t: random return for fund i in year t
μi: expected arithmetic annual return of fund i
σi: annualized standard deviation (volatility) of fund i
N(0,1): standard normal random variable
π: annual inflation rate
Wt: withdrawal amount in year t
W0: initial withdrawal at t = 1 (user input)
1{·}: indicator function
Random return generation
For each fund i and year t:
Ri,t = μi + σi Zi,t, where Zi,t ~ N(0,1), independent across i and t.
Notes:
This is a simple normal model around an arithmetic mean. It does not enforce lognormality or constrain returns; extremely bad/good years can occur with small probability.
If you desire lognormal compounding, you could set gross returns as exp(μ̃i + σi Zi,t) − 1 with μ̃i adjusted to target an arithmetic mean; the current implementation uses the additive normal form for speed and simplicity.
Portfolio evolution with annual rebalance (default = Yes)
Step 1: Compute portfolio gross return in year t from target weights:
Rp,t = Σi wi Ri,tStep 2: Grow the portfolio before withdrawal:
Vt(pre) = Vt−1 × (1 + Rp,t)Step 3: Apply withdrawal policy (see below) to determine Wt
Step 4: Subtract withdrawal:
Vt = max(0, Vt(pre) − Wt)
Portfolio evolution without rebalance (drift allowed)
Initialize sleeves per fund:
Vi,0 = V0 × wi
Each year t:
Step 1: Evolve each sleeve:
Vi,t(pre) = Vi,t−1 × (1 + Ri,t)Step 2: Aggregate:
Vt(pre) = Σi Vi,t(pre)Step 3: Determine Wt via withdrawal policy
Step 4: Subtract withdrawal from sleeves proportionally to their values (preserving relative drift):
If Vt(pre) > 0, set scale factor s = (Vt(pre) − Wt)/Vt(pre); then
Vi,t = max(0, s × Vi,t(pre)) and Vt = Σi Vi,t
If Vt(pre) ≤ 0, set Vt = 0 and terminate the path.
Withdrawal policies
4% Safe Withdrawal Rate (fixed-dollar withdrawal)
Intention: Keep nominal withdrawals constant at the initial amount.
Rule:
Wt = W0 for all tComments:
This is “fixed nominal,” not inflation-indexed in this implementation. If you want classic Bengen-style 4% which is inflation-adjusted, use the Inflation-Adjusted policy and set W0 = 0.04 × V0.
Inflation-Adjusted withdrawal
Intention: Maintain purchasing power by increasing the withdrawal by inflation each year.
Rule:
W1 = W0
Wt = Wt−1 × (1 + π), for t ≥ 2Comments:
π is the user’s long-run inflation assumption (constant). You can test sensitivity by varying π.
Guardrail strategy (caps and portfolio triggers)
Intention: Allow spending to grow, but cap growth and respond to large portfolio moves with modest adjustments.
Implementation (simple guardrail):
Annual increase cap:
cap = min(π, 0.05)
W1 = W0
Wt(base) = min(Wt−1 × (1 + cap), 1.75 × W0)Portfolio trigger adjustments relative to starting value:
If Vt(pre) < 0.80 × V0, then Wt = 0.90 × Wt(base) (−10% cut)
Else if Vt(pre) > 1.20 × V0, then Wt = 1.05 × Wt(base) (+5% bump)
Else Wt = Wt(base)
Comments:
This is a simplified rule-of-thumb guardrail. It is not the full Guyton-Klinger rule set (which includes decision rules around inflation adjustments and capital preservation triggers). The chosen parameters are illustrative and can be tuned.
Order of operations per year t
Generate returns Ri,t and compute either Rp,t (rebalance) or sleeve evolutions (no rebalance).
Compute Vt(pre).
Determine Wt using the selected policy (note: Vt(pre) is used for guardrail triggers).
Set Vt = max(0, Vt(pre) − Wt).
If Vt = 0, record depletion year and stop the path; otherwise continue to t+1.
Success criterion
A path is a success if Vt > 0 for all t = 1..T. Equivalently, the portfolio does not deplete before or at T.
Success rate = (number of successful paths) / (total simulations).
Summary statistics
Final values: {VT(s)} across simulations s = 1..N.
Median: 50th percentile of final values.
Percentiles: P10 and P90 as 10th and 90th percentiles.
Mean (average): Arithmetic mean of final values.
Expected shortfall (worst 10% average) [optional metric included in some versions]:
ES10 = average of the lowest 10% of final values.Depletion year: min year t at which Vt = 0 (if any). Report earliest depletion across failed paths.
Time-series summaries for charting
For each year t, compute:
Cross-sectional average of Vt across surviving and failed (0-valued) paths
Cross-sectional median of Vt
Normalize by V0 to display as multiples of starting value:
AvgMultiple(t) = (average Vt)/V0
MedianMultiple(t) = (median Vt)/V0
Modeling assumptions and implications
Independence and normality: Returns are independent across years and assets (no correlations modeled between funds in the base version) and normally distributed. This can understate tail risks and sequence-of-returns clustering.
Arithmetic means: Using arithmetic μ with additive Gaussian shocks means expected compound growth over multiple years is roughly μ − ½σ2 in log terms; higher σ lowers geometric growth relative to arithmetic assumptions.
No fees/taxes/slippage: You may haircut μ or increase W0 to approximate these.
Rebalancing: When enabled, portfolio return is a weighted mixture each year, implicitly rebalancing continuously at yearly boundaries. When disabled, sleeves drift and withdrawals come pro-rata.
Practical calibration tips
Pick μ and σ from long-run sources (fund factsheets, research estimates). Ensure σ is annualized.
If you prefer correlations, approximate with a single-portfolio return μp and σp derived from your covariance matrix, and input it as one “fund.”
For more conservative planning, lower μ and/or raise σ, or switch to the inflation-adjusted policy and test lower W0.
Algorithmic complexity
For N simulations and T years with K funds:
Rebalance mode: O(N × T × K) to compute portfolio returns.
Drift mode: O(N × T × K) for sleeve updates and proportional withdrawals.
Typical interactive settings (N up to ~5,000, T up to ~40, K up to 6) run quickly in-browser.
Potential extensions (not currently in base version)
Correlated multivariate normal shocks using a Cholesky of a K×K covariance matrix.
Fat-tailed innovations (e.g., Student-t) or regime-switching volatility.
Time-varying inflation, fee drag, or tax-aware withdrawals (tax lot logic, RMDs).
Sequence-aware guardrails (Guyton-Klinger’s decision rules: inflation skip, capital preservation, prosperity rules with bands on withdrawal rate).
Glidepaths (changing weights by year).
Lognormal compounding returns to bound −100% and avoid additive normal pathologies in extreme σ scenarios.
Validation and sanity checks
If σ = 0 for all funds, results reduce to deterministic compounding with fixed mean and specified withdrawals.
If W0 = 0, success is trivially 100% and final value grows per compounding assumptions.
With rebalance on and K=1, the rebalance/nost-rebalance paths are identical.
In short, the calculator simulates many plausible return histories around your inputs, applies a chosen spending rule each year, and tracks whether the portfolio survives to the horizon. The simplified yet transparent formulas make it easy to understand and audit how each assumption affects sustainability.