QuantCalc Methodology
Technical Documentation v1.7 · Last updated: September 2026
QuantCalc is a web-based Monte Carlo retirement engine. It simulates a plan in monthly steps across thousands of market scenarios using log-normal returns, Cholesky-correlated assets, and forward-looking capital market expectations from published sources. The engine models stochastic inflation, federal and 51-jurisdiction state taxes, RMDs and IRMAA (a separate bridge planner prices the ACA subsidy cliff), then reports the probability the portfolio sustains retirement. The simulation runs on QuantCalc’s servers from the inputs you enter: no account is needed, and the inputs are used for the run and not stored (what is sent and logged). Details at quantcalc.app.
Looking for the calculator itself? Try the free Monte Carlo simulation calculator →
Prefer plain English on the tax side? See How QuantCalc models retirement taxes — a short FAQ on Social Security taxation, IRMAA, state tax, capital gains, Roth conversions, RMDs and the ACA cliff.
- Introduction
- Monte Carlo Overview
- Asset Return Modeling
- Generating Correlated Returns
- Capital Market Expectations
- Portfolio Return Calculation
- Cash Flow Modeling
- Simulation Execution
- Success Rate and Statistics
- Quasi-Monte Carlo Methods
- Optimization Problem Formulation
- Objective Functions
- Constraints
- Sequential Quadratic Programming
- Multi-Period Optimization
- Initial Point Selection
- Convergence and Termination
- Practical Considerations
- Gompertz Gender-Specific Mortality
- Fat-Tail Returns & Regime Switching
- Stochastic Inflation
- Per-Asset Inflation Coupling (β)
- State Tax, Roth, QCD & IRMAA
- Randomized QMC & Wilson CI
- Historical Sequences · Near/Long-Term CME
- Withdrawal Rules
1. Introduction
QuantCalc uses Monte Carlo simulation to model the uncertainty inherent in retirement planning. Unlike deterministic calculators that assume fixed returns, Monte Carlo methods generate thousands of possible future scenarios based on the statistical properties of financial markets.
The fundamental question we answer is: Given your savings, contributions, spending needs, and asset allocation, what is the probability that your portfolio will sustain your retirement?
Real vs nominal dollars
QuantCalc separates three distinct dollar concepts so that the math behind every figure is unambiguous:
- What you enter is in today's dollars. Monthly contribution, annual spending, Social Security, life-event amounts — all interpreted as the purchasing power those amounts have right now. You don't need to project them forward yourself. In Tax-Aware Mode annual spending is what you spend after income tax; otherwise the engine does not model tax and the spending figure is the total withdrawal.
- What the engine simulates is nominal. The published Capital Market Expectations (CME) used for asset returns are nominal (before inflation). Internally, the engine inflates your cash flows forward at your inflation rate so that nominal flows meet nominal returns — the arithmetically consistent way to model purchasing-power growth.
- What you see is deflated back to today's dollars. All percentile bands, projection-chart values, sample paths, and yearly statistics are divided by the cumulative inflation factor at each point so the chart reads in today's purchasing power. If you turn off "adjust for inflation," the engine treats your inputs as fixed nominal amounts and skips the deflation step.
Worked example: $100,000 starting balance, 7% nominal return, 3% inflation, no cash flows, 30-year horizon. Internally the engine grows the portfolio to $100,000 × 1.07³⁰ ≈ $761,225 in nominal dollars. Before display, it divides by 1.03³⁰ ≈ 2.427 to give ≈ $313,600 in today's purchasing power — the figure you'll see on the chart. The real return that is actually visible is 1.07 / 1.03 − 1 ≈ 3.9% a year (roughly the 7% nominal minus 3% inflation). The inflation rate you enter is an annual rate, as the Bureau of Labor Statistics reports CPI inflation as a 12-month change, so the engine compounds it monthly at (1 + i)1/12. After 12 months prices are exactly (1 + i) higher. It does not use i/12 a month, which would turn 3% into about 3.04% a year.
For stochastic-inflation models (AR(1), regime-switching, AR(1) multi-category), each simulation path has its own inflation trajectory, and each path is deflated by its own per-path cumulative CPI factor before percentiles are computed. The deflation is correct path-by-path, not just on average.
Cash-flow timing convention
The simulation runs in monthly steps. Cash flows you enter as annual amounts are divided by 12 and applied at the end of each month, after that month's growth. So a $12,000/year contribution becomes 12 separate $1,000 cash flows: the first lands at the end of month 1 and earns 11 more months of growth before "year 1" on the chart; the last lands at the end of month 12 and earns no further growth in year 1. The effective center of mass of each year's cash flow is roughly mid-year.
This is the institutional convention — it matches how paychecks, bills, and retirement withdrawals actually move through real life. It is not the convention used by typical textbook PMT/FV/PV formulas in Excel or Google Sheets, which assume one annual lump sum either at year-start (annuity due) or year-end (ordinary annuity). When you compare a QuantCalc result against a hand-built annual spreadsheet, the gap is real and predictable:
| Scenario | QuantCalc (monthly) | EOY annual spreadsheet | Gap |
|---|---|---|---|
| $1,000/month contribution, 30 years, 7% nominal | $1,169,452 | $1,133,529 | +3.17% (engine higher; monthly contributions earn more growth) |
| 4% rule on $1M, 30 years, 4% real return | $502,315 leftover | $551,320 leftover | −8.9% (engine lower; monthly withdrawals leave the account earlier) |
| Drawdown to zero: $100k, 10y, 7% | Supports $13,800/yr | Supports $14,237/yr | $437/yr ≈ half a year of growth on $100k |
If you build a verification spreadsheet to sanity-check QuantCalc, you'll see these gaps. They are not arithmetic errors in either model — both are internally consistent. They reflect the difference between annual-lump and monthly-uniform cash-flow timing. To match a QuantCalc number with an annual spreadsheet exactly, your spreadsheet would need to compound monthly and place 1/12 of the annual cash flow at the end of every month.
2. Monte Carlo Simulation Overview
Monte Carlo simulation is a computational technique that uses repeated random sampling to obtain numerical results. For retirement planning, we simulate many possible "paths" that a portfolio might take over time.
The Basic Algorithm
For each simulation s = 1, 2, ..., N:
Initialize portfolio value V₀
For each time period t = 1, 2, ..., T:
Generate random asset returns
Update portfolio value based on returns and cash flows
Record portfolio value Vₜ
Record final outcome (success or failure)
Calculate statistics across all N simulations
With N = 1,000 to 10,000 simulations, we obtain a distribution of outcomes that reflects the range of possibilities given market uncertainty.
3. Asset Return Modeling
Log-Normal Returns
Financial returns are commonly modeled as log-normally distributed. If $P_t$ is the price of an asset at time $t$, the continuously compounded return over one period is:
We assume these log-returns follow a normal distribution:
where $\mu$ is the expected (mean) return per period and $\sigma$ is the volatility (standard deviation) per period.
Converting Annual to Monthly Parameters
Capital Market Expectations are typically quoted as annual figures. For monthly simulation:
The division by $\sqrt{12}$ for volatility follows from the property that variance scales linearly with time for independent returns.
Growth Factor
Given a monthly return $r_t$, the portfolio growth factor is:
4. Generating Correlated Returns
The Challenge
Real asset classes don't move independently. Stocks tend to move together, bonds often move inversely to stocks during crises, etc. We must generate returns that respect these correlations.
Correlation Matrix
For $n$ asset classes, the correlation matrix $\mathbf{R}$ is an $n \times n$ symmetric matrix where $R_{ij}$ is the correlation between assets $i$ and $j$:
Covariance Matrix
The covariance matrix $\mathbf{\Sigma}$ combines volatilities and correlations:
Or in matrix form: $\mathbf{\Sigma} = \mathbf{D} \cdot \mathbf{R} \cdot \mathbf{D}$, where $\mathbf{D} = \text{diag}(\sigma_1, \sigma_2, \ldots, \sigma_n)$.
Cholesky Decomposition
To generate correlated random variables, we use the Cholesky decomposition. Any positive-definite covariance matrix can be factored as:
where $\mathbf{L}$ is a lower triangular matrix.
- Generate $n$ independent standard normal variables: $\mathbf{z} = (z_1, z_2, \ldots, z_n)^T$ where $z_i \sim \mathcal{N}(0, 1)$
- Transform using Cholesky factor: $\mathbf{x} = \mathbf{L} \cdot \mathbf{z}$
- The resulting vector $\mathbf{x}$ has covariance matrix $\mathbf{\Sigma}$
- Add means to get final returns: $r_i = \mu_i + x_i$
5. Capital Market Expectations
QuantCalc references return assumptions derived from publicly available publications by major asset managers. QuantCalc is not affiliated with any of these firms. The data is sourced from publicly available reports, press releases, and financial media coverage.
Capital Market Expectations (CME) are forward-looking estimates of expected returns, volatilities, and correlations for each asset class. Major asset managers publish CMEs annually, and these forecasts are widely reported in public financial media.
QuantCalc's Asset Classes
| Asset Class | Description |
|---|---|
| US Stocks | Large-cap US equities (S&P 500-like) |
| International Stocks | Developed market ex-US equities |
| Bonds | Investment-grade fixed income |
| Real Estate | REITs / Real estate securities |
| Cash | Money market / Short-term treasuries |
Source mapping: Each firm publishes forecasts at varying levels of granularity. Where a source provides separate forecasts for US Large Cap, Mid Cap, and Small Cap equities, QuantCalc uses the Large Cap figure for "US Stocks" as it most closely represents the S&P 500 universe. Similarly, "Bonds" uses investment-grade aggregate or core bond forecasts, and "International Stocks" uses developed-market ex-US figures. For exact sub-category details, consult each firm's published report linked below.
Volatility estimates: Most firms do not publicly publish volatility estimates for exactly QuantCalc's 5 asset classes. Where a source publishes volatility data (e.g., J.P. Morgan's LTCMA includes volatility estimates in its full report, checked 2026-09-10), those figures inform our estimates. For other sources, volatilities are representative estimates based on long-term historical realized volatility for each asset class. Typical ranges: US equities 15-17%, international equities 17.5-20%, bonds 5-6.5%, real estate 13-16%, cash ~1%.
Correlation estimates: Published correlation matrices vary by source and methodology. J.P. Morgan's LTCMA includes a comprehensive correlation matrix in their full report. For sources that do not publish complete correlation matrices for these specific asset classes, QuantCalc uses representative estimates consistent with long-term empirical relationships (e.g., US/Intl equity correlation of 0.75-0.85, equity/bond correlation of 0.05-0.15, as documented in Dimson, Marsh & Staunton and other academic research). All correlation matrices are verified to be positive semi-definite for valid Cholesky decomposition.
Real vs. nominal returns: Most sources publish nominal returns (before adjusting for inflation). GMO is a notable exception — it publishes real returns (after inflation); as of 2025-12-31 its US large-cap forecast is −6.0% real (gmo.com, checked 2026-09-10). QuantCalc converts GMO's real returns to nominal by adding an assumed 2.5% long-term inflation rate, as noted in the GMO source description below. This enables consistent comparison across all sources.
Arithmetic vs. geometric return conventions: Published expected returns come in two conventions. Forward-looking firm forecasts (BlackRock, J.P. Morgan, Vanguard, GMO, Schwab, Invesco — each firm's own publication is linked in the source list below, and the set is restated in Morningstar's 2026 roundup, checked 2026-09-10) are geometric (compound annual) expectations — the long-run growth rate a buy-and-hold investor would experience. Long-run historical averages, by contrast, are conventionally quoted as arithmetic means of annual returns, which for a volatile asset overstate the achievable compound growth rate by approximately σ²/2 (about 1.9 percentage points for an equity series with 19.5% volatility). QuantCalc tags every source with its convention and converts arithmetic inputs to geometric (μgeometric ≈ μarithmetic − σ²/2) before they enter the lognormal return-generation step, so the Historical source no longer compounds an arithmetic mean as if it were a growth rate — a subtle convention mismatch that roughly doubled long-horizon Historical wealth projections before being corrected in May 2026. All sources therefore simulate on a consistent geometric basis, and Historical-source results are directly comparable with the forward-looking forecasts.
Independent Source Selection
QuantCalc allows you to select separate sources for each of the three CME components:
- Return Expectations: The expected annual return for each asset class. All 8 sources are available since every source publishes return estimates.
- Correlation Matrix: The pairwise correlations between asset classes. Only sources that publish verified correlation data are available (currently JPMorgan LTCMA, Historical, and Equilibrium). A direct API request can still name a source that publishes no correlation matrix, or no volatilities. For that component the engine uses the Historical estimate, not a matrix of zeros, which would treat every asset class as independent and understate risk. The response names the source that actually ran each component (
cmeSourcesUsed) and flags the substitution. - Volatility: The expected annual standard deviation of returns. Only sources that publish volatility estimates are available (currently JPMorgan, Vanguard, Historical, and Equilibrium).
This separation is important because different firms have different strengths. For example, you might prefer GMO's bearish return outlook combined with JPMorgan's well-documented correlation structure and historical volatility estimates. The backend automatically recomputes the Cholesky decomposition of the correlation matrix whenever sources are mixed, ensuring mathematically consistent correlated return generation.
By default, QuantCalc uses JPMorgan for returns and correlations (their LTCMA is the most comprehensive publicly available dataset) and Historical for volatility (long-term realized volatility is a robust baseline).
Near-Term and Long-Term Assumptions PRO
A single CME set applies one view of the world to the entire horizon, which is not how the published sources are written. GMO's headline numbers are a 7-year forecast; BlackRock's and Vanguard's are 10-year; JPMorgan's and Schwab's are explicitly long-term. Applying a seven-year forecast unchanged across thirty years is arguably the misuse, not the alternative.
QuantCalc therefore accepts an optional second set: a near-term source governs the first N years and the long-term set governs the remainder. Both slots take real published assumptions — no near-term view is interpolated or synthesised, because QuantCalc does not produce its own forecasts and manufacturing one here would break that. Only sources whose own published horizon is short are offered in the near-term slot, and the default length follows that source's stated horizon (GMO defaults to 7 years, BlackRock and Vanguard to 10), so a forecast is applied over the period it was written for. Each set keeps its own returns, volatilities and correlation matrix, and the engine switches between two fully-prepared sets at the boundary month.
The split is refused — visibly, with the reason reported in the results panel — in four cases: when regime switching is active, because its volatility correction is computed from a single set and the near-term months would otherwise silently carry long-term volatilities; when the return model is the bootstrap or historical sequences, which read no capital market expectations at all; when the named source is not one we carry; and when the requested length falls outside 1–50 years. A near-term period longer than the plan itself is treated as a single set rather than pretending there is a second phase.
Example CME Data (Illustrative — BlackRock, as of Sep 2025)
| Asset | Expected Return | Volatility |
|---|---|---|
| US Stocks | 5.2% | 16.5% |
| Intl Stocks | 7.2% | 17.5% |
| Bonds | 4.1% | 5.5% |
| Real Estate | 6.8% | 14.0% |
| Cash | 3.1% | 1.0% |
CME Sources
QuantCalc references return assumptions derived from publicly available publications by major asset managers. QuantCalc is not affiliated with any of these firms. The data is sourced from publicly available reports, press releases, and financial media coverage.
QuantCalc references Capital Market Expectations from six publicly available sources, each with distinct methodological approaches:
BlackRock Investment Institute
Source: BlackRock return assumptions as reported in Morningstar's annual Capital Market Expectations survey — Christine Benz, Experts Forecast Stock and Bond Returns: 2026 Edition, morningstar.com, checked 2026-09-10. BlackRock publishes the underlying assumptions at blackrock.com.
Last Updated: September 2025 (data as of Sep 30, 2025)
BlackRock's CMAs use a building-block approach combining current yields, expected growth, and valuation adjustments. Their methodology emphasizes regime-based analysis and incorporates macro factors including demographic trends, productivity growth, and monetary policy normalization. 10-year nominal return estimates: US equity 5.2%, US aggregate bonds 4.1%, as of Sept. 30, 2025 — as published in Morningstar's 2026 roundup and on blackrock.com, checked 2026-09-10.
J.P. Morgan Asset Management
Source: As published in J.P. Morgan's publicly available Long-Term Capital Market Assumptions (Annual). Available at am.jpmorgan.com and via public press releases.
Last Updated: November 2025
J.P. Morgan's LTCMAs provide 10-15 year forecasts using equilibrium models adjusted for current valuations. Their framework integrates global macro research with quantitative factor models, producing return estimates that account for mean reversion in valuations and yields.
Vanguard Investment Strategy Group
Source: As published in Vanguard's publicly available Economic and Market Outlook (Annual). Available at vanguard.com.
Last Updated: December 2025
Vanguard employs the Vanguard Capital Markets Model (VCMM), a proprietary Monte Carlo simulation tool. VCMM generates 10,000 simulations based on historical relationships, current market conditions, and forward-looking yield curves to produce return distributions rather than point estimates.
GMO (Grantham, Mayo, Van Otterloo)
Source: GMO's 7-Year Asset Class Forecast (quarterly). The edition used here is as of 2025-12-31: US large cap −6.0% real, US bonds 1.3% real, published at gmo.com and restated in Morningstar's 2026 roundup, checked 2026-09-10. The GMO research library is at gmo.com/americas/research-library.
Last Updated: January 2026 (Q4 2025 data)
GMO's forecasts are explicitly mean-reverting, assuming asset prices return to historical fair value over a 7-year horizon. Their methodology adjusts current prices for profit margins, valuations (P/E, Shiller CAPE), and dividend yields relative to long-term averages, producing forecasts that often diverge significantly from consensus.
Important note on return type: GMO publishes real returns (after inflation), while all other sources in QuantCalc publish nominal returns. To enable apples-to-apples comparison, GMO's real return forecasts have been converted to nominal by adding an assumed 2.5% long-term inflation rate. For example, GMO's published -6.0% real return for US equities (gmo.com, as of 2025-12-31, checked 2026-09-10) becomes -3.5% nominal. This conversion is approximate; actual future inflation may differ. Users should be aware that GMO's forecasts are notably more pessimistic than other sources, reflecting their mean-reversion methodology and current high equity valuations.
Charles Schwab
Source: As published in Schwab's publicly available Long-Term Capital Market Expectations. Available at schwab.com/learn.
Last Updated: January 2026
Schwab's CMEs provide 10-year forward-looking return estimates derived from their proprietary framework. Their 2026 forecasts project 5.9% for US large cap equities and 4.8% for bonds, as of Oct. 31, 2025 — as published on schwab.com and restated in Morningstar's 2026 roundup, checked 2026-09-10. Published on their consumer-facing Learn page, these estimates are widely cited in public financial media and press releases.
Invesco
Source: Invesco's publicly available Capital Market Assumptions, at invesco.com. The set QuantCalc ships is the December 2025 edition; the edition on that page when checked 2026-09-10 is Q1 2026, at 5.1% for US large cap and 5.0% for US aggregate bonds.
Last Updated: December 2025
Invesco's Capital Market Assumptions provide long-term return forecasts across a broad range of asset classes. Their methodology combines macroeconomic analysis with valuation-driven models, producing estimates that are published in publicly downloadable PDF reports across multiple regional pages.
Historical Bootstrap PRO
As an alternative to the parametric CME framework above, PRO users can switch to a historical bootstrap return model that resamples actual monthly history instead of drawing from a fitted log-normal distribution. Block lengths follow a geometric distribution averaging 24 months (a Politis–Romano stationary block bootstrap), and all five asset classes are resampled jointly — the same historical month drives every asset at once — so real correlation, volatility clustering, and regime sequencing carry through directly rather than being approximated.
The dataset spans July 1990 through May 2026 (431 months): US and developed ex-US market returns and the listed real-estate industry portfolio (REIT-dominated in the modern era) from the Ken French Data Library, par-bond returns derived from FRED's 10-year constant-maturity yield, and cash returns from FRED's 3-month T-bill yield. Two notes on what those series are. The real-estate series is an industry portfolio, so it includes real-estate operating companies as well as REITs and runs at about 26% annualized volatility against roughly 19–20% for a REIT index — real-estate risk is overstated relative to a pure REIT allocation. And returns are nominal: they are deflated by a CPI path drawn from QuantCalc's inflation model, not by the inflation that actually accompanied each resampled month (see the coupling note below).
Window bias — read bootstrap success rates as an optimistic bound. The 1990 start excludes the 1970s stagflation era, and the direction of that omission is one-sided. Within this sample a 60/40 US-equity/bond mix compounded about 8.7%/yr nominal, US equity 11.16%/yr and bonds 5.04%/yr — and the bond figure is the average of two very different halves, 7.67% annualized in 1990–2007 against 2.69% in 2008–2026, so roughly a third of the window is the tail of a bond bull market that cannot repeat from today's yields. Every forward-looking capital market expectation in the parametric model is materially lower. Switching a plan from parametric to Historical Bootstrap therefore tends to raise its success rate for reasons that are a property of the window, not evidence about the future. A related caveat on precision: 431 months at a 24-month mean block length is only about 18 effectively independent segments, so the Wilson interval on the success rate (Section 26) covers sampling error within the resampled distribution and captures none of that window uncertainty — which dominates here.
Fat tails and regime clustering are already embedded in the resampled history, so those parametric add-ons don't apply here. Return–inflation coupling is a different case: because the resampled series is nominal and the CPI path is drawn independently, the coupling is absent under this model rather than embedded — the historical link between a month's returns and its inflation is not carried through. The portfolio optimizer and the source-comparison view are parametric-only and reject this model rather than substituting one silently: optimizing an allocation against a resample of a single 36-year window maximizes performance inside that window, and comparing capital market expectations is meaningless for a model that does not read them. Sobol scrambling is likewise inert here — the resampler draws historical months directly, so there is no low-discrepancy sequence to rotate, and the run uses plain pseudo-random draws (the results panel reports which sampler actually ran).
Historical Sequences PRO
Where the bootstrap above resamples history in blocks, this model replays it. Simulation k is the actual run of months beginning at start month k and continuing in order, so sequence-of-returns risk is whatever it really was: 1929–32, 1966–82 and 2008 arrive in their true order, at their true length, with their true recoveries, rather than being reassembled from geometric blocks.
That requires a longer dataset than the bootstrap uses. The bootstrap panel begins in July 1990 because Ken French's developed ex-US series starts there and the listed real-estate series only reaches 1972 — fine for resampling short runs, useless for contiguous 30-year sequences: over 1990–2026 a 30-year horizon admits only about 83 heavily overlapping start months, roughly 7 distinct start years, and excludes every period that makes historical simulation informative in the first place. This model therefore runs on a separate panel that trades breadth for length: 1,178 contiguous months, August 1926 through September 2024, giving 819 distinct start months at a 30-year horizon and 699 at 40 years.
The price of that length is asset coverage. The panel carries three series — US equity and cash from the Ken French Data Library (market return including the risk-free rate, and the one-month Treasury bill respectively), and a par-bond total return derived from Shiller's monthly long-term yield by the same approximation used for the bootstrap panel's bond series. International equity and real estate are absent, not proxied: no public monthly series for either reaches 1926, and substituting an invented stand-in would fabricate the very data this model exists to respect. A five-asset allocation is folded onto the three — international and real estate join US equity, because both are equity-risk assets and dropping their weight would silently run a smaller portfolio than the client holds — and the results panel states that the folding happened.
Read these success rates against forecasts, not as forecasts. This model scores higher than the parametric one, and not because the plan is safer. Realized US equity compounded at 10.21%/yr nominal across this window; every forward-looking capital market expectation on offer here sits well below that — the J.P. Morgan Long-Term Capital Market Assumptions figure carried in this app for US equity is 6.7%. That gap is roughly three and a half points a year, which over a thirty-year horizon is the whole difference. The results panel reports the realized figure next to the number for exactly this reason. The same one-sided caution that applies to the bootstrap window applies here with a longer lever.
A second precision caveat: the 819 start months of a 30-year horizon overlap almost entirely, so the effective independent sample is one or two non-overlapping periods, not 819. The panel therefore reports the count of distinct start months rather than a path count — quoting “10,000 paths” would imply 10,000 independent draws from a distribution when nothing is being drawn at all. For the same reason the Wilson interval of Section 26 is not meaningful under this model, and Sobol sampling is inert: there is no low-discrepancy sequence to rotate, because nothing is sampled.
As with the bootstrap, the parametric overlays are disabled here — real history already contains its own regimes, fat tails and crashes, so layering synthetic ones on top would double-count them. An inline custom CME forces a downgrade to the parametric engine (the panel is a fixed three-asset set with no correspondence to an arbitrary roster), and the response echoes the model that actually ran rather than the one requested.
6. Portfolio Return Calculation
Weighted Portfolio Return
Given asset allocation weights $w_1, w_2, \ldots, w_n$ (summing to 1) and individual asset returns $r_1, r_2, \ldots, r_n$, the portfolio return is:
Portfolio Statistics
The expected portfolio return: $\mathbb{E}[r_p] = \sum_{i=1}^{n} w_i \cdot \mu_i$
The portfolio variance:
7. Cash Flow Modeling
Time Periods
QuantCalc simulates on a monthly basis from current age to end of plan. Total months:
Cash Flow Components
At each month $t$, the net cash flow $C_t$ consists of:
Pre-Retirement Phase
Before retirement (month $t < t_{\text{retire}}$): $C_t = M_{\text{contribution}} \times I_t$
Post-Retirement Phase
After retirement (month $t \geq t_{\text{retire}}$):
Income tax does not appear in $C_t$: the standard engine does not model it, so $M_{\text{withdrawal}}$ is a total withdrawal. Tax-Aware Mode (Part III) replaces this identity with $W_t - \text{tax}_t = S_t$.
Social Security and Pension
Social Security begins at the specified claiming age:
Supplemental income streams are opt-in. Social Security and pension income are each zero unless you enter an amount — the engine does not assume a benefit on your behalf. A simulation with no Social Security and no pension entered draws spending entirely from the portfolio, which is the conservative baseline for an early-retirement or FIRE plan. To include a benefit, enter its annual amount (today's dollars) and the age it begins; it is then inflated forward like every other cash flow.
Inflation Adjustment
Cash flows are adjusted for inflation to maintain purchasing power:
8. Simulation Execution
Portfolio Evolution
The portfolio value evolves according to:
where $V_t$ is portfolio value, $G_t = 1 + r_{p,t}$ is the growth factor, and $C_t$ is net cash flow.
Handling Ruin
If the portfolio value goes negative, it is floored at zero:
Once $V_t = 0$ during retirement, the simulation is marked as a "failure" (ruin).
9. Success Rate and Statistics
Success Rate
A simulation is "successful" if the portfolio never hits zero during retirement:
Percentiles
- 10th percentile: "Pessimistic" outcome (90% did better)
- 50th percentile (median): "Typical" outcome
- 90th percentile: "Optimistic" outcome
Confidence Interval
The standard error of the success rate estimate is:
For $p = 0.95$ and $N = 1000$: $SE \approx 0.007$, so the 95% CI is approximately $\pm 1.4\%$.
10. Quasi-Monte Carlo Methods
Sobol Sequences
Standard Monte Carlo uses pseudo-random numbers which can exhibit clustering. Quasi-Monte Carlo (QMC) methods use deterministic low-discrepancy sequences designed to fill the sample space more uniformly.
QuantCalc uses Sobol sequences, which provide:
- Deterministic, reproducible results
- Better space coverage than pseudo-random
- Faster convergence: $O(1/N)$ vs $O(1/\sqrt{N})$
Transformation to Normal
Sobol points $u \in [0,1]$ are transformed to standard normal via the inverse CDF:
11. Optimization Problem Formulation
QuantCalc's portfolio optimizer finds the asset allocation that maximizes retirement success probability (or other objectives) subject to real-world constraints. Unlike simple mean-variance optimization, our approach directly optimizes the Monte Carlo simulation output—accounting for sequence-of-returns risk, cash flows, and the full distribution of outcomes.
General Form
Decision Variables
Single-period: $\mathbf{w} = (w_{\text{US}}, w_{\text{Intl}}, w_{\text{Bonds}}, w_{\text{RE}}, w_{\text{Cash}})^T$ — 5 variables
Multi-period (glide path): For $k$ periods, we optimize $k \times n$ weights:
| Periods | Variables | Description |
|---|---|---|
| 1 | 5 | Static allocation |
| 2 | 10 | Two-phase (accumulation/retirement) |
| 3 | 15 | Three-phase glide path |
12. Objective Functions
Maximize Success Rate
Maximize Median Final Value
13. Constraints
Equality: For each period $p$: $\sum_{i=1}^{n} w_{p,i} = 1$
Bounds: $0 \leq w_{p,i} \leq 1$ for all weights (no short selling)
14. Sequential Quadratic Programming (SLSQP)
We use SLSQP because it handles exactly the constraint structure we need: equality constraints (weights sum to 1), bound constraints (0–100% per asset), and a smooth but simulation-derived objective.
The Quadratic Subproblem
At each iteration $k$:
Gradient Estimation
We estimate gradients numerically using finite differences:
A fixed random seed is used for all objective evaluations to eliminate stochastic noise.
BFGS Hessian Update
15. Multi-Period Optimization
For $k$ periods, we flatten the weight matrix into a single decision vector:
| Periods | Variables | Equality Constraints | Gradient Evaluations |
|---|---|---|---|
| 1 | 5 | 1 | 6 |
| 2 | 10 | 2 | 11 |
| 3 | 15 | 3 | 16 |
16. Initial Point Selection
Strategy 1: User's current allocation extended to all periods
Strategy 2: Balanced portfolio: $w_{p,i}^{(0)} = 1/n$ (20% each)
Strategy 3: Age-based heuristic: $w_{\text{stocks}}^{(0)} = 1 - \text{age}/100$
17. Convergence and Termination
The optimization terminates when any condition is met:
- Gradient tolerance: $\|\nabla f\| < 10^{-4}$
- Step tolerance: $\|\mathbf{w}^{(k+1)} - \mathbf{w}^{(k)}\| < 10^{-6}$
- Function tolerance: $|f^{(k+1)} - f^{(k)}| < 10^{-6}$
- Maximum iterations: $k > 100$
18. Practical Considerations
Simulation Noise
A fixed random seed is used for all objective evaluations within the optimization loop. The final optimized allocation is then validated with a fresh simulation run.
Computational Cost
Flat Regions
When success rate is very high (>95%) or very low (<5%), the objective surface becomes flat. Switching to median value objective can help.
19. Tax-Aware Withdrawal Optimization
QuantCalc's Tax-Aware Mode chooses the withdrawal policy across traditional, Roth and taxable accounts that minimizes lifetime tax cost. It simulates a set of whole-retirement candidates on the same market paths — traditional first, taxable first, filling the standard deduction or the top of the 10%, 12%, 22% or 24% bracket (or the first Medicare surcharge tier) from traditional each year before touching taxable and Roth, the same bracket and tier fills completed with a Roth conversion for any room the year's withdrawals leave (from retirement until the year before required distributions begin), and a "convert to the 10% or 12% top, then spend traditional first" pair — and recommends the one with the lowest present value of lifetime tax: every year's federal, state, Medicare-surcharge and penalty cost discounted at the portfolio's own return on that path, plus any spending the portfolio could no longer fund on paths where it runs out, plus the tax still owed on any traditional balance left at the end, valued as an heir drawing it evenly over ten years as a single filer with no other income in the plan's state. A single-year grid search that minimizes only that year’s bill is not among them: it was removed from the search in September 2026 because it lost to drawing traditional first on every realistic long plan we tested. It survives only as a forced comparison in the withdrawal-order study, which reports how often it would have helped or backfired. Spending is after tax: in every retirement year the engine withdraws enough to fund the year's spending plus that year's whole tax bill, and pays the bill from the accounts it drew — so the success rate, the ending balances and the recommendation all depend on your state and your withdrawal order. Because drawing traditional first is itself one of the candidates, the recommended policy can only tie it or beat it; the reported saving is the median, over paths, of the per-path present-value difference. A winner whose median saving is under $1,000 is treated as not a real recommendation and traditional-first is used instead, so the reported saving is then exactly $0; a bracket- or tier-fill candidate that recommends a Roth conversion is held to the same $1,000 bar against its own non-converting twin (the same fill with no conversion), so a household is never shown a multi-year conversion schedule that only edges out doing nothing by a few dollars. If you enter a Roth-conversion plan of your own, the conversion candidates are not used: every candidate order is simulated around your plan and the results say so. The pre-Medicare Roth Conversion Planner is a separate joint optimization of conversions and income that also prices ACA premium subsidies, healthcare costs and the 400% FPL cliff; Tax-Aware Mode's conversion candidates model no ACA subsidy.
How the advantage is explained. The two lifetime-tax figures the app shows are each the median of one order's own per-path tax paid, in today's dollars; the saving is the median of the per-path present-value difference. A median of a difference is not the difference of two medians, and the two are in different bases, so the app does not explain the saving from those figures. It takes the single simulated market history whose present-value advantage equals the reported median and reports that history's own parts — the present value of tax paid along the way, of tax still owed on any traditional balance at the end, and of any spending the portfolio could not fund — which sum exactly to the reported saving, alongside the same tax paid in today's dollars. When that history's tax is larger in today's dollars but smaller in present value, its tax fell later, and the app says so; when the advantage comes from less tax owed at the end, it says that instead. If that history's difference in tax paid lies outside the middle 80% of histories, the app says so as well.
The Tax Problem in Retirement
Retirees typically hold assets across three account types, each with different tax treatment:
| Account Type | Contributions | Growth | Withdrawals |
|---|---|---|---|
| Traditional IRA/401k | Pre-tax (deductible) | Tax-deferred | Fully taxable as ordinary income |
| Roth IRA/401k | After-tax (non-deductible) | Tax-free | Tax-free (qualified distributions) |
| Taxable Brokerage | After-tax | Taxed annually (dividends, interest) | Long-term capital gains rate on appreciation |
Choosing which accounts to withdraw from—and in what amounts—directly impacts:
- Federal income tax (10% to 37% marginal rates)
- Capital gains tax (0%, 15%, or 20% depending on income)
- IRMAA surcharges (Medicare Part B/D premium increases based on MAGI)
- ACA subsidy eligibility (for early retirees under age 65)
- Early withdrawal penalties (10% penalty if withdrawing before age 59½ from traditional accounts)
No single fixed sequence is best for every household: which accounts to draw first depends on the horizon, the size of the traditional balance relative to required distributions, Social Security timing and the state. The candidate orders above span the choices a planner would actually consider; the engine measures each on the household's own paths rather than assuming one.
Account Structure
The optimizer tracks three account balances:
For the taxable account, we also track the cost basis ratio:
This determines what fraction of a taxable withdrawal is principal (not taxed) versus capital gains (taxed at preferential rates). The single cost-basis ratio is the default model, and is described first because it is what most plans use. The engine internally represents it as a single tax lot; the lot-level model below is a strict generalization that reduces to it exactly when there is one lot.
Taxable Account: Per-Lot Cost-Basis Accounting
Rather than carry a single blended cost-basis ratio for the whole taxable account, the engine tracks the taxable account as a ledger of individual tax lots, each with its own dollar value and cost basis. This matters because a real taxable account is not homogeneous: shares bought at different times have different embedded gains, and which shares you sell changes the tax bill.
The ledger evolves over each simulated path:
- Growth applies to the whole ledger through a single shared growth index, so a lot's current value is its units times that index. Growth never changes the ordering of lots by cost-basis-per-dollar, which keeps the per-month update inexpensive.
- Simulation-created purchases become new lots. After-tax money that flows into the taxable account during the run — reinvested required-minimum-distribution excess, or a positive life-event windfall — is added as a fresh lot whose basis equals the full amount deposited (new money is not phantom gain), tagged with the month it was purchased.
- Sales use specific identification, highest-basis-first (HIFO). When the optimizer draws from the taxable account, it sells the highest-cost-basis lots first, which realizes the smallest gain (or harvests the largest loss) for a given dollar of proceeds — the standard tax-aware lot-selection order.
Short-term vs. long-term character
Each sale carries the correct holding-period character. A lot sold less than 12 months after it was purchased realizes a short-term gain; a lot held 12 months or longer realizes a long-term gain. The distinction is not cosmetic:
- Long-term gains are taxed at the preferential 0% / 15% / 20% capital-gains rates (stacked on top of ordinary income) and flow into the Net Investment Income Tax base.
- Short-term gains are taxed as ordinary income at your marginal bracket, and are likewise included in net investment income for the 3.8% surtax.
Because the initial holdings and user-supplied lots are treated as long-term, short-term character arises only on money the simulation itself deposited and then sold within a year — an uncommon but correctly-priced case.
Optional custom lots PRO
By default the initial taxable balance becomes a single long-term lot whose basis is taxableBalance × costBasisRatio — the same information the single-ratio model used, expressed as one lot. PRO users who know their actual holdings can instead supply up to 8 custom lots, each a {current value, cost basis} pair. The supplied values must sum to the taxable balance (checked to within about 0.1% of the balance, with a $1 floor; otherwise the request is rejected with a clear message); when custom lots are provided the single cost-basis ratio is ignored. All custom lots are treated as long-term. The response reports which mode was used and how many lots are tracked, so the assumptions are visible rather than hidden.
Withdrawal Decision Variables
In each year, the optimizer chooses amounts to withdraw from each account:
where $W_t$ is the withdrawal that funds year $t$'s spending and its tax: the smallest amount whose own split under the policy satisfies $W_t - C(\mathbf{w}_t) = S_t$, with $S_t$ the year's spending net of Social Security and pension (a bracketed solve to within $1; when a required minimum distribution exceeds it, the after-tax excess is deposited in the taxable account).
Tax Cost Function
The total tax cost for a given withdrawal mix is:
Every term is evaluated for the withdrawal mix each candidate policy draws that year, and the terms summed over the plan are what the policy search compares (above). In addition to the federal income, capital-gains and penalty terms below, the cost includes the state income tax for the selected state (Section 25), the Net Investment Income Tax (the 3.8% tax under §1411 on the smaller of net investment income — short- and long-term gains, and any taxable-account interest and dividends — and the amount by which modified AGI exceeds its threshold), and the IRMAA Medicare surcharge. Short-term gains realized from the taxable lot ledger are added to ordinary income before the income-tax term is computed.
Conversion candidates
Six of the whole-retirement candidates pair a bracket or Medicare-surcharge-tier fill with a Roth conversion. Within a candidate's year, the withdrawal is sized first, with no conversion income; the conversion is then sized on the full year so that withdrawal income plus the conversion lands exactly on the fill target, capped so the withdrawal itself stays fundable from what remains in the traditional account. Conversions never include RMD dollars — the required distribution is taken first and is not itself convertible. The window runs from retirement (or today, if already retired) through the year before the plan's required-distribution age begins; once RMDs start, the required dollars already occupy the low brackets, so later conversions were not evaluated for this branch.
The tax on a recommended conversion is paid the same way a real conversion is funded: from the taxable account first, where the sale itself realizes and pays tax on its own gain, and otherwise withheld from the converted dollars, in which case the withheld amount is treated as an early withdrawal and can carry the 10% additional tax under age 59½.
Every dollar of tax is paid from the accounts in the year it is owed. A Roth conversion pays its own marginal tax from the taxable account first (the funding sale goes on the year's Schedule D with the other sales: its gain is taxed, and a loss is deducted up to $3,000 and carried forward like any other) and otherwise from the converted dollars, with the 10% additional tax under age 59½ withheld as well; the rest of the year's bill is drawn through the policy's own withdrawal order — "traditional to the top of the 12% bracket, then taxable, then Roth" pays its tax bill from taxable once traditional has reached the bracket top. Because nothing is left undebited, the present-value comparison between candidates is exact on solvent paths, and no allowance for an unmodelled funding account is needed.
Income Tax Component
Ordinary income includes traditional IRA withdrawals, the taxable part of Social Security, pensions, and, when you enter a taxable-account yield, the interest and non-qualified dividends the taxable account pays:
Taxable-account yield. \(D_{\text{ord}}\) is zero unless you enter a yield. With no yield, the taxable account's whole return is treated as growth, taxed only as capital gains when you sell. With a yield, each retirement year the account pays that percentage of its start-of-year value. The qualified-dividend share is taxed at the 0%, 15% or 20% rates together with long-term gains (IRC §1(h)(11)), using the Qualified Dividends and Capital Gain Tax Worksheet, which never charges more than the regular tax on the same income (Form 1040 instructions; the engine applies that limit to long-term gains on every return). The rest is ordinary income. All of it counts toward the 3.8% net investment income tax (IRC §1411), the taxation of Social Security benefits and the Medicare IRMAA income test. The yield is part of the account's total return, not extra return: it is reinvested, which raises the cost basis by the same amount, so it isn't taxed a second time when the shares are sold. The qualified share is taken to meet the holding-period test: a dividend is qualified only if you “held the stock for more than 60 days during the 121-day period that begins 60 days before the ex-dividend date” (IRS Publication 550). The model does not track how long each share was held around each dividend, so if you trade often, enter a lower qualified share: a dividend that fails the test is ordinary income.
Capital losses. A year in which sales net to a capital loss deducts up to $3,000 ($1,500 married filing separately) of it from other income (IRC §1211(b)), which lowers the income used for Social Security taxation, the Medicare IRMAA test and the 3.8% net investment income tax. The rest carries forward on each simulated path, short-term and long-term separately, as the Schedule D carryover worksheet does (IRC §1212(b), Schedule D instructions). You can enter a carryover from before retirement with the API options capitalLossCarryoverShortTerm and capitalLossCarryoverLongTerm. When a spouse dies, only the survivor's share of the carryover passes on: a decedent's capital loss “can be deducted only on the final income tax return filed for the decedent”, and “The decedent's estate cannot deduct any of the loss or carry it over to following years” (IRS Publication 550). The simulator deducts the loss on the joint return for the year of death as usual, then carries forward only the survivor's share. It assumes the losses are split evenly, as for a jointly owned account; the API option spouseCapitalLossShare (0 to 1) sets the spouse's share. State returns take the loss by each state’s own rule (state engine 1.9.0): the same $3,000 ($1,500) in the states that start from federal adjusted gross income (Colorado, Iowa and North Dakota, which start from federal taxable income, get it through that figure), and in Arkansas, Mississippi and Wisconsin; up to $2,000 against interest and dividends only in Massachusetts; the whole year’s loss, with no carryover, in Alabama; nothing in Pennsylvania and New Jersey (the sources are on each state’s page of the state tax reference). Where a state keeps its own carryover (Massachusetts, Wisconsin) the plan carries the federal one, so those later years’ state deduction can be understated. (Before engine 1.3.0 a net loss was taxed as a year with no gain unless you turned these rules on; the API option capitalLossRules: false still gives that older result, which is not the law.)
Every step of the federal calculation (the Form 1040 lines it fills, the official source of each rule and the tests behind it) is documented in the federal tax engine documentation, with the order of the steps on the calculation order page and what the engine does not model on its overview.
Federal income tax is computed using the progressive bracket structure. For married filing jointly in 2026 (indexed for inflation):
| Taxable Income | Marginal Rate |
|---|---|
| $0 – $24,800 | 10% |
| $24,800 – $100,800 | 12% |
| $100,800 – $211,400 | 22% |
| $211,400 – $403,550 | 24% |
| $403,550 – $512,450 | 32% |
| $512,450 – $768,700 | 35% |
| Over $768,700 | 37% |
Capital Gains Component
When withdrawing from a taxable account, only the appreciated portion is subject to capital gains tax:
Long-term capital gains rates (for assets held >1 year) are preferential:
| Taxable Income | LTCG Rate |
|---|---|
| $0 – $98,900 (MFJ) | 0% |
| $98,900 – $613,700 | 15% |
| Over $613,700 | 20% |
Notably, the 0% capital gains bracket creates an opportunity: if ordinary income is low enough, retirees can sell appreciated assets and pay zero tax on the gains.
IRMAA Surcharges
Medicare Part B and Part D premiums increase for high-income beneficiaries based on Modified Adjusted Gross Income (MAGI) from two years prior. For 2026 (based on 2024 MAGI):
| MAGI (MFJ) | Part B Surcharge (per person) | Part D Surcharge (per person) | Total Annual (both spouses) |
|---|---|---|---|
| Under $218,000 | $0 | $0 | $0 |
| $218,000 – $274,000 | +$81.20/mo | +$14.50/mo | +$2,297/yr |
| $274,000 – $342,000 | +$202.90/mo | +$37.50/mo | +$5,770/yr |
| $342,000 – $410,000 | +$324.60/mo | +$60.40/mo | +$9,240/yr |
| $410,000 – $750,000 | +$446.30/mo | +$83.30/mo | +$12,710/yr |
| Over $750,000 | +$487.00/mo | +$91.00/mo | +$13,872/yr |
IRMAA creates income cliffs: earning $1 over a threshold can cost thousands in additional premiums.
Early Withdrawal Penalty
Traditional IRA/401k withdrawals before age 59½ incur a 10% additional tax (IRC §72(t): none on a distribution “made on or after the date on which the employee attains age 59½”; exceptions such as SEPP or separation at 55 are not modelled). The engine works in whole years, so it has to decide how much of the year in which you reach 59½ is still before it. With your birth month, it charges the share of that year before 59½, counting the month you reach it as before (the conservative side, since the day is unknown); without it, it charges the whole year you turn 59 and nothing from the year you turn 60:
where $m$ is the birth month (1–12). Without a birth month, $s = 1$ through the year you reach 59 and $0$ after. For someone born July–December this leaves the first months of the year they turn 60 (which are still before 59½) unpenalised; giving the birth month removes that gap.
Required Minimum Distributions (RMDs)
Starting at age 73 (for those born 1951-1959), the IRS requires minimum annual withdrawals from traditional accounts based on the Uniform Lifetime Table:
The optimizer enforces: $w_{\text{trad}} \geq \text{RMD}_t$ when RMDs apply. Failing to take RMDs results in a 25% penalty on the shortfall (recently reduced from 50%). The RMD start age is birth-year dependent under SECURE 2.0 (26 CFR 1.401(a)(9)-2): age 73 for those born 1951–1959 and age 75 for those born 1960 or later (“born on or after January 1, 1960”; the 1959 cohort is reserved in the regulation and treated as 73). The birth year is the one you give, or 2026 minus your age — see the age convention below. By default the simulation takes one RMD on the household’s combined traditional balance at the primary owner’s age, with the Uniform Lifetime divisor. When you enter your spouse’s share of the traditional balance (married filing jointly, with the spouse’s age given), it figures each spouse’s RMD separately, as the IRS does (Publication 590-B; 26 CFR 1.401(a)(9)-5): each on their own balance, from their own SECURE 2.0 start age, with the Uniform Lifetime divisor, or the Joint and Last Survivor divisor (26 CFR 1.401(a)(9)-9(d)) when the other spouse is the sole beneficiary and more than 10 years younger. QCDs come out of each owner’s own IRA. In the year the spouse dies the spouse’s RMD is still taken; from the next year the survivor treats the inherited IRA as their own (26 CFR 1.408-8(c)): one balance, at the survivor’s age and divisor. Withdrawals and Roth conversions above the RMDs, contributions and growth are shared between the two balances in proportion to their size. Either way, employer plans are not figured separately from IRAs, and the primary owner’s own death is not modelled: the plan follows the primary owner to the plan end. By default it takes each RMD in its own year. With First RMD by April 1 of the next year (tax inputs), each owner’s first RMD is taken by its required beginning date (26 CFR 1.401(a)(9)-5(a)(3): it “may be made on or before April 1 of the following calendar year”): the first year has no RMD floor and no Roth conversion (an RMD must come out before a conversion), what that owner withdraws in the first year counts toward the first RMD (Pub 590-B), and the rest is taken in the next year together with that year’s own RMD on its own December 31 balance — two RMDs in one year, taxed together, which can raise that year’s bracket, IRMAA tier and NIIT. The still-working exception for an employer plan (“the calendar year in which the employee retires”) is not modelled.
Age convention
Every age in the plan runs on one clock: in plan year $y$ (year 0 is the current tax year, 2026) you are your current age plus $y$. Your inputs (retirement age, Social Security and conversion ages, life events), the year-by-year tables and every tax rule read that same age. Unless you give a birth year, the engine assumes you were born in 2026 minus your age — that your birthday has already passed this year, which by late September is true for about three people in four. If your birthday is still to come this year, give your birth year: the plan's ages stay as they are, and the tax rules then use the age you reach in each calendar year, which is one higher.
- Age 65 deductions (§63(f) and the senior deduction) apply from the year you reach 65 — the statute's “attained age 65 before the close of his taxable year”.
- Medicare and IRMAA start at your Medicare age. Coverage starts in the month you turn 65 when you sign up in time (Medicare.gov: “Coverage always starts on the first of the month”), so the first Medicare year is charged the surcharge only for the months from your birthday month: $(13-m)/12$ of the year, or 6 months when you have not given a birth month. The same holds for a spouse.
- Qualified charitable distributions are allowed only from 70½: from the year you reach 70 if you were born January–June, otherwise from the year you reach 71. Without a birth month, from the year you reach 71, so the engine never allows one before 70½.
- The 10% early-withdrawal tax follows the 59½ rule above.
- Required minimum distributions start in the year you reach your SECURE 2.0 age.
Each result states the convention it ran under (the birth year used, whether it was assumed, and the RMD start age) in its assumptions panel.
Standard Deduction and Senior Deductions
Ordinary taxable income is computed after the standard deduction for the filing status, plus two age-based additions once a filer reaches 65:
- Additional standard deduction for the aged (IRC §63(f)). A set add-on to the standard deduction for each filer 65 or older ($1,650 per qualifying married filer, $2,050 unmarried, 2026 amounts). On a joint return it is granted per spouse who is 65+, so a couple where both are 65+ receives it twice. It has no income phase-out.
- OBBBA senior deduction (§70103). A separate $6,000-per-qualifying-individual deduction for filers 65+, available for tax years 2025 through 2028 only, and unavailable to married-filing-separately filers. It phases out at 6% of modified AGI above $75,000 (single / head of household) or $150,000 (joint), applied to each qualifying individual's amount — so a joint return with both spouses 65+ loses $0.12 of deduction per dollar over the threshold and reaches zero at $250,000 of joint MAGI. Because the phase-out depends on MAGI, the deduction is applied after the year's income is known.
The planner takes the standard deduction every year: it itemizes nothing (a QCD is an exclusion from income, not a deduction), so a charitable contribution carryover (IRC §170(d)(1)) cannot change a planner year's tax and has no planner input. The federal tax API and Year-end Tax Moves take carryovers for a single year (federal engine 2.2).
Yearly Cash-Flow Sequencing
Within each simulated year the engine resolves the interacting tax events in a set order so that later steps see the correct income base:
- Required minimum distribution first. The RMD floor is computed on the traditional balance at the start of the year, the balance at the close of the preceding December 31 (IRS Publication 590-B), not on the balance after the year's market return, and, where a Qualified Charitable Distribution is specified, the QCD is applied against that floor (a QCD satisfies the RMD without adding to taxable income). Any RMD beyond the QCD is a taxable distribution.
- Roth conversion. A conversion is ordinary income in the year it occurs. Conversions run only inside their configured age window, which typically ends before RMDs begin.
- Withdrawal under the policy's order funds the remaining spending need plus the year's tax (the gross-up above).
- Conversion tax funded from real dollars. The additional tax caused by a Roth conversion is paid with actual money drawn from the taxable account, not conjured for free. The engine attributes this cost marginally — the tax with the conversion minus the tax without it — and debits the taxable ledger accordingly (a HIFO sale), so the conversion's true after-tax drag is reflected.
- Reinvestment of RMD excess. When a required distribution forces more out of the traditional account than spending and tax require, the after-tax excess is not discarded — it is deposited into the taxable account as a new full-basis lot.
IRMAA Two-Year MAGI Lookback
Medicare's income-related surcharge for a given premium year is set from modified AGI two years earlier. The simulation carries this lag explicitly: each year's surcharge is driven by the MAGI recorded two years prior (a short ring buffer of recent MAGI values), rather than the current year's income. In the first years of Medicare, before two years of simulated history exist, the current-year MAGI is used. Not modelled: SSA uses the return three years back when the two-year-old one is not available (POMS HI 01101.020: “If MAGI in 2024 (or 2023 if 2024 is not available) was”); a retiree whose income fell after a life-changing event such as stopping work can ask for a new determination on Form SSA-44, which the simulation never assumes; and the IRMAA MAGI adds tax-exempt interest but not the other add-backs (the savings-bond interest exclusion, foreign earned income, possession income). Married-filing-separately filers who lived with their spouse at any time in the year use the compressed IRMAA schedule (a steeper ladder with two surcharge steps rather than the five surcharge steps on joint or single returns); a separate filer who lived apart from their spouse for the entire year uses the individual schedule, as for a single filer (20 CFR 418.1115). On a joint return where both spouses are Medicare-age the surcharge is levied on each spouse at the couple's joint MAGI — effectively doubling it.
Tax-Exempt (Municipal) Interest
Tax-exempt interest is optional annual income that is deliberately treated the way the tax code treats it — it counts in exactly the places it legally counts, and nowhere else. It is added to the provisional-income base that determines how much Social Security is taxable, and to the modified AGI used for IRMAA, but it is not ordinary taxable income and is not part of the Net Investment Income Tax base. Like pension and Social Security amounts, it is entered in today's dollars and inflated forward.
Life Events in Tax-Aware Mode
A life event's type decides how Tax-Aware Mode taxes it (federal engine 2.0, October 2026):
- Wages and Self-employment (yours or, on a joint return, your spouse's) are earned income on that year's federal and state returns: employee Social Security and Medicare tax on wages, or Schedule SE on self-employment profit, the Additional Medicare Tax (Form 8959), the half-SE-tax deduction and the §199A qualified business income deduction (Form 8995), and the amounts count in AGI and in the MAGI the IRMAA two-year lookback reads. Later years use the year's wage base, earnings-test limits and other amounts as the plan's “Tax Amounts in Later Years” setting moves them. Before your retirement age the planner holds no salary of its own, so such an event is the household's taxed income that year: its own return is figured and the after-tax amount goes to savings.
- The Social Security earnings test. When a claimed benefit is being paid before full retirement age, Social Security withholds $1 of benefits for every $2 of the year's wages and net self-employment earnings above the exempt amount ($1 for $3 in the year you reach full retirement age, counting only earnings before that month), in whole monthly payments, and pays the excess back the next year (SSA, How Work Affects Your Benefits). From full retirement age the benefit is refigured for the months withheld (42 U.S.C. 402(q)(7); the reduction of 5/9 of 1% a month for the first 36 months and 5/12 of 1% after, 20 CFR 404.410). The planner pays Social Security from your retirement age, so the test applies to work after that age.
- Sell Property with a cost basis is a sale: the gain over the basis, less the §121 exclusion ($250,000; $500,000 on a joint return) for a primary residence, is a long-term capital gain on that year's return. Without a basis the proceeds are after-tax cash.
- Windfall is not income by default (a gift or cash inheritance, §102(a)); marked “taxable as ordinary income” (an inherited traditional IRA taken at once, a prize) it is ordinary income that year.
- Rental income (federal engine 2.1) is rental real estate on Schedule E: the yearly net cash (rents less cash expenses, grown by the event's inflation category) less the depreciation you enter (in dollars as entered). A loss passes the passive-activity loss limit (IRC §469(i); Form 8582): you are taken to actively participate, so up to $25,000 a year is deducted from other income, reduced by half of modified AGI over $100,000 (none on a separate return), and the rest is carried to later years on each simulated path. Rental income is net investment income for the 3.8% tax and counts in AGI and the IRMAA MAGI; the state return takes the federal Schedule E amount: income is other ordinary income, and an allowed loss reduces the state’s income where the state starts from federal AGI or follows the federal schedule (Georgia and Delaware count it in their retirement-income exclusion), while Pennsylvania and New Jersey let a rental loss offset no other class of income. Not modelled: the real estate professional rule, the release of a carried loss when the property is sold (§469(g)), depreciation recapture and a net operating loss.
- Inherited IRA (federal engine 2.2) is an IRA or plan account you inherited: the federal engine decides the beneficiary's rule from the decedent's birth and death years and your category (26 CFR 1.401(a)(9)-5; Pub 590-B): the 10-year rule (with annual distributions in years 1-9 when the decedent died on or after the required beginning date), a life-expectancy payout for an eligible designated beneficiary, the 5-year rule or the decedent's remaining life expectancy without a designated beneficiary. Each plan year takes the required minimum, or spreads the balance evenly to the deadline if you choose; the account grows at the rate you enter after inflation, apart from the portfolio, and each distribution is paid in at the start of the year. A traditional account's distribution is ordinary income with no 10% early-withdrawal tax (a beneficiary's), and other income on the state return; an inherited Roth IRA's is tax-free cash. Not modelled: successor beneficiaries, several beneficiaries of one account, and the decedent's own RMD in the year of death.
- Income events (and the cash cases above) are after-tax cash: they reduce what the portfolio must fund and are not taxed.
The alternative minimum tax (Form 6251) is figured in every year whose income could reach it. Without Tax-Aware Mode no event is taxed.
Federal credits (federal engine 2.2): in a year with wages or self-employment income (a life event) the planner figures the credits on that year's return, as the federal tax API does. The earned income credit without a qualifying child (the planner has no dependents), for a filer at least 25 and under 65 (Publication 596), is refundable: in a low-income working year the federal total can be a refund. The saver's credit takes the plan's contributions of that year before retirement as the primary's own, for 2026 only: from 2027 the law counts only ABLE contributions for it (IRC §25B(d)(1)(B)). The credit for the elderly cannot lower a year's tax for a filer 65 or older on the standard deduction: its income limits ($17,500; $25,000 on a joint return) are below the standard deduction with the extra amount for age, a property the engine's tests check. A year without earned income has none of these credits; the child tax credit needs a dependent. The state return's federal tax (Alabama, Oregon) is taken before the credits.
Social Security Taxation (Provisional Income)
The taxable portion of Social Security is computed with the provisional-income tiers of IRS Publication 915: up to 85% of benefits become taxable as provisional income (AGI excluding Social Security, plus tax-exempt interest, plus half of benefits) rises through the tier thresholds. Married-filing-separately filers who lived apart from their spouse for the entire year use the single thresholds ($25,000 / $34,000); otherwise the separate-filer thresholds are $0 / $0, so their benefits are taxable from the first dollar. This lived-apart distinction is an optional input.
The Retired Single-Year Grid Search (comparison only, never recommended)
Until September 2026 QuantCalc chose each year’s mix with a brute-force grid search over that year’s withdrawal splits. It is described here because the withdrawal-order study still scores it as a comparison, and because results published before that date were produced by it. It is no longer a candidate in any projection. The search space was discretized as:
- Divide total withdrawal $W_t$ into increments of 10%
- Enumerate all combinations: $(w_{\text{trad}}, w_{\text{roth}}, w_{\text{tax}})$ where each is a multiple of $0.1 \times W_t$
- Subject to: $w_{\text{trad}} + w_{\text{roth}} + w_{\text{tax}} = W_t$ and $w_{\text{trad}} \geq \text{RMD}_t$
This produces 66 unique combinations per year. For each combination, we compute total tax cost $C(\mathbf{w}_t)$ and select the minimum.
- Tax brackets create a non-smooth objective with discontinuities
- IRMAA thresholds introduce sharp cliffs
- The search space is small (66 points) and evaluation is fast
- Global optimum is guaranteed (no local minima trap)
Multi-Year Simulation
Each Monte Carlo simulation path is run once per candidate policy, all on the same market draws, and the candidate with the lowest present value of lifetime tax is re-run as the primary so every chart and table reflects the recommendation:
For each candidate order k:
For each simulation path s = 1..N (identical paths for every k):
Initialize accounts (B_trad, B_roth, B_tax), the tax-lot ledger, the MAGI ring
For each year t = 1..T:
Apply returns; apply contributions and life events
Resolve spending (fixed real, or the guardrail / VPW rule on this candidate's own balances)
QCD -> RMD floor -> Roth conversion -> conversion-tax funding -> withdrawal under order k grossed up so that W - tax = spending -> surplus deposit / shortfall record
PV_k[s] += (tax_t + IRMAA_t + unfunded_t) / G_t (G_t = portfolio growth from today to year t on path s)
PV_k[s] += heir tax on ending traditional / G_T
score_k = median_s ( PV_baseline[s] - PV_k[s] ) (baseline = traditional first; score_baseline = 0)
Recommend k* = argmax_k score_k; re-run k* as the primary strategy for every chart and table
Metrics Reported
Tax-Aware Mode adds these outputs:
- Lifetime tax paid: Median tax paid under the recommended order, today's dollars
- Traditional-first lifetime tax paid: The same, for the traditional-first baseline
- Tax still owed at the end: The heir valuation (Section on Conversion candidates' heir assumptions), for both the recommended order and traditional-first
- Lifetime tax saved: Present value, paired per path against traditional-first, never negative
- Recommended order: The candidate policy chosen, named
- Effective tax rate: Total taxes / Total withdrawals (withdrawals include the tax they fund)
- Account depletion sequence: Which accounts run out first
- Unfunded spending: Median spending and tax the portfolio could not fund, today's dollars — zero when the median path stays solvent
Practical Impact
How much the order is worth depends on the household. Measured results for nine households and a horizon sweep, with the recommended order for each, are published in When Withdrawal Order Helps, and When It Backfires (2026).
- Staying in lower tax brackets by mixing Roth withdrawals
- Harvesting capital gains at 0% when income allows
- Avoiding IRMAA cliffs
- Strategic Roth conversions in low-income years
- Drawing traditional first while brackets are low when a large traditional balance would otherwise be forced out later at higher rates and with Medicare surcharges
Changes to how ages are counted (28 September 2026)
Until this change the engine used two age clocks. Your inputs used your age during each plan year, but the tax rules and the year-by-year tables counted you a year older, as if your birthday were still to come this year. That put several rules a year early or late. What changed, in plain terms:
- A Roth conversion plan that starts in your retirement year now converts in that year too; before, the first year was silently skipped.
- Required minimum distributions start in the year you reach 73 or 75, from your birth year; before, they started a year early, and someone who is 66 now was assumed born in 1959 (RMDs at 73) when most people that age were born in 1960 (RMDs at 75).
- Medicare surcharges start at your Medicare age and, in the first Medicare year, only for the months you are covered; before, they could be charged for the whole year, and a year early.
- Charitable distributions (QCDs) start at 70½; before, the engine allowed them from the year you turned 69 or 70.
- After a spouse's death the return stays joint for that year and becomes single the next, and the survivor's Social Security applies from the year of death; before, the switch came a year early. A spouse-death age you give is no longer replaced by a random draw when you also give the spouse's age.
- The year-by-year table labels each year with your age during it, matching the retirement age you typed; the projection chart's Retire line and life-event markers now sit on their own labels; and the guardrail withdrawal rate is read from the balance at retirement rather than a year later.
- You can give a birth year and month for exact timing; without them the result says what it assumed.
Most plans move little. Plans with a conversion window, a spouse-death age, QCDs or Medicare in the first years move more: across our sixteen test households lifetime tax changed by between −6% and +5% and success rates by at most half a point.
Changes to the ACA Bridge Planner and the Roth Conversion Planner (28 September 2026)
The multi-year plan behind the ACA Bridge Planner and the Roth Conversion Planner used to work out each year's federal tax with its own, simpler arithmetic. It now uses the same tax engine as the retirement simulator, so the two agree. What changed, in plain terms:
- From the year you turn 65, your tax is lower: the extra standard deduction for age 65 and over and the senior deduction for 2025–2028 now apply (26 U.S.C. §63(f), §151(d)(5)). Before, a married couple both 66 with $150,000 of income was charged $15,340 of federal tax instead of $11,974.
- Money taken from a traditional IRA or 401(k) before 59½ now carries the 10% additional tax (26 U.S.C. §72(t)); it is included in the federal tax shown. The planner counts whole years: the 10% applies in any year you are 59 or younger at year end. It never applies to a Roth conversion. Only the age-59½ exception is modelled.
- The year you turn 65 is split: marketplace coverage (and its premium credit) for the months before your birthday, Medicare after. Without a birth month the planner assumes a mid-year birthday. Medicare surcharges (IRMAA) are charged for the Medicare months only, per spouse, and in the plan's first two years they are based on that year's income, as in the simulator.
- State tax in states that start from, or deduct, federal figures (for example Alabama, Colorado and Oregon) now uses the real federal numbers.
- A married person filing separately who lived apart from their spouse all year can say so, and less of their Social Security is taxed. Their Medicare surcharge (IRMAA) also uses the individual table rather than the separate-filer one (20 CFR 418.1115), in the bridge and in the simulator.
- The recommended plan is never more costly than converting nothing. Before, in some households the search could settle on a plan that cost more than doing nothing.
- Required minimum distributions are part of the plan from the age that applies to your birth year (73, or 75 if born in 1960 or later), on the IRS Uniform Lifetime Table, or the Joint Life table when your spouse is your sole beneficiary and more than ten years younger (26 CFR 1.401(a)(9)-9). What you don't spend is reinvested in your taxable account. Before, a plan past that age could leave the account untouched.
- Roth withdrawals follow the Roth rules (26 U.S.C. §408A(d)): your contributions come out first, tax- and penalty-free; then conversions, oldest first, with the 10% on any conversion taken out within five tax years before 59½; then earnings, which are taxed (and carry the 10% before 59½) until the account is five years old and you are past 59½. The planner treats your starting Roth balance as contributions in an account open at least five years unless you say otherwise. Before, every Roth dollar was treated as tax- and penalty-free.
- Engine 1.4.0: months on Medicare are never counted as Medicaid months. The Medicaid expansion group is adults “under age 65” who “Are not entitled to or enrolled for Medicare benefits under part A or B” (42 CFR 435.119). Before, in the year you turn 65 a household below 138% of the poverty line was on Medicaid for all twelve months, including the months after the birthday. Now the months on Medicare pay the plan's full out-of-pocket estimate, as on the marketplace side. The Medicaid programs open to people on Medicare (the Medicare Savings Programs) have a 2026 resource limit of $9,950 for one person and $14,910 for a couple (Medicare.gov), below the savings the planner assumes, so they are not modelled. For a single person turning 65 on the low profile, that year's healthcare cost goes from $900 to $1,950. A year with everyone on Medicare all year is shown as Medicare.
- Marketplace premiums are priced on your age on 1 January of each year, the age the marketplace uses (45 CFR 147.102); before, a year older. The ACA Bridge Planner now runs through the year you turn 65.
Who sees a difference: anyone who will draw from a traditional account (or from Roth conversions and earnings) before 60 (higher tax), anyone whose plan runs past 65 (lower tax, and some premium credit in the year they turn 65), and couples on Medicare early in the plan. In the Roth Conversion Planner's worked example (a single Ohioan aged 62, planning to 73), lifetime federal and state tax went from $24,801 to $23,470. Anyone who will draw on the Roth before 60, or whose plan runs past the RMD age, sees larger changes.
20. ACA Subsidy Cliff Management
For early retirees (ages 55-64, before Medicare eligibility), the Affordable Care Act (ACA) subsidy cliff represents one of the most significant financial risks in retirement planning. The cliff creates a scenario where earning just $1 of additional income can eliminate the whole premium tax credit ($15,634 a year for the couple in the example below)—an effective marginal tax rate that can exceed 1,000%.
The retirement simulator's Tax-Aware Mode (Section 19) does not price the premium tax credit: its candidate orders and conversions are costed on income tax, Medicare surcharges and penalties only. The ACA subsidy and the cliff are modelled by the separate ACA Bridge Planner, which also runs inside the Roth Conversion Planner; what it does is described below and in Section 25.
What is the ACA Subsidy Cliff?
The ACA provides premium tax credits (subsidies) to reduce the cost of marketplace health insurance for individuals and families below certain income thresholds. Prior to 2026, enhanced subsidies phased out gradually. Starting in 2026, the subsidies revert to the original ACA structure with a hard cutoff at 400% of the Federal Poverty Level (FPL).
For 2026, the cliff occurs at:
| Household Size | 400% FPL (MAGI Threshold) |
|---|---|
| 1 (Single) | $62,600 |
| 2 (Married) | $84,600 |
| 3 | $106,600 |
| 4 | $128,600 |
| +1 per additional | +$22,000 |
These are 4 × the 2025 HHS poverty guidelines for the 48 contiguous states and DC, which govern 2026 coverage (90 FR 5917: $15,650 plus $5,500 per additional person). Alaska and Hawaii have their own, higher guidelines.
If Modified Adjusted Gross Income (MAGI) exceeds the threshold by even $1, the entire subsidy disappears. There is no gradual phase-out.
Subsidy Calculation
ACA subsidies are calculated as the difference between the "benchmark plan" premium (second-lowest-cost Silver plan in your area) and a capped percentage of your income:
where $r_{\text{cap}}$ is the income-based required-contribution percentage. With the ARPA/IRA enhanced subsidies expired after 2025 (and not extended), 2026 reverts to the indexed §36B applicable-percentage table of IRS Rev. Proc. 2025-25 — running from 2.10% up to 9.96%, with the hard 400% FPL cliff restored. The percentage is piecewise-linear within each band:
| MAGI as % of FPL | Required contribution (% of MAGI) |
|---|---|
| Under 133% | 2.10% |
| 133% – 150% | 3.14% – 4.19% |
| 150% – 200% | 4.19% – 6.60% |
| 200% – 250% | 6.60% – 8.44% |
| 250% – 300% | 8.44% – 9.96% |
| 300% – 400% | 9.96% |
| Over 400% | No subsidy (cliff) |
Example: The $1 Cliff
Consider a 62-year-old married couple in Denver, Colorado:
Scenario A: MAGI = $84,000 (below the $84,600 couple cliff)
- Benchmark Silver plan premium: $24,000/year
- Required contribution (9.96% of MAGI): $8,366
- ACA subsidy: $24,000 - $8,366 = $15,634
- Out-of-pocket: $8,366/year
Scenario B: MAGI = $85,000 (above the cliff by $400)
- Benchmark Silver plan premium: $24,000/year
- ACA subsidy: $0 (cliff)
- Out-of-pocket: $24,000/year
Result: Earning an extra $1,000 cost this couple $15,634 in lost subsidies—a 1,563% marginal tax rate.
MAGI for ACA Purposes
ACA subsidies are based on Modified Adjusted Gross Income (MAGI), which is AGI plus certain add-backs. Critically, not all retirement income counts toward MAGI.
Income that COUNTS toward ACA MAGI:
- Traditional IRA/401k withdrawals
- Wages and self-employment income
- Taxable interest and dividends
- Capital gains (including from portfolio rebalancing)
- Rental income (net of expenses)
- Pension income
- All Social Security benefits, including the part that is not taxable (IRC §36B(d)(2)(B)(iii))
- Tax-exempt (municipal bond) interest (IRC §36B(d)(2)(B)(ii))
IRC §36B(d)(2)(B) adds to AGI “any amount of interest received or accrued by the taxpayer during the taxable year which is exempt from tax” and the part of “social security benefits (as defined in section 86(d)) which is not included in gross income”.
Income that DOES NOT count toward ACA MAGI:
- Roth IRA withdrawals that are qualified, or that return your contributions (earnings taken out early are taxable and do count)
- HSA withdrawals for qualified medical expenses
- Qualified Charitable Distributions (QCDs) from IRAs
- Return of principal from non-qualified annuities
- Borrowed money (home equity lines of credit, margin loans)
How the ACA Bridge Planner handles the cliff
The planner runs one year at a time from your current age through the year you turn 65 and chooses a Roth conversion amount for each year:
- Household and threshold. The household size and state give the year's federal poverty level; you choose the MAGI ceiling as a percentage of it (400% by default, or lower to stay in a cheaper credit band).
- Withdrawals. Each year's spending, healthcare cost and tax are funded from any required minimum distribution first, then the taxable account, then the Roth, then traditional, solved to a fixed point because the tax and the premium credit depend on the withdrawals.
- The ceiling is a hard limit. A year's conversion is capped so that ACA MAGI (with all Social Security, tax-exempt interest and the gain on taxable sales) stays at or under the ceiling. Withdrawals the spending needs are never cut, so a year can still cross the cliff when spending alone requires it, and the result shows that year's MAGI and credit.
- Coverage regime. Below 138% FPL in an expansion state a year is priced as Medicaid, below 100% FPL in a non-expansion state as the coverage gap (Wisconsin: BadgerCare to 100%), otherwise as a marketplace plan with the credit.
- Objective. The conversions are chosen to minimize lifetime federal and state income tax plus healthcare cost net of the credit plus IRMAA (a small reward for ending wealth breaks ties); federal tax is the same engine as the simulator's.
The planner does not cut your spending to stay under the cliff, and does not time one-off income events for you: harvesting losses, moving a large sale to a year before retirement or after 65, and spending less in the bridge years are choices you model by changing the inputs.
Metrics Reported
For every plan year the ACA Bridge Planner reports the recommended conversion, the withdrawal from each account, ACA MAGI and its percentage of FPL, the coverage regime, the healthcare cost and the premium tax credit, and federal tax (with any 10% early-withdrawal tax), state tax and IRMAA; and for the plan the lifetime totals of each and the ending portfolio.
Limitations and Assumptions
QuantCalc's ACA cliff modeling assumes:
- Cliff remains at 400% FPL: If Congress restores enhanced subsidies, the cliff may be eliminated or softened
- Benchmark premium estimates: Actual premiums vary by location, age, and plan design
- Income is known in advance: the credit is computed on the year's final MAGI. Advance payments and their reconciliation at tax time (Form 8962) are not modelled
References and Further Reading
For detailed guidance on ACA subsidy optimization, see QuantCalc's ACA Subsidy Cliff 2026 blog post and the ACA Subsidy Calculator.
Part IV documents the PRO-gated modeling extensions. Each feature is off by default and preserves bit-for-bit output when disabled — the baseline Monte Carlo engine described in Parts I–III is a strict subset.
21. Gompertz Gender-Specific Mortality
By default, simulations run a fixed horizon from current_age to life_expectancy. Under the mortality model, we draw per-path terminal ages from a Gompertz distribution with gender-specific parameters, so outcomes reflect the joint distribution of portfolio performance and longevity.
where $M$ is the modal age at death and $b$ is the dispersion parameter. Calibration follows Milevsky (2020) using SSA period life tables:
| Gender | Modal age $M$ | Dispersion $b$ |
|---|---|---|
| Male | 86.0 | 9.5 |
| Female | 89.0 | 9.0 |
| Unisex (default) | 87.5 | 9.25 |
For joint-life scenarios (joint filers with a spouse), each simulation path draws two independent Gompertz death ages. Supplying the spouse's current age enables stochastic widowhood: each path draws a spouse-death year from the gender-specific Gompertz table, so the timing of the first death varies across the distribution rather than being held constant. (A single deterministic spouse-death age can be specified instead when a constant assumption is preferred.)
The first death is a material tax event, and the engine models its consequences. In the plan year of the death the household switches to the survivor's income and spending: it keeps the larger of the two Social Security benefits, the survivor share of any spouse pension, and the survivor spending percentage. The return for that year is still a joint return — IRS Publication 501: “If your spouse died during the year, you are considered married for the whole year” — including the late spouse's age-based deductions. From the next year the survivor files single: the brackets compress, the standard deduction and its age-based additions halve, and the IRMAA thresholds halve. (A survivor with a dependent child may file as a qualifying surviving spouse for two more years — Publication 501 ties it to “the child who qualifies you for this filing status” — but the engine has no dependents input, so it files single.) A spouse-death age you give always wins over the mortality draw. While both spouses are alive and 65 or older, the couple receives the age-based deductions per spouse and pays the Medicare surcharge on each spouse — effects driven by the same spouse-age input.
22. Fat-Tail Returns & Regime Switching
The two overlays in this section — fat tails and regime switching — add empirical realism to the parametric return model. They are the parametric route to the same properties that the Historical Bootstrap return model (Section 5) captures non-parametrically by resampling actual history. The two are alternatives: when the bootstrap return model is active these parametric overlays (and inflation coupling, Section 24) are disabled. Fat tails and volatility clustering are genuinely present in the resampled data, so the overlays would double-count them. Return–inflation coupling is not: the resampled series carries nominal returns only and the simulated CPI path is drawn from a separate process, so under the bootstrap model a month's returns and its inflation are independent — less coupling than the parametric path it replaces, not more.
Student-t Variance Mixture (Fat Tails)
The Gaussian return model understates the empirical kurtosis of equity returns. When Fat-Tail Returns is enabled, each monthly shock is drawn from a Student-t variance mixture:
The result is Student-t distributed with $\nu$ degrees of freedom. Variance is rescaled by $\sqrt{(\nu-2)/\nu}$ so the marginal variance still matches CME inputs. Recommended: $\nu=5$ reproduces empirical equity kurtosis $\approx 7$.
2-State Markov Regime Switching (Bull / Bear)
A Markov chain with transition matrix $P$ governs monthly switching between a bull and bear regime. In the bear state, the vol of the joint shock is multiplied by regime_bear_vol_mult and the drift shifted by regime_bear_drift_shift:
Defaults ($p_{bb}=0.01$, $p_{\bar b b}=0.15$, vol multiplier $1.8\times$) imply mean bear duration $\approx 6.7$ months and long-run bear probability $\approx 6.3\%$ — consistent with post-war US equity data.
Variance compensation. Under lognormal monthly growth $\exp(\mu_a + \sigma_a z)$, scaling the shock by $m$ in stressed months would, by Jensen's inequality, multiply that month's arithmetic expected return by $e^{(m^2-1)\sigma_a^2/2}$ — a hidden upward drift the user never asked for. The engine cancels it exactly: each asset's log-return in a stressed month receives the Itô correction $-(m^2-1)\,\sigma_a^2/2$. Stressed months therefore have higher variance but unchanged unconditional expected arithmetic return, so enabling regime switching widens the distribution without quietly changing its mean.
For a fully data-driven companion to this model — a Gaussian hidden-Markov fit to 150+ years of monthly real S&P total returns, with a current filtered regime reading refreshed monthly — see the Market Regime Monitor.
Fitted (1871–2026) Preset
The PRO regime panel offers a preset that transfers the fitted two-state structure into the engine: monthly transition probabilities $p_{bb}=0.0304$, $p_{\bar b b}=0.1488$, a stressed/calm volatility ratio of $2.55\times$, and the full fitted bull–bear drift spread of $-0.0277$/month (log). These four numbers are derived from the same monthly refit that drives the Market Regime Monitor rather than being chosen by hand, and the shipped preset is checked against the published fit before release, so the two cannot drift apart. Because forward-looking capital market expectations are unconditional — they already average over historical bear markets — applying the spread as a raw bear-only drag would double-count bears and depress the unconditional mean by $\pi_{bear}\times$ spread $\approx 5.6\%$/yr. The preset therefore re-centers the shift under the chain's stationary distribution: every month receives $-\pi_{bear}\,\Delta$, leaving the calm state at a small positive offset and the stressed state carrying the full spread.
Initial regime. Because the shift is de-meaned at the stationary stressed share $\pi_{bear}$, the chain must also start at that share or the re-centering over-corrects early. Each path therefore draws its month-0 regime from the stationary distribution, $s_0 \sim \text{Bernoulli}(\pi_{bear})$, instead of always opening in the calm state. Two consequences: the unconditional expected return matches your CME inputs from the first month rather than from about year two, and the first year of the plan — the window that dominates sequence-of-returns risk — carries the model's own long-run share of stressed months instead of a systematically calmer one. Opening every path in the calm state understated the stressed share for roughly 24 months and left about $+2\%$ of unintended cumulative drift on terminal values, almost all of it inside the first 12 months.
What the preset changes is where losses concentrate — contiguous stressed episodes — which is exactly the sequence-of-returns channel. The spread is estimated on real returns and applied to nominal paths; the difference is second-order because inflation is common to both regimes. Calm-state volatility equals your CME volatility, so unconditional volatility under the preset is $\sqrt{1-\pi_{bear}+\pi_{bear}m^2} \approx 1.39\times$ the CME volatility input (regime switching is deliberately a vol-increase overlay, as above).
23. Stochastic Inflation
The default engine compounds a constant CPI rate. The stochastic-inflation module replaces this with one of three user-selectable calibrated processes. Cash flows are stored in real (2025-dollar) terms and multiplied by a per-path cumulative inflation factor inside the simulation loop; this preserves bit-identical output when the model is deterministic.
Method 1 — AR(1) on CPI
Calibrated on FRED CPIAUCSL monthly log-differences, 1947–present. Anchored fit (post-1985 sample): $\bar\pi = 2.53\%$/yr, $\varphi = 0.4495$, $\sigma = 0.80\%$/yr.
Method 3 — Multi-Category Correlated AR(1)
Retirement spending is not single-index CPI. Medical, education, and housing categories compound at different rates with imperfect correlations. The multi-category model runs four parallel AR(1) processes on:
| Category | BLS Series | Long-run $\bar\pi$ | $\varphi$ | $\sigma$ (%/yr) |
|---|---|---|---|---|
| CPI (all items) | CPIAUCSL | 2.53% | 0.45 | 0.80 |
| Medical care | CPIMEDSL | 3.48% | 0.55 | 1.20 |
| Education | CUSR0000SAE | 4.54% | 0.60 | 1.50 |
| Housing | CUSR0000SAH | 3.01% | 0.65 | 1.00 |
Shocks are cross-correlated via a Cholesky factor $L$ of a user-overridable correlation matrix. Each life event has a inflationCategory tag that selects which factor compounds that line item — medical events ride the medical-CPI path, tuition rides education, etc.
Method 4 — 2-State Regime (Anchored / Unanchored)
The 1970s and 2021–23 episodes are poorly described by a single Gaussian AR(1). We fit a 2-state hidden Markov model (Hamilton 1989) via the EM algorithm on the full postwar sample:
| State | Mean | Std | Transition to other state |
|---|---|---|---|
| 0 — Anchored | 2.0%/yr | 0.6%/yr | $p_{01} = 0.4\%$/mo |
| 1 — Unanchored | 6.0%/yr | 2.2%/yr | $p_{10} = 2.0\%$/mo |
Stationary distribution gives $P(\text{unanchored}) \approx 17\%$, matching the empirical unanchored months in 1965–1982 + 2021–2023. Calibration is in backend/calibration/fit_inflation_regime.py.
Method 5 — Stationary Block Bootstrap (internal validation only)
Politis-Romano (1994) stationary block bootstrap on historical CPI returns. Blocks are drawn with Geometric lengths (default mean 30 months) and resampled with wraparound. Used as a non-parametric yardstick against which methods 1/3/4 are validated; not user-exposed.
24. Per-Asset Inflation Coupling (β)
Real assets don't respond neutrally to inflation surprises. When coupling is enabled, each asset's monthly log-return is shifted by its inflation beta times the current surprise:
Literature defaults (Ang & Piazzesi 2003; Fama & Gibbons 1984; Bekaert & Wang 2010):
| Asset | $\beta$ | Interpretation |
|---|---|---|
| US Equity | -0.30 | Mildly negative; long-duration cashflows hurt by surprise |
| Intl Equity | -0.20 | Smaller due to FX hedging |
| Bonds | -5.00 | Nominal duration risk — large sensitivity |
| Real Estate | +1.00 | Partial hedge; rents reset with CPI |
| Cash | +0.00 | Near-neutral at monthly horizon |
25. State Tax, Roth Conversion, QCD & IRMAA Refinements
State Tax Engine (51 jurisdictions)
Each jurisdiction's rules as the engine applies them, with the official source for each rule (the few that have none yet are listed on the verification page), worked examples and the state's verification status, are documented in the state tax engine documentation (all 51 jurisdictions, verification).
Federal-only tax mode still accounts for most of QuantCalc's audience, but single-state filers see meaningful divergence (FL/TX 0% vs CA 13.3% top). The state engine carries 2026 law for all 50 US states plus the District of Columbia; where a state has not yet published a 2026 figure, the latest published figure is used, and the provenance record (downloadable from the documentation) marks that source as a prior-year proxy. It is not a single blended rate per state: each jurisdiction has its own bracket schedule per filing status, standard deduction, retirement-income treatment, Social Security rule, and capital-gains treatment. The schedules are checked against each state's Department of Revenue filings.
The federal dollar amounts of later years move the same way (federal engine 2.0; the federal indexing registry gives every amount with its statute, base year, rounding and official source), under the same later-years setting as the state amounts; the API keeps a separate option for each side (federalThresholdIndexing and stateThresholdIndexing). As the law sets them is the default: the brackets, the standard deduction, its age-65 amount, the capital-gain breakpoints, the IRMAA income floors and the QCD limit are indexed from their statutory base years with the statute's rounding, at the path's cumulative inflation; the thresholds the law fixes stay at their nominal figures in every year (the $200,000 / $250,000 Net Investment Income Tax thresholds, the $25,000 / $32,000 and $34,000 / $44,000 Social Security taxation thresholds, the $3,000 capital-loss limit), so more of a growing income crosses them as prices rise; and the senior deduction ($6,000 per person 65 or older) ends after 2028, as the statute enacts. Rise with inflation is the planner's convention before September 2026, reproduced exactly: the brackets, the standard deduction and its age-65 amount, the IRMAA floors and the QCD limit rise with inflation, unrounded; the fixed thresholds and the enacted schedules are the law's in both settings. The simulation response says which ran (federalTaxProjection).
How later years move each state's dollar amounts is a setting (State Amounts in Later Years; the API option stateThresholdIndexing). As the law sets them is the default (state engine 1.10.0; the indexing registry gives every rule with its official source): an amount the statute indexes grows with the path's cumulative inflation and is rounded the statute's way; an amount fixed in law, such as New York's brackets or a $1,000,000 surtax floor, stays at its nominal figure, so it loses real value as prices rise; an enacted schedule (Virginia's standard deduction, which falls back to $3,000 in 2030; Hawaii's 2027 and 2029 bracket tables) is followed, and a step that waits on a revenue test is not; a birth-year cutoff moves one year per year. Other rate changes a state has already enacted for later years are not applied, and an amount whose later-year treatment no official source settles is held at its 2026 figure. Rise with inflation is the option: the convention QuantCalc used before September 2026, reproduced exactly, in which most state dollar amounts rise with inflation every year even where the law fixes them, and the rest (such as capital-loss limits) stay at their 2026 figures. The simulation response says which ran and what was held (stateTaxProjection), and so does the Assumptions panel. Before September 2026 the second convention was the only one, which understated tax in the states that do not index.
Rate schedules
Both progressive (multi-bracket) and flat-rate states are represented, with the correct schedule selected for single, married-filing-jointly, married-filing-separately, and head-of-household filers. Separate filers are handled per each state's actual rule — some states compress the joint brackets by half, others apply one shared schedule across statuses. Distinct head-of-household schedules are carried where a state publishes them.
Retirement-income exclusions
Retirement income is not taxed uniformly across states, and the engine encodes each state's actual rule rather than a flat inclusion:
- Full exclusions — a handful of states (for example Illinois, Pennsylvania, Mississippi) exclude qualified pension and IRA distributions entirely, with no dollar cap; in these states a traditional-to-Roth conversion is likewise not taxed.
- Capped exclusions — many states exclude the first $N of retirement distributions (for example a $20,000 private-pension exclusion, or larger age-tiered caps), sometimes with a lower cap for a younger age band.
- Age gates — exclusions frequently apply only at or above a threshold age.
- AGI cliffs and ramps — some states remove the exclusion entirely above an income limit, others phase it out ratably over an income range.
- Public vs. private pensions — certain states fully exempt government or employer-funded pensions while capping private pensions and IRAs. The optional
pensionTypeinput (public, private or military) routes the pension stream to the correct treatment; public/employer-funded pensions receive the full exemption where a state grants it, and military retirement pay gets each state's military rule (see Military retirement pay).
Social Security
As of the 2026 tax year, eight states still apply some tax to Social Security benefits (Colorado, Connecticut, Minnesota, Montana, New Mexico, Rhode Island, Utah, Vermont), each under its own statutory formula — a full exemption below an AGI threshold with a hard cliff above, a fixed partial inclusion, a ratable phase-out of the exemption, a phase-out credit, an age-plus-income test, or full federal conformity. West Virginia completes its phase-out to full exemption for 2026. The remaining 42 states and the District of Columbia do not tax Social Security. The engine owns this exemption: callers pass the federally-taxable benefit and the filer's age, and each state's real formula decides how much (if any) enters the state base.
Capital gains
Most states tax long-term capital gains at their ordinary rates. The engine also captures the exceptions:
- Flat-rate states (for example Pennsylvania) tax gains at the single statutory rate.
- A few states exempt investment income entirely (for example New Hampshire), so the ordinary/gain split changes the result.
- Washington levies a standalone capital-gains excise — 7% on long-term gains above a large standard deduction, plus an additional 2.9% above $1,000,000 of gain — despite having no income tax.
- Maryland adds a 2% capital-gains surcharge above a federal-AGI threshold; Massachusetts, California and (from 2026) Maine apply high-income surtaxes on top of the bracket tax — Maine's 2% surcharge starts at $1,000,000 of Maine taxable income for single filers, $750,000 married filing separately and $1,500,000 for joint filers and heads of household (Maine Revenue Services 2026 rate schedule).
- Montana taxes net long-term gains on its own two-rate schedule; Hawaii caps the tax on gains at an alternative rate; Vermont and New Mexico exclude a flat first slice of gain.
Federal-coupled bases and additional taxes
States that begin from federal taxable income are computed federal-first: the engine calculates the federal result, then hands the post-deduction federal taxable ordinary income and gains (and, where relevant, the year's federal tax liability) to the state engine, so conformity states inherit the real federal deduction stack rather than re-deriving a proxy. Two states allow a deduction for federal income tax paid (Alabama in full including the surtax, Oregon capped and phased out with income), and local income taxes are included when you choose a locality (an official code from GET /api/state-tax/localities, sent as localities): the planner computes that locality’s income tax with the state engine’s own locality rules and adds it to the state tax each year. Each kind of local tax reaches its own base: Pennsylvania’s local earned income tax reaches only earned income, so a retiree whose income is a pension owes $0 of it, while Philadelphia’s School Income Tax reaches unearned income such as dividends; New York City’s tax is figured on the New York return; a Maryland county applies its own rate or brackets to Maryland taxable income. Local rates and thresholds are held at their published year’s values in later years: the law holds 13 of the 15 kinds of local tax fixed, and the other two, Portland Metro’s CPI-indexed thresholds and Philadelphia’s scheduled wage-tax steps, are held too. Without a locality, Indiana and Maryland county taxes, which ride on the state taxable base, use the optional localTaxRate input (clamped to a reasonable range) or the state’s population-weighted county average, as before, and other states’ local income taxes are not included. Vermont's minimum tax is applied as well: above $150,000 of federal AGI the Vermont tax is at least 3% of federal AGI (32 V.S.A. §5822).
Couples: each spouse's own age
On a joint return many state rules test each spouse separately: a spouse who has reached the qualifying age claims the exclusion or deduction against their own income, and the younger spouse's income stays taxable. When a plan gives the spouse's age (the spouseAge input, or spouse.age on the state-tax API), the engine evaluates every such rule per spouse: the primary filer at their age, the spouse at theirs. Without a spouse age it keeps one household age for both, as before.
Income is attributed to each spouse from the API's per-spouse amounts when they are given. The planning app models the IRA and pension as household amounts. Its “Whose Income Is It?” setting (spouseSplit, a joint plan with a state and the spouse's age) says whose they are on the state return in every joint year: split evenly (the default, as on the calculators), all in one name, or by owner, where the traditional withdrawals and Roth conversions come from each spouse's own balance (the spouse's share of the traditional balance; each spouse's RMD from their own IRA and what is taken above the RMDs in proportion to what each holds above them, as the per-owner balances move) and each pension is its owner's. With a split the states that tax a couple by each spouse's own income (Arkansas, Delaware, Maryland, Minnesota, Missouri, North Dakota, Ohio and Virginia) apply those rules. Without one (no spouse age, or an API request that omits it) the engine splits the IRA and pension equally between the spouses and applies those couple rules only in years with wages or self-employment income (with the spouse's age stated); Social Security, interest and gains, which the engine carries as household totals, are split equally in every case. For jointly owned investment income that equal split is what several states' own instructions direct, for example Delaware ("The income from these joint accounts would be split equally").
The per-spouse rules the engine applies, with the source that states each one:
- Per-spouse retirement exclusions against the spouse's own income: Alabama (Schedule RS, "each taxpayer is eligible up to $6,000"), Arkansas (AR1000F instructions), Delaware (PIT-RES instructions), Georgia (Retirement Income Exclusion, "each must qualify on a separate basis"), Iowa (retirement income guidance), Kentucky (Schedule P), Louisiana (LAC 61:I.1311), Maryland (resident booklet, "a separate column must be completed for each spouse"), Maine (income tax FAQ), Mississippi (FAQ), Missouri (RSMo 143.124), New York (IT-201 instructions, "neither of you can claim any unused part of your spouse’s exclusion"), Oklahoma (Form 511 packet), Rhode Island (Retirement Income Guide) and South Carolina's retirement deduction (RR 21-13).
- One joint cap per return: Michigan applies one joint limit to either spouse's income and uses the older spouse's age where age still matters (RAB 2026-1). New Jersey gives the full joint exclusion when either spouse is 62, but "you can exclude only the pension, annuity, or IRA withdrawal of the qualified spouse" (NJ Division of Taxation). Wisconsin pools $48,000 when both spouses are 67 or older and otherwise allows $24,000 against the qualifying spouse's own income (WI DOR practitioner Q&A).
- Colorado's pension and Social Security subtraction "is computed separately for each spouse", each at their own age band (CO DOR). Before this change the engine applied one $20,000/$24,000 cap to the whole couple, which under-stated the exclusion for couples.
- Age-based deductions and credits per qualifying spouse: Illinois (IL-1040 instructions), Indiana (IN DOR), Delaware (30 Del. C. §1110), Mississippi (MS DOR), Montana (Form 2), South Carolina's age-65 deduction, which "is not traced separately for each spouse" (SC DOR), and Virginia's age deduction, $12,000 per 65-or-older spouse reduced once by the couple's combined income over $75,000 (Va. Code §58.1-322.03). West Virginia's $8,000 senior modification is limited to the qualifying spouse's own income (IT-140 instructions).
- Social Security: Rhode Island's modification applies only to the portion of benefits belonging to a spouse at full retirement age, and Missouri's public-pension exemption is reduced by each 62-or-older spouse's own Social Security exemption (Form MO-A).
Military retirement pay
Military retirement pay is its own income type in the engine (pensionType "military" in the planner, pensionMilitary on the state-tax API), separate from government and private pensions, because most states treat it differently from both. Each state's 2026 rule is applied per retiree, at the retiree's own age: 28 jurisdictions exempt it in full, 10 exempt part of it (a dollar cap, an age tier, an income test, or a credit), 4 tax it under their general pension rules, and 9 have no tax on wages or pensions. Where a state's 2026 guidance is not yet published, the latest official figures are used. Where the military amount reduces another benefit (Arkansas, Michigan, South Carolina, West Virginia) the engine applies that reduction. Military pay a state does not exempt is treated as an ordinary government pension for that state's general retirement rules.
| Jurisdiction | Military retirement pay, 2026 | Official source |
|---|---|---|
| Alabama | Exempt | source |
| Alaska | No income tax | source |
| Arizona | Exempt (since 2021) | source |
| Arkansas | Exempt; the amount uses up the retiree's $6,000 general retirement exemption | source |
| California | Up to $20,000 per return, only at federal AGI up to $125,000 ($250,000 joint) | source |
| Colorado | Under 55: up to $15,000; 55 and older: counts toward the general $20,000/$24,000 pension subtraction | source |
| Connecticut | Exempt | source |
| Delaware | Under 60: up to $12,500; 60 and older: counts toward the general $12,500 exclusion | source |
| District of Columbia | Taxable (the $3,000 exclusion ended after 2014) | source |
| Florida | No income tax | source |
| Georgia | Under 62: up to $17,500, or $35,000 with over $17,500 of Georgia earned income; 62 and older: counts toward the Retirement Income Exclusion | source |
| Hawaii | Exempt | source |
| Idaho | 62 and older: up to $49,824 single / $74,736 joint per return (2026: the maximum Social Security benefit at full retirement age the statute pegs it to), less Social Security received | source |
| Illinois | Exempt | source |
| Indiana | Exempt | source |
| Iowa | Exempt | source |
| Kansas | Exempt | source |
| Kentucky | No separate rule: counts toward the general $31,110 pension exclusion | source |
| Louisiana | Exempt | source |
| Maine | Exempt | source |
| Maryland | Under 55: up to $12,500; 55 and older: up to $20,000; the rest can use the 65+ pension exclusion | source |
| Massachusetts | Exempt | source |
| Michigan | Exempt; the amount reduces the general retirement deduction limit | source |
| Minnesota | Exempt | source |
| Mississippi | Exempt | source |
| Missouri | Exempt | source |
| Montana | Taxable in the engine; the Working Military Retirement Exemption depends on residency history and earned income, which are not modeled | source |
| Nebraska | Exempt | source |
| Nevada | No income tax | source |
| New Hampshire | No tax on wages or pensions | source |
| New Jersey | Exempt | source |
| New Mexico | Up to $30,000 per retiree | source |
| New York | Exempt (a United States government pension) | source |
| North Carolina | Exempt for 20 or more years of service or a medical retirement | source |
| North Dakota | Exempt | source |
| Ohio | Exempt | source |
| Oklahoma | Exempt | source |
| Oregon | Taxable in the engine; only the share for service before October 1991 is subtractable, which is not modeled | source |
| Pennsylvania | Exempt | source |
| Rhode Island | Exempt | source |
| South Carolina | Exempt; the amount reduces the retiree's own retirement and age-65 deductions | source |
| South Dakota | No income tax | source |
| Tennessee | No income tax | source |
| Texas | No income tax | source |
| Utah | Taxed, then a credit per person on the military pay (4.45% in the engine) | source |
| Vermont | Exempt up to federal AGI $125,000, phased out to $175,000 | source |
| Virginia | Up to $40,000 per person, any age | source |
| Washington | No income tax | source |
| West Virginia | Exempt; the amount reduces the $8,000 senior modification | source |
| Wisconsin | Exempt | source |
| Wyoming | No income tax | source (Title 39: the income-tax chapter is repealed; read from an archived copy of that page) |
Survivor Benefit Plan annuities follow the retiree's rule in most states. The exceptions the engine does not apply automatically: California gives them a separate $20,000 exclusion (RTC §17132.10), Missouri treats them as a public pension rather than military retirement (MO DOR Military Reference Guide), and the District of Columbia excludes federal survivor benefits at 62 and older (D.C. Code §47-1803.02). An SBP annuity in those jurisdictions should be entered as the pension type the jurisdiction treats it as.
Three state rules depend on facts the inputs do not carry, so the engine takes the higher-tax reading: Montana's working-retiree exemption (residency history and Montana earned income), Oregon's subtraction for service before October 1991, and Kentucky's full exclusion for service credit earned before 1998 (Schedule P). Idaho's deduction for retirees under 62 who still work is likewise not applied.
Wages and earned income
Wages and net self-employment income are ordinary income in every state. Three states treat them differently from other ordinary income in ways the engine models:
- Georgia: up to $5,000 of each qualifying person's earned income counts toward the Retirement Income Exclusion, inside its $35,000/$65,000 cap (GA DOR, "Up to $5,000 of earned income"). A military retiree under 62 with more than $17,500 of Georgia earned income gets an additional $17,500 military exclusion (same source).
- Wisconsin: the married couple credit is 3% of the lower-earning spouse's earned income, at most $480 (Wis. Stat. §71.07(6)). Claiming the age-67 retirement subtraction forfeits the credit (WI DOR), so the engine grants it only when that subtraction is not taken.
- Ohio: the joint filing credit needs at least $500 of qualifying income, which includes wages but not interest, dividends or gains, from each spouse; it is 5% to 20% of the tax, at most $650 (Ohio IT 1040 instructions).
The two couple credits need each spouse's own earnings, so they apply only when the per-spouse amounts are given. Age deductions that apply to income from any source also cover wages: South Carolina's age-65 deduction, Virginia's age deduction and West Virginia's senior modification, the last limited to the qualifying spouse's own income. Not modeled: state earned income tax credits, which depend on children and income tests outside the engine's inputs; local taxes that reach only earned income, such as Pennsylvania's local earned income tax (PA DCED) and Ohio municipal and earned-income school district taxes (Ohio Department of Taxation); state payroll levies such as California SDI (EDD); and the per-spouse marriage-penalty adjustments of Minnesota, North Dakota, Maryland and Virginia, which count all income rather than earnings.
Roth Conversion Optimizer
Two modes are supported for a user-entered conversion plan:
- FIXED — convert a constant dollar amount each year from
rothConvStartAgethroughrothConvEndAge(both ages included). - BRACKET_FILL — convert up to the marginal federal bracket ceiling (e.g. the top of 12% or 22%). Amount varies annually with other income.
Conversions add to ordinary income in the year they occur, raising tax and potentially IRMAA tier. The simulator captures this interaction by re-running the full federal+state+Medicare pipeline per year.
When no conversion plan is entered, Tax-Aware Mode's whole-retirement policy search (Section 19) also considers six candidates that pair a withdrawal order with a recommended Roth-conversion rule of its own — the same FIXED/BRACKET_FILL-style sizing described above, chosen automatically per household rather than typed in. The two are mutually exclusive per run: entering a plan here disables the recommended-conversion candidates and the search instead recommends only among withdrawal orders, honoring the plan exactly as configured.
Qualified Charitable Distributions (QCD)
For filers aged $\geq 70\tfrac{1}{2}$ (IRC §408(d)(8)(B)(ii): the owner “has attained age 70½”), up to $111,000 per IRA owner (2026 cap, inflation-indexed and rounded to the nearest multiple of 1,000 dollars — up from $108,000 in 2025) of IRA distributions can be directed to charity and excluded from gross income. On a joint return each spouse who is 70½ or older may exclude up to the limit from their own IRA (IRS Publication 590-B). When you enter your spouse’s share of the traditional balance, each spouse’s QCD comes out of their own IRA and counts against their own RMD; without it the simulator holds one household traditional balance, so it assumes each such spouse gives from IRA money of their own. QCD reduces AGI, lowering both federal tax and the IRMAA premium tier. The simulator applies the QCD against the required minimum distribution first — a QCD satisfies the RMD without generating taxable income — then treats any remaining distribution normally.
Medicare-Specific Inflation (IRMAA)
Medicare premiums and IRMAA thresholds have historically outpaced core CPI by 1–3 percentage points. Users can decouple the Medicare inflation rate from the headline rate (medicareInflationRate). Defaults use the Medicare Board of Trustees projections; empirical calibration lives in backend/data/medicare/.
IRMAA Two-Year Lookback Projector (/irmaa-projector/)
The IRMAA bracket lookup is a step function in MAGI with a fixed two-year lag between the tax year and the Medicare premium year. The projector accepts a year-by-year MAGI schedule from the user, identifies the lookback MAGI for each premium year (premium year t uses MAGI from year t−2), and applies the 2026 CMS bracket table to produce the projected per-month surcharge plus annual totals. Both single and MFJ filing statuses are supported; for MFJ households where both spouses are Medicare-enrolled, the per-person surcharge is doubled. The Form SSA-44 life-changing-event flow is documented inline so users can identify qualifying situations.
The math is a deterministic table lookup with the 2-year offset and the optional "both spouses on Medicare" multiplier; there's no optimization here, only projection. The free tier offers a 3-year horizon; the PRO tier extends to 10 years and integrates with the bridge optimizer (below) for conversion-window timing.
ACA Marriage Penalty Calculator (/aca-marriage-penalty/)
The marriage penalty under the 400% FPL cliff, back for 2026 now that the 2021–2025 enhanced credit has expired, arises because the household-of-two FPL ($84,600 in 2026) is roughly 1.35× the household-of-one threshold ($62,600), not 2×. A two-earner couple with $60k each crosses the cliff jointly but stays under it filing separately. The calculator enumerates 4–6 filing+coverage scenarios (MFJ both ACA, MFJ A-employer-B-ACA, unmarried both ACA, unmarried A-employer-B-ACA, MFJ A-Medicare-B-ACA, MFJ both Medicare) and ranks them by total annual cost (premium + federal tax + IRMAA where applicable).
State-specific Silver-benchmark premiums are KFF’s 2026 state averages for a 40-year-old (KFF, Marketplace Average Benchmark Premiums, checked 2026-09-28). This is a modelling input, not a government figure: no government source publishes a 2026 benchmark for every state. CMS’s own series (QHP Choice and Premiums in HealthCare.gov Marketplaces) stops at plan year 2025 and covers HealthCare.gov states only; for those 31 states KFF’s 2025 figures match CMS’s to within $0.50. A state average is not your own benchmark, which depends on your county and rating area, so your actual credit can differ. The averages are scaled by the CMS 45 CFR 147.102 age-rating curve (3:1 from age 21 to 64). Medicaid expansion status is encoded for all 50 states + DC; non-expansion states trigger a coverage-gap detection when MAGI < 100% FPL. The scenario engine handles the constraint that Medicare-age (≥65) household members cannot be on ACA marketplace plans.
ACA Bridge Optimizer (/aca-bridge-optimizer/)
The bridge optimizer solves the joint multi-year decision problem: given a household's portfolio split (traditional / Roth / taxable), required annual cash-out for living expenses, chronic-condition healthcare cost band, target FPL ceiling, and state of residence, find the year-by-year Roth conversion amounts that minimize lifetime cost (federal + state tax + healthcare net of subsidy + IRMAA from the 2-year lookback) over the bridge from current age through the year you turn 65.
Problem class. The decision variables are the Roth conversion amounts, one per plan year (at most 25); each year's withdrawals follow from them (any required minimum distribution first, then taxable, Roth and traditional). The objective is non-convex, non-smooth, and includes cliff discontinuities at 400% FPL (full subsidy forfeiture), 138% FPL (Medicaid eligibility edge), and the five IRMAA surcharge thresholds. Federal and state tax are piecewise-linear with kinks at bracket boundaries. The cash-flow constraint couples decisions across buckets within each year; the IRMAA constraint couples decisions across years via the 2-year lookback.
Solver architecture. Two tiers:
- Free tier — per-year greedy heuristic. Each year, the algorithm computes a fixed-point iteration over (taxable withdrawal, Roth withdrawal, traditional withdrawal, Roth conversion) until cash-flow, MAGI, healthcare cost, and tax all converge mutually (typically <8 iterations, contractive because higher conversion → higher tax → larger cash need → larger withdrawals → larger LTCG MAGI → shrunk headroom → smaller conversion).
- PRO tier — joint nlopt ISRES + SBPLX refinement. Warm-started from the greedy result, the optimizer uses nlopt's ISRES (Improved Stochastic Ranking Evolution Strategy — gradient-free, handles non-smooth constraints) at high population, followed by a deterministic SBPLX local-refinement pass to tighten the result. Because neither pass is run to convergence, the search also starts SBPLX from each baseline plan and from plans that keep every year just under or just over the Medicaid/marketplace boundary or just under the 400% cliff, moves each year onto those boundaries one at a time, and polishes the best point; the cheapest candidate wins. The FPL ceiling is a hard limit, not a penalty: each year's conversion is capped so that ACA MAGI stays at or under it. The final plan never costs more, by the optimizer's own lifetime-cost measure, than the greedy plan, the never-convert plan, or the naive fill-the-12%-bracket plan when that plan stays within your ceiling: if one of them is cheaper, it is returned as the recommendation and labelled as such.
Healthcare model. Chronic-condition out-of-pocket bands are QuantCalc's own model parameters (~$3k/yr for one mild condition, ~$8k/yr for 2–3 conditions, ~$18k/yr for 3+ severe), calibrated against the out-of-pocket spending distribution the Peterson-KFF Health System Tracker publishes (healthsystemtracker.org, checked 2026-09-10). KFF does not publish these bands. Premium subsidy follows the 2026 statutory applicable-percentage curve as indexed by IRS Rev. Proc. 2025-25 §3.01 (2.10% of income at ≤133% FPL, scaling to a flat 9.96% across 300–400% FPL, cliff above). The ARPA/IRA enhanced schedule (0%–8.5%, no cliff) expired after 2025 and is not modeled as current law. Medicaid (≤138% FPL in expansion states) and the coverage gap (≤100% FPL in non-expansion states) are detected and modeled separately. The model makes one exception among the non-expansion states: Wisconsin, where BadgerCare Plus covers adults up to 100% FPL (Wisconsin DHS, BadgerCare Plus income limits: “Adult monthly income limit (100% FPL)”, checked 2026-09-28), so a Wisconsin household at or below 100% FPL is modeled as covered, not uninsured.
State tax. Uses the same 51-jurisdiction engine as Section 25, with the user's MAGI split between ordinary income (other income + traditional withdrawal + conversion) and LTCG (taxable-account withdrawal × gain fraction). Most states tax LTCG at ordinary rates; a handful (e.g., NH) exempt investment income and the split matters.
Verification. The C implementation carries 73 unit tests covering cliff respect across many scenarios, infeasibility handling, money conservation (no money created or destroyed by the simulation), stochastic-run stability, naive-baseline domination, and state-tax variance. The frontend JS module carries an additional 44 tests on the greedy math. Both run as part of the deploy gate.
26. Randomized QMC & Wilson CI
Cranley-Patterson Scrambling
Unscrambled Sobol sequences are deterministic — two runs with the same inputs produce identical output and give no Monte Carlo standard-error estimate. With Sobol Scrambling enabled, each dimension is rotated by a random offset $r_d \sim U[0,1)$:
This preserves the low-discrepancy property while randomizing the realization (Cranley & Patterson 1976). Running $K$ independent scrambled replicates gives an unbiased estimate of the QMC error.
When Sobol is not in use. Three settings bypass the Sobol sequence entirely, and scrambling has nothing to act on in any of them: Fat-Tail Returns and regime switching both replace the draws with pseudo-random ones (the regime volatility multiplier destroys the low-discrepancy property, so keeping Sobol would be worse than not), and the Historical Bootstrap return model draws historical months directly and never touches the normal array at all. Under any of the three, $K$ replicates return $K$ identical answers. The scrambling toggle is disabled while the bootstrap preset is active, and the “Assumptions used” panel reports the sampler the run actually used rather than the one requested.
Wilson 95% Confidence Interval on Success Rate
With $N$ simulations and $k$ successes, the normal-approximation CI $\hat p \pm 1.96 \sqrt{\hat p(1-\hat p)/N}$ degrades badly when $\hat p$ is near 0 or 1. The Wilson score interval stays valid across the full range:
where $z = 1.96$. QuantCalc displays this CI next to every success-rate metric.
Pre-Computed Sobol Cache
At container-build time we generate a 10,000-sample × 6,480-dim Sobol cache using QuantLib's Joe-Kuo D7 direction numbers. Dimensions: 9 per month × 720 months (5 asset-return dimensions + 4 inflation-category dimensions), covering the widest model configuration.
27. Withdrawal Rules
Every simulation applies one withdrawal rule to the planned spending. The rule decides how much is taken from the portfolio each year; the tax-aware order (Part III) decides from which accounts. In Tax-Aware Mode the rule's amount is the year's after-tax spending; the engine withdraws that amount plus the year's taxes. One consequence for VPW: it amortises the balance as after-tax spending while taxes are drawn on top, so in Tax-Aware Mode a VPW plan can reach zero before the horizon, which the standard engine's VPW cannot. A second consequence, for Guyton-Klinger: the guardrail's withdrawal-rate test (current spending divided by the current portfolio, compared with the initial rate) keeps running on the after-tax spending amount, not on the grossed-up withdrawal that actually leaves the portfolio — so in Tax-Aware Mode the measured rate reads lower than a gross-withdrawal-over-portfolio reading would, and a guardrail cut or raise fires later than that gross reading would suggest. Guardrails and VPW run in Tax-Aware Mode (the rule sets each year's spending target; the tax-aware order chooses which accounts fund it); the bucket rule is fixed-path only, because it chooses which assets are sold — the decision the tax-aware order makes for itself. Dynamic rules are ignored when a multi-period glide path is set.
Fixed real (the 4% rule family)
The first year's spending is taken in dollars and indexed to the simulated inflation path every year thereafter, regardless of portfolio performance. This is the default and the baseline every other rule is compared against in the withdrawal-strategies study.
Guyton-Klinger guardrails
The initial withdrawal rate is recorded at retirement. Each year the current withdrawal rate (planned spending divided by the current portfolio) is compared with it. When the current rate rises above 120% of the initial rate, spending is cut by 10%; when it falls below 80% of the initial rate, spending is raised by 10%; otherwise spending is indexed to inflation. The cut is suppressed inside the final 15 years of the plan (the capital-preservation rule). Because the rule is closed-form, the two guardrail portfolio levels on page 1 of the client report are computed exactly: a cut fires below the retirement portfolio divided by 1.20, a raise above the retirement portfolio divided by 0.80. The report's survival rate under this rule is the rule's survival; the realised-spending distribution shows what the rule actually paid out.
Variable percentage withdrawal (VPW)
Each year's spending is the amortised payment of the remaining portfolio over the remaining horizon at the plan's assumed real return, so spending rises and falls with markets and cannot exhaust the portfolio before the horizon by construction. Survival is not the relevant measure for VPW; the realised-spending distribution is.
Bucket (cash reserve)
At retirement a chosen number of years of planned spending (one to ten, default three) is set aside in the plan's lowest-volatility asset and drawn on first; the rest stays invested at the plan's allocation and is rebalanced annually. The reserve is refilled to its target at year end either after any non-losing year or only when it has fallen below half its target. Spending itself follows the fixed-real rule, so the survival rate compares directly with fixed real. The apples-to-apples comparison against a total-return portfolio holds the same starting cash in both arms; see the bucket-strategy study.
Constants and formulas mirror js/guardrails.js and backend/src/monte_carlo.h; the three-way comparison of tent, bucket and guardrails on identical paths is in the sequence-risk defences study.
28. Implementation Notes
For $N$ simulations over $T$ months with $n$ assets, random numbers needed: $N \times T \times n$. For 10,000 sims × 720 months × 5 assets = 36 million random numbers. Stochastic inflation adds up to $4 \times 720 \times N$ more when method #3 is active.
Optimizations: Pre-generate random numbers in batch, vectorized operations, pre-compute Cholesky factors (asset returns and inflation categories), fixed seed during optimization, OpenMP parallelization of the per-simulation loop.
29. References
- Glasserman, P. (2003). Monte Carlo Methods in Financial Engineering. Springer.
- Jorion, P. (2006). Value at Risk. McGraw-Hill.
- Nocedal, J. & Wright, S. (2006). Numerical Optimization. Springer.
- Kraft, D. (1988). "A software package for sequential quadratic programming." DFVLR-FB 88-28.
- Sobol, I.M. (1967). "On the distribution of points in a cube." USSR Comp. Math. & Math. Phys.
- Joe, S. & Kuo, F.Y. (2008). "Constructing Sobol sequences with better two-dimensional projections." SIAM J. Sci. Comput.
- Cranley, R. & Patterson, T.N.L. (1976). "Randomization of number theoretic methods for multiple integration." SIAM J. Numer. Anal.
- Hamilton, J.D. (1989). "A new approach to the economic analysis of nonstationary time series and the business cycle." Econometrica.
- Politis, D.N. & Romano, J.P. (1994). "The stationary bootstrap." J. American Statistical Association.
- Ang, A. & Piazzesi, M. (2003). "A no-arbitrage vector autoregression of term structure dynamics with macroeconomic and latent variables." J. Monetary Economics.
- Fama, E.F. & Gibbons, M.R. (1984). "A comparison of inflation forecasts." J. Monetary Economics.
- Bekaert, G. & Wang, X. (2010). "Inflation risk and the inflation risk premium." Economic Policy.
- Milevsky, M.A. (2020). Retirement Income Recipes in R. Springer.
- Wilson, E.B. (1927). "Probable inference, the law of succession, and statistical inference." JASA.
- US Bureau of Labor Statistics — CPI series CPIAUCSL, CPIMEDSL, CUSR0000SAE, CUSR0000SAH (FRED).
A. Editorial Standards
QuantCalc's articles and calculators are written and maintained by the QuantCalc Research team. The same engineering team that maintains the simulation backend also writes the public-facing research — there is no separate editorial layer paraphrasing technical content for a general audience.
Verification process
- Primary-source-first: every numerical fact (tax brackets, FPL thresholds, IRMAA tiers, RMD divisors, contribution limits) is verified against the originating government publication, not against a secondary source aggregator. Each article's "Primary sources cited" block links directly to the IRS, SSA, CMS, HHS, or congressional bill text it relies on.
- Computed against the backend: any worked example or scenario in an article is computed using the same C backend the calculators run on. If the math in the article disagrees with the calculator, the article gets corrected.
- Forecast inputs are publicly cited: capital-market expectations (return, volatility, correlation) are sourced from six named investment firms (BlackRock, JPMorgan, Vanguard, GMO, Schwab, Invesco) whose 2026 publications are linked in §5 above. We do not modify these except for the documented GMO real→nominal conversion.
- Update on rule change: when a tax-law or regulatory change is signed (e.g., the One Big Beautiful Bill Act of July 2025, the SECURE 2.0 Act of December 2022), affected articles are updated within 30 days. The "Last reviewed" date on each post reflects the most recent verification pass.
Review cadence
- Annual review — every article is reviewed at least once per calendar year for accuracy against the new tax-year brackets, FPL guidelines, and Medicare premium adjustments. The "Last reviewed" date stamp on each article shows the most recent pass.
- Event-triggered review — when a primary source releases new data (IRS Rev. Proc., CMS annual notice, HHS poverty guidelines, OBRA/OBBBA-class legislation), all affected articles are re-verified within 30 days.
- User-flagged corrections — readers can email [email protected] to flag a specific number; we investigate within 7 days and either correct or document why the existing figure stands.
What you will not find here
- Personalized financial advice. QuantCalc is an educational research tool. We do not know your tax situation, employer plan details, or risk tolerance. A scenario shown by the calculator is one of 10,000 possible paths, not a recommendation.
- Pay-to-play product reviews. When an article mentions a brokerage, fund family, or competing planning tool, we have no commercial relationship with them. There are no affiliate links in our content; the only revenue path is a one-time PRO unlock for our own calculator.
- Backdated edits hidden from readers. Material corrections are dated; the
dateModifiedfield in each article's JSON-LD reflects the actual file mtime, and "Last reviewed" dates appear in the post-meta strip.
Author
QuantCalc Research is the engineering and research team behind QuantCalc. The team's published methodology covers Monte Carlo simulation with quasi-Monte Carlo sampling (Sobol sequences), Cholesky-decomposed correlated returns, log-normal asset return modeling, regime-switching volatility, stochastic inflation with category-specific drift, federal and state tax computation from the IRS's and each state's published rules, and SECURE 2.0-aware RMD/IRMAA modeling. See sections 2-15 above for the full technical specification.
For questions, corrections, or research collaboration: [email protected].
Ready to run your own simulation?
QuantCalc runs this methodology on its servers from the inputs you enter — no account needed, and your inputs are not stored after the run (what is sent and logged).
Open QuantCalc →