add stock split guide with full rationale
This commit is contained in:
parent
c08e89a025
commit
f1cabdcf9a
4 changed files with 126 additions and 2 deletions
|
|
@ -41,6 +41,7 @@ example portfolio and links to the reference for exhaustive detail.
|
|||
| [Read your portfolio](guides/read-your-portfolio.md) | Interpret `portfolio`, `analysis`, `exposure`, `review`, `perf` |
|
||||
| [Track contributions](guides/track-contributions.md) | See money added over time and tag internal transfers |
|
||||
| [Snapshots and history](guides/snapshots-and-history.md) | Record daily snapshots and compare your portfolio over time |
|
||||
| [Handle a stock split](guides/handle-a-stock-split.md) | Adjust for splits without restating shares (and why that matters) |
|
||||
| [Plan for retirement](guides/plan-retirement.md) | Configure `projections.srf` for accumulation and drawdown |
|
||||
| [Audit against your brokerage](guides/audit-against-brokerage.md) | Reconcile zfin against Fidelity/Schwab/Wells exports |
|
||||
| [A periodic review](guides/periodic-review.md) | Reconcile, see what changed, then commit the new baseline |
|
||||
|
|
|
|||
123
docs/guides/handle-a-stock-split.md
Normal file
123
docs/guides/handle-a-stock-split.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# 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)
|
||||
|
|
@ -310,4 +310,4 @@ every field is documented in the
|
|||
|
||||
---
|
||||
|
||||
[Previous: Snapshots and history](snapshots-and-history.md) | [Next: Audit against your brokerage](audit-against-brokerage.md) | [Documentation home](../README.md)
|
||||
[Previous: Handle a stock split](handle-a-stock-split.md) | [Next: Audit against your brokerage](audit-against-brokerage.md) | [Documentation home](../README.md)
|
||||
|
|
|
|||
|
|
@ -147,4 +147,4 @@ example includes one spanning 2016-2024.
|
|||
|
||||
---
|
||||
|
||||
[Previous: Track contributions](track-contributions.md) | [Next: Plan for retirement](plan-retirement.md) | [Documentation home](../README.md)
|
||||
[Previous: Track contributions](track-contributions.md) | [Next: Handle a stock split](handle-a-stock-split.md) | [Documentation home](../README.md)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue