zfin/docs/guides/snapshots-and-history.md
Emil Lerch 6ebd944f94
All checks were successful
Generic zig build / build (push) Successful in 6m49s
Generic zig build / deploy (push) Successful in 20s
Generic zig build / publish-macos (push) Successful in 1m2s
additional snapshot documentation
2026-08-21 12:38:13 -07:00

154 lines
5.8 KiB
Markdown

# Snapshots and history
**Goal:** record your portfolio's value over time and review how it has
changed -- day to day, year over year, and between any two dates.
**You'll need:** a working portfolio. The
[`post-retirement`](../../examples/post-retirement/) example ships with
a `history/` folder of snapshots, so you can explore the read side
immediately:
```bash
ZFIN_HOME=examples/post-retirement zfin history
```
## The idea
zfin doesn't track your value automatically -- it reads what you have
*right now*. To build a time series, you write a **snapshot** each day
(or week), and the history/compare commands read those snapshots back.
Snapshots live in `<portfolio-dir>/history/<date>-portfolio.srf`. Each
is an immutable **valuation** record for one date: the portfolio's
totals, its per-account and per-tax-type values, and a per-lot
breakdown of where that value sat. It records what things were *worth*,
not the full detail of your lots -- see
[The snapshot model](../explanation/snapshots-model.md) for what is and
isn't captured, and why.
## 1. Write a snapshot
The simplest way is to run it yourself.
[`zfin snapshot`](../reference/cli/snapshot.md) computes today's
snapshot and writes it under `history/`. Try a dry run first -- it
computes and prints the snapshot without writing anything:
```bash
zfin snapshot --dry-run # compute + print, write nothing
zfin snapshot # write history/<today>-portfolio.srf
```
Run it whenever you want a record on the books -- after a monthly
review, say. The snapshot is just a file in `history/`; nothing else is
required.
**Back-filling a past date (optional, needs git).** If you keep your
portfolio file under [git](https://git-scm.com/) version control,
`--as-of` can reconstruct a snapshot for an earlier date: it recovers
your portfolio as it was then (from git) and prices it from the cached
price history.
```bash
zfin snapshot --as-of 2025-01-02
```
If you don't use git, skip this -- just snapshot going forward.
## 2. Keep it current automatically (optional)
Most people would rather not remember to run it every day. You can hand
that off to your operating system's **task scheduler** -- a built-in
service that runs a command on a set timetable, even while you're away.
**When to schedule it.** Run it in the early morning, *after* the prior
trading day's closing prices have posted. ETF and mutual-fund values
update overnight, and while data providers say "after midnight," in
practice **3:30am US Eastern** is the first time yesterday's closing
NAVs reliably land -- schedule it earlier and you risk capturing stale
prices.
**macOS and Linux** use `cron`. Run `crontab -e` and add a line like
this (3:30am, Monday-Friday -- adjust the hour for your machine's
timezone if it isn't US Eastern):
```cron
30 3 * * 1-5 cd ~/finance && /usr/local/bin/zfin snapshot
```
The five fields are minute, hour, day-of-month, month, day-of-week
(`1-5` = Mon-Fri); the full path to `zfin` matters because cron runs
with a minimal `PATH`. macOS ships cron, though the first run may prompt
you to grant your terminal "Full Disk Access."
**Windows** has no `cron` -- use Task Scheduler to run `zfin snapshot`
daily. (zfin should run on Windows, but it isn't regularly tested
there.)
## 3. Review the timeline with `history`
Run [`zfin history`](../reference/cli/history.md) with no symbol for the
portfolio-value timeline: rolling-window changes, a chart (an inline
Kitty image when your terminal supports it, else braille), and a
recent-snapshots table.
```bash
ZFIN_HOME=examples/post-retirement zfin history
```
```
Portfolio Timeline: Liquid
========================================
Change Δ % % / yr
1 year +$230,000.00 +9.79% +9.79%
3 years +$459,059.08 +21.64% +6.72%
5 years +$686,215.45 +36.24% +6.37%
All-time +$1,073,725.79 +71.28% +6.00%
```
Useful flags: `--metric liquid|illiquid|net_worth`, `--since` /
`--until` to bound the window, and `--resolution daily|weekly|monthly`.
> The percentage change includes contributions and withdrawals, not
> just market movement. To separate new money from market gains, use
> [contributions](track-contributions.md).
## 4. Compare two points with `compare`
[`zfin compare`](../reference/cli/compare.md) diffs two dates: liquid
totals, per-symbol price moves, and -- when your portfolio is tracked
in git -- contribution attribution. Pass one date to compare against
the live portfolio, or two dates to compare historical snapshots:
```bash
ZFIN_HOME=examples/post-retirement zfin compare 2024-04-01 2025-04-01
```
```
Portfolio comparison: 2024-04-01 -> 2025-04-01 (365 days)
Liquid: $2,350,000.00 -> $2,580,000.00 +$230,000.00 +9.79%
```
Arguments can be given in any order; output always reads older ->
newer. On a missing snapshot date, `compare` prints the nearest
available dates and exits rather than silently snapping. Add
`--projections` to include projected-return and safe-withdrawal deltas.
## Back-history without daily snapshots
If you have historical totals from a spreadsheet but no per-day
snapshots, record them in
`history/imported_values.srf` (one `liquid::` total per date). The
history and projection-overlay tools read it as a lower-fidelity
fallback when no native snapshot covers a date. The post-retirement
example includes one spanning 2016-2024.
## Next steps
- [Track contributions](track-contributions.md) -- separate new money from gains.
- [Plan for retirement](plan-retirement.md) -- overlay actuals on projections.
- [`zfin snapshot`](../reference/cli/snapshot.md) / [`zfin history`](../reference/cli/history.md) / [`zfin compare`](../reference/cli/compare.md)
---
[Previous: Track contributions](track-contributions.md) | [Next: Handle a stock split](handle-a-stock-split.md) | [Documentation home](../README.md)