5.6 KiB
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 example ships with
a history/ folder of snapshots, so you can explore the read side
immediately:
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 record of totals, per-account values, and lot-level
state for one date.
1. Write a snapshot
The simplest way is to run it yourself.
zfin snapshot computes today's
snapshot and writes it under history/. Try a dry run first -- it
computes and prints the snapshot without writing anything:
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 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.
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):
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 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.
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.
4. Compare two points with compare
zfin compare 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:
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 -- separate new money from gains.
- Plan for retirement -- overlay actuals on projections.
zfin snapshot/zfin history/zfin compare
Previous: Track contributions | Next: Handle a stock split | Documentation home