142 lines
8.6 KiB
Markdown
142 lines
8.6 KiB
Markdown
# `projections.srf` reference
|
|
|
|
`projections.srf` configures [`zfin projections`](../cli/projections.md):
|
|
the Monte-Carlo-style retirement simulation run over the Shiller
|
|
dataset (1871-present). zfin loads it from the same directory as the
|
|
portfolio. It is optional -- without it, the command runs with
|
|
sensible defaults (20/30/45-year horizons, 90/95/99% confidence,
|
|
no accumulation phase).
|
|
|
|
This page is the field reference. For how the simulation actually
|
|
works see [The retirement projection model](../../explanation/projections-model.md);
|
|
for a guided setup see [Plan for retirement](../../guides/plan-retirement.md).
|
|
|
|
## Record types
|
|
|
|
Every line starts with a `type::` discriminator:
|
|
|
|
| `type::` | Purpose |
|
|
|-------------|---------------------------------------------------------------------------------------------------|
|
|
| `config` | A single configuration field (allocation, horizon, retirement target, contributions, spending). |
|
|
| `birthdate` | A household member's birthdate (drives ages, `horizon_age`, `retirement_age`, life-event timing). |
|
|
| `event` | A life event: recurring income or expense (Social Security, pension, tuition, healthcare). |
|
|
|
|
```srf
|
|
#!srfv1
|
|
type::config,target_stock_pct:num:80
|
|
type::config,horizon:num:25
|
|
type::config,horizon_age:num:95
|
|
type::birthdate,date::1981-04-12
|
|
type::event,name::Social Security,start_age:num:70,amount:num:38400
|
|
```
|
|
|
|
## `config` fields
|
|
|
|
| Field | Type | Description |
|
|
|--------------------------------------|------|--------------------------------------------------------------------------------------------------------------------------------|
|
|
| `target_stock_pct` | num | Asset-allocation target (0-100). Sets the simulation's stock/bond blend. |
|
|
| `horizon` | num | Distribution-phase length in years. Repeat the line for multiple horizons. |
|
|
| `horizon_age` | num | Horizon expressed as an age; resolves to `target_age - oldest_current_age`. Repeatable. |
|
|
| `retirement_age` | num | Age the **oldest** configured person must reach to retire. |
|
|
| `retirement_at` | date | Absolute retirement date (`YYYY-MM-DD`). Wins over `retirement_age` if both set. |
|
|
| `annual_contribution` | num | Yearly accumulation-phase contribution, in today's dollars. |
|
|
| `contribution_inflation_adjusted` | bool | If `true` (default), contributions grow with CPI year over year. |
|
|
| `target_spending` | num | Desired retirement spending, in today's dollars. |
|
|
| `target_spending_inflation_adjusted` | bool | If `true` (default), target spending grows with CPI during distribution. |
|
|
| `retirement_target` | num | Annotation on a `horizon`/`horizon_age` line that overrides the earliest-retirement promotion rule. Allowed: `90`, `95`, `99`. |
|
|
|
|
## `birthdate` fields
|
|
|
|
| Field | Type | Description |
|
|
|----------|------|----------------------------------------------------|
|
|
| `date` | date | Birthdate (`YYYY-MM-DD`). |
|
|
| `person` | num | Household member (`1` default, `2` for a partner). |
|
|
|
|
```srf
|
|
type::birthdate,date::1981-04-12
|
|
type::birthdate,date::1983-09-08,person:num:2
|
|
```
|
|
|
|
## `event` fields
|
|
|
|
Life events modify annual cash flow in both phases. Positive amounts
|
|
are income (offset withdrawals); negative amounts are expenses (added
|
|
to withdrawals).
|
|
|
|
| Field | Type | Description |
|
|
|----------------------|--------|-----------------------------------------------------------------------------------------|
|
|
| `name` | string | Label shown in the Life Events table. |
|
|
| `amount` | num | Annual amount. Positive = income, negative = expense. |
|
|
| `start_age` | num | Age (of `person`) at which the event begins. |
|
|
| `duration` | num | Optional length in years. Omit for a permanent event. |
|
|
| `person` | num | Whose age `start_age` refers to (`1` default, `2` for a partner). |
|
|
| `inflation_adjusted` | bool | If `true` (default), the amount grows with CPI. Set `false` for a fixed nominal amount. |
|
|
|
|
```srf
|
|
# Permanent income starting at age 70
|
|
type::event,name::Social Security,start_age:num:70,amount:num:38400
|
|
|
|
# 4-year expense starting at age 50
|
|
type::event,name::College Tuition,start_age:num:50,duration:num:4,amount:num:-55000
|
|
|
|
# A partner's pension
|
|
type::event,name::Pension,start_age:num:65,person:num:2,amount:num:24000
|
|
```
|
|
|
|
## The two retirement-planning inputs
|
|
|
|
`projections.srf` answers a different question depending on which
|
|
inputs you set. This is the single most important thing to understand
|
|
about the file:
|
|
|
|
| You set... | zfin answers... | Display |
|
|
|----------------------------------------------------|-----------------------------------------|-----------------------------------------------------------------------|
|
|
| A target date (`retirement_age` / `retirement_at`) | "Given my date, what can I spend?" | Accumulation-phase block with a dated headline. |
|
|
| A target spending (`target_spending`) | "Given my spending, when can I retire?" | Earliest-retirement grid; one cell is promoted to the headline. |
|
|
| Both | Both, back to back | Configured date wins the headline; grid renders below for comparison. |
|
|
| Neither | Already-retired view | "Years until possible retirement: none". |
|
|
|
|
When `target_spending` is set, the **earliest-retirement grid** shows,
|
|
for each (horizon x confidence) pair, the earliest year that sustains
|
|
the spending. The default promotion rule picks the headline cell by
|
|
walking horizons longest-to-shortest at 99% confidence, preferring the
|
|
longest horizon that keeps the oldest person under age 100. Override it
|
|
with a `retirement_target` annotation on one horizon line:
|
|
|
|
```srf
|
|
# use the 35yr x 95% cell as the headline
|
|
type::config,horizon:num:35,retirement_target:num:95
|
|
```
|
|
|
|
At most one horizon may carry the annotation; configuring more than one
|
|
drops them all and falls back to the default rule. If the promoted cell
|
|
is infeasible (no accumulation length <= 50 years sustains the
|
|
spending), the headline reads "not feasible" and the grid still renders
|
|
so you can pick a workable anchor.
|
|
|
|
## The example configurations
|
|
|
|
The five bundled examples are fully-configured walkthroughs of each
|
|
combination:
|
|
|
|
| `examples/...` | Inputs |
|
|
|----------------------------------|---------------------------------------------------|
|
|
| `pre-retirement-age` | target date only |
|
|
| `pre-retirement-spending` | target spending only |
|
|
| `pre-retirement-spending-target` | target spending + an explicit (infeasible) anchor |
|
|
| `pre-retirement-both` | target date + target spending |
|
|
| `post-retirement` | neither (distribution-only) |
|
|
|
|
```bash
|
|
ZFIN_HOME=examples/pre-retirement-both zfin projections
|
|
```
|
|
|
|
## See also
|
|
|
|
- [Plan for retirement](../../guides/plan-retirement.md) -- guided setup.
|
|
- [The retirement projection model](../../explanation/projections-model.md) -- how the simulation works.
|
|
- [`zfin projections`](../cli/projections.md) -- command flags (`--as-of`, `--overlay-actuals`, `--convergence`, `--return-backtest`).
|
|
|
|
---
|
|
|
|
[Documentation home](../../README.md#reference)
|