# The retirement projection model [`zfin projections`](../reference/cli/projections.md) simulates your retirement portfolio against real market history. This page explains the model so you can trust -- and correctly distrust -- its output. For how to configure it, see the [`projections.srf` reference](../reference/config/projections-srf.md) and [Plan for retirement](../guides/plan-retirement.md). ## Historical simulation, not a formula Rather than assume a single average return, zfin replays your portfolio through actual historical sequences drawn from the **Shiller dataset** (US equity total returns and CPI back to 1871). Each simulated run uses a real historical path of returns and inflation, so the spread of outcomes reflects real sequences -- including bad-timing sequences like retiring into 1929, 1973, or 2000. This is the same family of method as FIRECalc. ## Two phases Every projection runs the same two phases in order: 1. **Accumulation** -- contributions added each year, no spending. Its length comes from your retirement-date input. With no input, it's zero years (an already-retired view). 2. **Distribution** -- annual spending withdrawn (CPI-adjusted by default), no contributions. Its length is the configured `horizon`. [Life events](../reference/config/projections-srf.md#event-fields) (Social Security, pensions, tuition, healthcare) adjust the cash flow in both phases. ## How inflation is handled Inflation isn't a fixed assumption. Each historical cycle uses that start year's **actual CPI sequence** alongside its actual returns (the Shiller dataset carries both), so a cycle beginning in 1966 replays 1966's stagflation while one beginning in 2009 replays low-inflation years. The simulation runs in **nominal dollars**, which means the output mixes two units -- and knowing which is which is the difference between a sensible plan and a badly misread one: - **Flows are entered in today's dollars and inflated forward.** Your `annual_contribution`, `target_spending`, and inflation-adjusted life events are amounts in *today's* dollars; each simulated year the model multiplies them by that cycle's cumulative CPI, holding their purchasing power constant. Set `contribution_inflation_adjusted`, `target_spending_inflation_adjusted`, or an event's `inflation_adjusted` to `false` to pin a flow at a flat nominal amount instead (e.g. a fixed pension with no COLA). - **Safe-withdrawal figures are in today's dollars.** "You could spend ~$264k/yr at 99%" means ~$264k of *today's* purchasing power, with the actual dollar amount rising each retirement year to keep pace with inflation. - **Portfolio and terminal values are nominal (future dollars).** The "Median portfolio at retirement" and the `Terminal Portfolio Value (nominal, ...)` percentiles are **not** inflation-adjusted. A ~$244M median balance 50 years out is heavily inflated dollars, not $244M of today's purchasing power -- judge it against the inflated spending it has to support, never against today's prices. This split is deliberate and matches FIRECalc: you plan spending in real (today's) terms while the balance compounds in nominal terms. ## Percentile bands Across all the historical runs, zfin reports the distribution of outcomes rather than a single number: - **p10 (pessimistic)** -- only 10% of histories did worse. - **p50 (median)** -- the middle outcome. - **p90 (optimistic)** -- only 10% did better. ``` Terminal Portfolio Value (nominal, at 99% withdrawal rate) 25 Year 35 Year Pessimistic (p10) $6,739,560.02 $11,597,557.94 Median (p50) $30,023,255.68 $66,794,741.87 Optimistic (p90) $103,184,321.05 $279,372,182.75 ``` The wide spread is the point: it shows sequence-of-returns risk honestly instead of hiding it behind an average. ## Confidence and safe withdrawal The **Safe Withdrawal** table answers "how much could I spend and still not run out?" at chosen confidence levels (90/95/99%). A 99% safe withdrawal is the spending level that survived 99% of historical sequences over that horizon -- the most conservative. Higher confidence and longer horizons both lower the safe number. ## The earliest-retirement search When you set a `target_spending` instead of a date, zfin inverts the question: for each (horizon x confidence) cell it searches for the **earliest** accumulation length (up to 50 years) that sustains your spending, and renders the grid of answers. One cell is promoted to the headline (see [promotion rules](../reference/config/projections-srf.md#the-two-retirement-planning-inputs)). If no length within the cap works, the cell is **infeasible** -- shown honestly rather than fudged. ## The caveat that matters most zfin states this loudly by design, and so does this page: > The actuals overlay and evaluation views > (`--overlay-actuals`, `--convergence`, `--return-backtest`) tell you > whether the model was **directionally honest** -- did your real > trajectory fall within the bands it would have drawn. They do **not** > tell you whether a safe-withdrawal claim is **accurate**. An SWR > claim is a 30-year claim; there is at most ~12 years of weekly > history and a year or two of native snapshots to check it against. > No one will have data to validate a full-retirement SWR within our > lifetimes. Treat the projection as a disciplined way to compare scenarios and visualize sequence risk -- not as a promise about your specific future. ## Assumptions to keep in mind - **Allocation** is a single stock/bond blend (`target_stock_pct`), not your exact holdings. - **Inflation** comes from each historical cycle's own CPI; flows are real (today's-dollar) and balances are nominal. See [How inflation is handled](#how-inflation-is-handled). - **Taxes** are not modeled. Withdrawal figures are pre-tax. - **Imported-value overlays** scale today's allocation to a historical total when lot-level history isn't available, because a `liquid::` row can't reconstruct past composition. ## See also - [Plan for retirement](../guides/plan-retirement.md) -- the guided walkthrough. - [`projections.srf` reference](../reference/config/projections-srf.md) -- every input. - [`zfin projections`](../reference/cli/projections.md) -- flags and evaluation views.