zfin/docs/guides/track-contributions.md

4.8 KiB

Track contributions

Goal: see how much new money you've added (or withdrawn) over a period, separated from market movement -- and stop internal transfers between your own accounts from being counted as contributions.

You'll need: your portfolio under git version control, with commits over time. contributions works by diffing two revisions of your portfolio.srf, so it only sees money movement you've committed.

How it works

Market gains change your portfolio's value; contributions change its shares and lots. zfin contributions diffs your portfolio file between two git revisions, attributes the share/lot changes to contributions vs. withdrawals, and ignores price movement.

This means the workflow is: keep portfolio.srf in a git repo, and commit it whenever you update it. A natural cadence is a commit per account update or per weekly review.

Do this bookkeeping when the market is closed -- a weekend is ideal. Prices and balances have settled, your brokerage statements are final, and zfin's cached closing prices won't shift under you mid-run, so the numbers are stable and reproducible. The same applies to audit: reconciling against an export lines up cleanly when both sides reflect the same settled close, rather than a moving intraday price.

The default modes

With no flags, the comparison depends on your working tree:

zfin contributions
  • Clean working tree: compares HEAD~1 against HEAD -- i.e. "what changed in my last commit."
  • Dirty working tree: compares HEAD against the working copy -- i.e. "what have I edited but not yet committed."

Against a freshly-checked-out example (clean, nothing to diff) you'll see:

Portfolio contributions report
  Working tree clean - comparing HEAD~1 against HEAD

  No changes detected.

Choosing a window

Use --since (and optionally --until) to pick the endpoints. Dates accept YYYY-MM-DD or relative shortcuts (1W, 1M, 1Q, 1Y):

zfin contributions --since 1Y                 # a year ago vs. now
zfin contributions --since 2025-01-01 --until 2025-12-31

Each date resolves to the commit at or before it. When a review date and its commit date diverge (you committed two days after your Sunday review), pin commits directly with --commit-before / --commit-after (which accept HEAD, HEAD~N, a SHA, or working).

Don't double-count transfers

Moving money between two accounts you own isn't a contribution, but a naive diff sees the receiving account gain lots and counts it as new money. transaction_log.srf is how you tell zfin "this was a transfer, not new money."

Like the other sibling files, it's optional and additive: you only need it if you move money between your own accounts and want clean attribution. Without it nothing breaks -- those transfers just show up as contributions, inflating the total by the amount moved. If you never shuffle money between accounts, skip the file entirely.

When you do, declare each move in transaction_log.srf so it cancels out:

#!srfv1
transfer::2026-05-02,type::cash,amount:num:50000,from::Joint taxable,to::Pat Roth,dest_lot::cash

zfin matches the transfer against the diff and removes it from the attribution total.

If the securities moved rather than cash -- an ACAT transfer or an in-kind rollover -- use type::in_kind and point dest_lot at the lot that arrived:

transfer::2026-05-02,type::in_kind,amount:num:87000,from::Old 401k,to::Pat Roth,dest_lot::VTI@2024-01-15

In-kind records are verified by share count rather than by amount (which is informational there), so the shares that left have to match the shares that arrived. See the reference for the exact tolerances and what happens when they don't line up.

Cash that is a contribution

By default, raw cash-balance increases are treated as internal noise (interest, dividends, sweeps). For accounts whose cash movement is dominated by real external deposits (payroll ESPP, direct 401k cash), set cash_is_contribution:bool:true in accounts.srf so those increases count.

zfin compare shows the same attribution alongside value and per-symbol price moves between two dates. See Snapshots and history.

Next steps


Previous: Read your portfolio | Next: Snapshots and history | Documentation home