# Handle a stock split

**Goal:** keep your holdings correct through a stock split without
breaking the history that zfin's other commands rely on.

**The one rule:** when a stock you hold splits, **do not edit the share
count on your existing lot.** Leave the lot exactly as you transacted
it, and tell zfin about the split with one line in `metadata.srf`. zfin
does the rest on read.

## Why not just change the share count?

It seems natural: NVDA does a 10:1 split, your 100 shares become 1,000,
so you open `portfolio.srf` and change `shares:num:100` to
`shares:num:1000`. Don't -- here is what that quietly breaks.

**Your portfolio file is history, and zfin reads the history, not just
the latest version.** If you are utilizing all zfin features, `portfolio.srf`
lives in git, and several commands diff *past commits* of it:

- [`contributions`](track-contributions.md) attributes what changed
  between two commits to *new money* vs. *market movement*. It works on
  the raw share/lot changes in the diff.
- [`compare`](../reference/cli/compare.md) and
  [`audit`](audit-against-brokerage.md) read git history the same way.

A split changes your **share count** but not your **money**: 100 shares
at $400 and 1,000 shares at $40 are the same $40,000. But if you edit the
lot from 100 to 1,000 and commit, the git diff shows **+900 shares**.
`contributions` cannot tell that apart from you *buying* 900 shares, so
it reports a large **phantom contribution** that never happened -- and it
is now baked into your commit history permanently.

**Snapshots make it worse.** [`zfin snapshot`](snapshots-and-history.md)
writes immutable, point-in-time records of your portfolio under
`history/`. A snapshot taken *before* your edit recorded 100 shares;
after the edit, your live file says 1,000. The two no longer agree, and
you **cannot fix the old snapshot** -- it is a frozen record of a past
day, and `compare` / `history` read it as-is.

Both git history and snapshots are **append-only truth**: undoing the
damage means rewriting git history (dangerous) or hand-editing frozen
snapshot files (error-prone). So the safe design is simple -- a split
must never touch your recorded shares. It is a *derivation*, not an
*edit*.

## What to do instead

Leave the lot alone. Add a per-symbol `splits_current_through` date to
that symbol's row in
[`metadata.srf`](../reference/config/metadata-srf.md#stock-split-adjustment):

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

Set the date to **when that symbol's recorded shares were last
accurate** -- for a lot you entered as transacted, that is on or around
the purchase. zfin then applies every split *after* that date to compute
the **effective** (split-adjusted) share count on the fly. Your
`portfolio.srf`, git history, and snapshots stay exactly as transacted;
only the *displayed and valued* shares reflect the split.

You can see the split zfin will apply with
[`zfin splits`](../reference/cli/splits.md):

```bash
zfin splits NVDA
```

## Copying post-split numbers from your brokerage is fine

Brokerages *do* restate: after a split, Fidelity or Schwab show you the
post-split share count and split-adjusted cost basis. Recording a lot
from one of those statements is **not** the mistake above -- you are
stating a holding as it stands today, not reaching back to rewrite a lot
that already lived through the split in your file.

The only thing zfin needs to know is whether the split is **already
baked into the number you typed.** The cutover date answers that:

- **Shares entered as transacted (pre-split).** The split happened after
  you recorded them, so set `splits_current_through` to a date *before*
  the split. zfin applies it.
- **Shares copied post-split from a statement.** The number already
  includes the split, so set `splits_current_through` to the statement
  date (*after* the split). zfin leaves it alone instead of applying it
  twice.

Either way the rule holds: you never went back and edited an existing
lot's shares. You either left it as transacted or recorded a fresh lot
from a statement, and the cutover date tells zfin which.

> **Bright line:** recording a lot from a post-split statement is fine.
> Reaching back to change an *existing* committed lot's `shares` because
> of a split is what corrupts your history. If you are tempted to edit a
> number that is already committed, set the cutover instead.

## Verify

`zfin audit`'s hygiene check lists any held symbol that has a
post-purchase split but no `splits_current_through` yet, under
**Unhandled stock splits** -- so you can see at a glance which rows still
need the line:

```bash
zfin audit
```

Once set, [`zfin portfolio`](../reference/cli/portfolio.md) shows the
effective (split-adjusted) share count and the correct market value,
while your files stay untouched.

## Next steps

- [`metadata.srf` reference](../reference/config/metadata-srf.md#stock-split-adjustment) -- the field's exact semantics.
- [Track contributions](track-contributions.md) -- why the git diff must stay honest.
- [Snapshots and history](snapshots-and-history.md) -- the frozen records a restate would desync.

---

[Previous: Snapshots and history](snapshots-and-history.md) | [Next: Plan for retirement](plan-retirement.md) | [Documentation home](../README.md)
