177 lines
7 KiB
Markdown
177 lines
7 KiB
Markdown
# A periodic review
|
|
|
|
**Goal:** on a regular cadence -- weekly works well -- make zfin agree
|
|
with your brokerages, see what changed since last time, and commit the
|
|
reconciled state so the *next* review has a clean baseline to compare
|
|
against.
|
|
|
|
This is the loop that ties the other guides together. Each step has its
|
|
own guide for the details; this one is the routine you actually run. It
|
|
settles into well under an hour once it's habit.
|
|
|
|
```
|
|
reconcile ──► what changed? ──► (projections) ──► commit
|
|
(audit) (compare) (optional) (baseline)
|
|
▲ │
|
|
└──────────────── next review ◄────────────────────────┘
|
|
```
|
|
|
|
## 1. Reconcile against your brokerages
|
|
|
|
Pull a fresh export from each brokerage that offers one and drop it in
|
|
your `audit/` folder (or wherever you've pointed `$ZFIN_AUDIT_FILES` --
|
|
see [Audit against your brokerage](audit-against-brokerage.md) for the
|
|
export steps and auto-discovery rules). Then:
|
|
|
|
```bash
|
|
zfin audit
|
|
```
|
|
|
|
Fix any flagged share or cash discrepancy in `portfolio.srf` and re-run
|
|
until it reconciles. A tight edit loop helps: if you have
|
|
[`watchexec`](https://github.com/watchexec/watchexec) installed,
|
|
|
|
```bash
|
|
watchexec -- zfin audit
|
|
```
|
|
|
|
re-runs the audit on every save, so the remaining-discrepancy list
|
|
shrinks live as you fix lots -- much faster than alt-tab, rerun, read,
|
|
alt-tab, edit.
|
|
|
|
**Reconcile first, for a reason.** Step 2 splits your change in value
|
|
into **contributions vs. market gains**, and that split is only as
|
|
honest as your share counts. Reconcile before you read the headline or
|
|
the attribution will lie to you.
|
|
|
|
### Blind spots the audit can't see
|
|
|
|
- **Accounts with no export** (some insurers, some 401(k)
|
|
recordkeepers) -- check the latest statement and update
|
|
`portfolio.srf` by hand.
|
|
- **Payroll-driven cash** -- e.g. ESPP contributions that haven't
|
|
purchased yet won't appear in a positions export until the purchase
|
|
posts. Reconcile those against a paystub.
|
|
- **A small, expected standing discrepancy** -- some accounts just sit a
|
|
few dollars off every week. Note it and move on rather than chasing it
|
|
each time.
|
|
- **Lagging transaction views.** A brokerage's *positions* view can
|
|
update overnight before its *transaction* view posts the dividend,
|
|
interest, or option assignment that caused the change. Trust the
|
|
positions numbers and reconcile the totals; the cause-side record
|
|
catches up later and isn't needed to get today's counts right.
|
|
|
|
## 2. The headline -- what changed since last time
|
|
|
|
One command gives you the whole "since last review" picture:
|
|
|
|
```bash
|
|
zfin compare 1W --projections --commit-before HEAD
|
|
```
|
|
|
|
- **`1W`** is the point of comparison -- the snapshot from one week ago.
|
|
Any [relative shortcut](#relative-dates) or an explicit `YYYY-MM-DD`
|
|
works.
|
|
- **`--projections`** folds in projected-return and safe-withdrawal
|
|
(SWR@99%) deltas, then vs. now. (Costs ~1-2s per endpoint for the
|
|
Monte Carlo search; add `--no-events` to exclude life events.)
|
|
- **`--commit-before HEAD`** pins the contributions/gains attribution to
|
|
your latest reconciliation commit. This matters -- see
|
|
[Attribution and commit timing](#attribution-and-commit-timing).
|
|
|
|
Read off the liquid-total delta, the contributions-vs-gains split, the
|
|
per-symbol winners and losers, and the projection deltas. For most
|
|
weeks, this single command *is* the review. See
|
|
[Snapshots and history](snapshots-and-history.md) for a full walk
|
|
through `compare` output.
|
|
|
|
## 3. (Optional) Full projections
|
|
|
|
`compare --projections` gives you the deltas but not the full benchmark
|
|
table or every scenario row. When you want the complete picture:
|
|
|
|
```bash
|
|
zfin projections # default: with life events (SS, college, ...)
|
|
zfin projections --no-events # baseline: life events excluded
|
|
zfin projections --as-of 1W # the same table as of last review
|
|
zfin projections --vs 1W # both ends of the window in one run
|
|
```
|
|
|
|
See [Plan for retirement](plan-retirement.md) for what these rows mean.
|
|
|
|
## 4. Commit -- the baseline for next time
|
|
|
|
```bash
|
|
git add portfolio.srf metadata.srf history/
|
|
git commit -m "review 2026-06-20"
|
|
```
|
|
|
|
Committing does double duty:
|
|
|
|
- It snapshots the reconciled `portfolio.srf`, and the day's snapshot
|
|
file in `history/` rides along, so future `--as-of` runs can read it.
|
|
- zfin walks the git history of `portfolio.srf` for
|
|
[contributions](track-contributions.md) analysis, treating each commit
|
|
as a reconciliation point. **Commit timing sets next review's
|
|
baseline** -- a same-day commit keeps a weekly cadence clean.
|
|
|
|
If you keep your portfolio directory in git (recommended), this is also
|
|
your backup and your audit trail.
|
|
|
|
## Attribution and commit timing
|
|
|
|
`compare` and `contributions` work out "contributions vs. gains" by
|
|
walking the git history of `portfolio.srf`. The positional date (`1W`)
|
|
picks the *snapshot* whose prices you compare against; **`--commit-before`**
|
|
picks which *commit* anchors the attribution. Those two can drift apart.
|
|
|
|
If you reconcile on Saturday but don't commit until Monday, next
|
|
Saturday's `1W` snapshot lands *before* your last commit -- so a bare
|
|
`compare 1W` would attribute **two weeks** of contributions to one week.
|
|
`--commit-before HEAD` sidesteps this by pinning attribution to your
|
|
most recent reconciliation commit regardless of the snapshot date. When
|
|
the dates line up anyway, the flag is harmless -- which is why it's
|
|
worth making a habit.
|
|
|
|
## Relative dates
|
|
|
|
Every date-accepting command takes the same shorthand, so you rarely
|
|
type a full date:
|
|
|
|
| Shortcut | Means |
|
|
|----------|-----------------|
|
|
| `1W` | one week ago |
|
|
| `3W` | three weeks ago |
|
|
| `1M` | one month ago |
|
|
| `1Q` | one quarter ago |
|
|
| `1Y` | one year ago |
|
|
|
|
`compare`, `contributions --since/--until`, `projections --as-of/--vs`,
|
|
`snapshot --as-of`, and `history --since/--until` all accept it (plus an
|
|
explicit `YYYY-MM-DD`).
|
|
|
|
## If there's no snapshot yet
|
|
|
|
The comparison needs a snapshot to compare against. If your daily
|
|
snapshot didn't run, or you're reviewing off your normal cadence, make
|
|
one first:
|
|
|
|
```bash
|
|
zfin portfolio --refresh # fresh close prices for tracked symbols
|
|
zfin snapshot # writes history/<today>-portfolio.srf
|
|
```
|
|
|
|
See [Snapshots and history](snapshots-and-history.md) for the cron setup
|
|
that automates daily snapshots.
|
|
|
|
## Next steps
|
|
|
|
- [Audit against your brokerage](audit-against-brokerage.md) -- step 1 in depth.
|
|
- [Snapshots and history](snapshots-and-history.md) -- `compare`, snapshots, and the timeline.
|
|
- [Track contributions](track-contributions.md) -- the contributions / gains attribution.
|
|
- [Plan for retirement](plan-retirement.md) -- the projection rows.
|
|
- [`compare`](../reference/cli/compare.md) and [`projections`](../reference/cli/projections.md) reference -- every flag.
|
|
|
|
---
|
|
|
|
[Previous: Audit against your brokerage](audit-against-brokerage.md) | [Next: Customize the TUI](customize-the-tui.md) | [Documentation home](../README.md)
|