add overlay information to README

This commit is contained in:
Emil Lerch 2026-05-13 13:07:10 -07:00
parent bacc01d9f4
commit dc956a2b8d
Signed by: lobo
GPG key ID: A7B62D657EF764F8

View file

@ -633,6 +633,71 @@ The Accumulation phase block reduces to a single soft
"Years until possible retirement: none" line; everything else
behaves like the legacy projection display.
### Realized actuals overlay (`--overlay-actuals`)
Run `zfin projections --as-of <DATE> --overlay-actuals` to plot the
**realized portfolio trajectory** from `<DATE>` up to today on top of
the projected percentile bands. Answers the question "how accurate
were my past projections compared to reality?"
The TUI is the high-fidelity surface — open the projections tab,
press `d` to set the as-of date, then press `o` to toggle the
overlay. The CLI prints a tip pointing at the TUI; the braille chart
itself doesn't render the overlay (the resolution doesn't do justice
to a 12+ year actuals trajectory laid against percentile bands).
**The overlay reads from two sources, snapshot-precedence:**
1. **Native snapshots** in `<portfolio-dir>/history/*-portfolio.srf`
— produced by `zfin snapshot`. Highest fidelity (full lot-level
state, exact totals).
2. **Imported values** in `<portfolio-dir>/history/imported_values.srf`
— a hand-maintained back-history file with one `liquid::` total
per date. Useful for backfilling a historical record from
spreadsheet data, statements, etc. Snapshots win on overlapping
dates.
**As-of resolution against either source.** `--as-of <DATE>`
resolves first against the snapshot directory (nearest-earlier
`*-portfolio.srf`); if no snapshot exists at or before the date,
it falls back to `imported_values.srf`. This means you can run
`zfin projections --as-of 2018-06-01` even with zero snapshot
files, as long as the imported back-history covers that date.
When the resolution lands on an imported value, the projection
bands are computed using **today's allocations scaled to the
imported liquid total** — we can't reconstruct the historical lot
composition from just a `liquid::` row, so today's stock/bond
split is substituted as the best-available approximation. The
header line reads `Projections (as of YYYY-MM-DD, imported value)`
and a muted note flags the scaling.
**How to read the chart:**
- **Actuals line stays inside the bands** → the model was
directionally honest.
- **Actuals line punches through the top band** → the model was
conservative (good problem to have).
- **Actuals line punches through the bottom band** → the model was
optimistic (bands need wider envelope, or a bear scenario was
underweighted).
- **A thin vertical "today" line** marks where the actuals end and
the projected future begins.
**Critical caveat (must be loud, by design):**
> This overlay shows whether the model was **directionally honest**,
> not whether the SWR claim was **accurate**. The SWR claim is a
> 30-year claim. We have at most ~12 years of weekly history
> (post-import) and 1+ years of native snapshots. The overlay tells
> you "did my actual trajectory fall within the bands the model would
> have drawn." It does **not** tell you "did the safe withdrawal rate
> hold up over a full retirement horizon." We will not have data to
> answer that within either of our lifetimes.
The TUI surfaces this caveat on a status line whenever the overlay is
active.
### Life events
Life events modify the simulation's annual cash flow. Positive