zfin/docs/reference/config/metadata-srf.md
Emil Lerch c08e89a025
All checks were successful
Generic zig build / build (push) Successful in 4m53s
Generic zig build / publish-macos (push) Successful in 11s
Generic zig build / deploy (push) Successful in 20s
update docs for split adjustment
2026-07-06 14:09:18 -07:00

6.4 KiB

metadata.srf reference

metadata.srf classifies each symbol by asset class, sector, and geography so zfin analysis can produce allocation breakdowns and zfin review can group holdings by sector. zfin loads it from the same directory as the resolved portfolio file.

It is optional, but without it the Asset Category / Sector / Geographic breakdowns have nothing to group by. The fastest way to create one is zfin enrich; see Classify your holdings.

File format

One record per (symbol, allocation) pair. A single-asset-class security needs one line; a blended fund needs several lines that sum to ~100%.

#!srfv1
symbol::VTI,sector::Diversified,geo::US,asset_class::US Large Cap
symbol::AGG,sector::Bonds,geo::US,asset_class::Bonds

Fields

Field Type Required Default Description
symbol string Yes -- Ticker or CUSIP. Must match symbol:: (or ticker::) on a portfolio lot.
name string No -- Human-readable security name (e.g. "SPDR S&P 500 ETF Trust"). Shown where available; falls back to the symbol.
asset_class string No -- e.g. US Large Cap, Bonds, International Developed, Emerging Markets.
sector string No -- e.g. Technology, Healthcare, Financials, Diversified, Bonds.
geo string No -- e.g. US, International Developed, Emerging Markets.
bucket string No (derived) User-curated grouping label that overrides the auto-derived sector bucket for concentration/dominance checks (see below).
pct number No 100 Weight of this allocation line for the symbol. Use multiple lines for blended funds.
splits_current_through date No (unset) Per-symbol opt-in for automatic stock-split adjustment (YYYY-MM-DD). See Stock split adjustment.

Cash and CD lots are classified as "Cash & CDs" automatically -- they need no metadata entry.

The bucket field

For concentration and sector-dominance analysis, zfin needs a meaningful grouping label. It derives one automatically, but the upstream sector can be uninformative -- ETF holdings data often tags everything as the generic "Equity / Corporate." When several distinct holdings collapse into one meaningless bucket, set bucket:: yourself to a label that actually distinguishes them. When bucket is unset, zfin falls back through: sector (if it isn't a fund-decomposition category) -> a composite "<geo> <asset_class>" -> Unclassified. See Classify your holdings for a worked bucket example.

Blended funds

For a target-date or balanced fund, add one line per asset class with pct:num: weights summing to ~100:

#!srfv1
symbol::02315N600,asset_class::US Large Cap,pct:num:55
symbol::02315N600,asset_class::International Developed,pct:num:20
symbol::02315N600,asset_class::Bonds,pct:num:15
symbol::02315N600,asset_class::Emerging Markets,pct:num:10

Stock split adjustment

Lots in portfolio.srf are immutable historical records -- the share count and price exactly as transacted. zfin never rewrites them for a stock split; instead it derives effective (split-adjusted) shares on read, so a position held across a split is valued correctly without you editing the file.

This adjustment is opt-in, per symbol. Add splits_current_through::YYYY-MM-DD to a symbol's row to enable it for that symbol:

#!srfv1
symbol::NVDA,sector::Technology,geo::US,asset_class::US Large Cap,splits_current_through::2024-01-01

The date is the point through which that symbol's recorded shares are already current. zfin auto-applies any split that occurs after it; splits on or before it are assumed already reflected in your recorded shares. Set it to the date you last reconciled (or entered) that holding:

  • If you record lots as transacted (pre-split share counts), set the cutover before the split so zfin applies it.
  • If you entered a lot with post-split share counts -- common when copying from a broker statement after the fact, e.g. an AMZN lot entered after its 2022 20:1 split -- set the cutover after that split so zfin does not double-apply it.

When the field is absent, split adjustment is off for that symbol -- identical to zfin's behavior before this feature existed. Split data comes from the same feed as zfin splits.

zfin audit lists held symbols that have a post-purchase split but no splits_current_through yet (under "Unhandled stock splits"), so you know which rows still need it.

Example (from examples/pre-retirement-both)

#!srfv1
symbol::VTI,sector::Diversified,geo::US,asset_class::US Large Cap
symbol::SPY,sector::Diversified,geo::US,asset_class::US Large Cap
symbol::QQQ,sector::Technology,geo::US,asset_class::US Large Cap
symbol::SCHD,sector::Diversified,geo::US,asset_class::US Large Cap
symbol::AGG,sector::Bonds,geo::US,asset_class::Bonds

See also


Documentation home