4.3 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~1againstHEAD-- i.e. "what changed in my last commit." - Dirty working tree: compares
HEADagainst 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. Only type::cash is wired up today; in_kind
parses but isn't yet supported.
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.
Related: compare
zfin compare shows the same
attribution alongside value and per-symbol price moves between two
dates. See Snapshots and history.
Next steps
- Snapshots and history -- record value over time.
transaction_log.srfreference
Previous: Read your portfolio | Next: Snapshots and history | Documentation home