update docs for split adjustment
This commit is contained in:
parent
9aaa374f12
commit
c08e89a025
4 changed files with 80 additions and 14 deletions
|
|
@ -8,10 +8,10 @@ Usage: zfin audit [opts]
|
||||||
```
|
```
|
||||||
|
|
||||||
**Flagless** runs the hygiene check -- stale manual prices,
|
**Flagless** runs the hygiene check -- stale manual prices,
|
||||||
accounts overdue for update, and auto-discovered brokerage-file
|
accounts overdue for update, unhandled stock splits, and
|
||||||
candidates. **With brokerage flags**, it reconciles your portfolio
|
auto-discovered brokerage-file candidates. **With brokerage flags**, it
|
||||||
against the export (treating the brokerage as source of truth) and
|
reconciles your portfolio against the export (treating the brokerage as
|
||||||
reports discrepancies.
|
source of truth) and reports discrepancies.
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
|
|
@ -34,6 +34,13 @@ The cutoff is per account -- raise or lower it on an account's record
|
||||||
via [`audit_large_lot_threshold`](../config/accounts-srf.md#audit_large_lot_threshold)
|
via [`audit_large_lot_threshold`](../config/accounts-srf.md#audit_large_lot_threshold)
|
||||||
in `accounts.srf` (e.g. to silence a noisy ESPP account).
|
in `accounts.srf` (e.g. to silence a noisy ESPP account).
|
||||||
|
|
||||||
|
It also lists held symbols that had a stock split *after* a lot's
|
||||||
|
purchase date but haven't opted into automatic split adjustment, in an
|
||||||
|
**Unhandled stock splits** section. Each needs a
|
||||||
|
[`splits_current_through`](../config/metadata-srf.md#stock-split-adjustment)
|
||||||
|
date on its `metadata.srf` row -- without it, that holding's shares (and
|
||||||
|
every value derived from them) are misstated across the split.
|
||||||
|
|
||||||
## Example (hygiene check)
|
## Example (hygiene check)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -59,6 +66,7 @@ ZFIN_HOME=examples/pre-retirement-both zfin audit
|
||||||
- [Audit against your brokerage](../../guides/audit-against-brokerage.md) -- the workflow.
|
- [Audit against your brokerage](../../guides/audit-against-brokerage.md) -- the workflow.
|
||||||
- [`import`](import.md) -- build a portfolio file *from* an export instead.
|
- [`import`](import.md) -- build a portfolio file *from* an export instead.
|
||||||
- [`accounts.srf` reference](../config/accounts-srf.md) -- `update_cadence`, `institution`, `account_number`.
|
- [`accounts.srf` reference](../config/accounts-srf.md) -- `update_cadence`, `institution`, `account_number`.
|
||||||
|
- [`metadata.srf` reference](../config/metadata-srf.md#stock-split-adjustment) -- `splits_current_through` for the unhandled-splits check.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ Polygon (`POLYGON_API_KEY`), merged with per-row split factors from
|
||||||
Tiingo's price series (which rescues events Polygon's reference
|
Tiingo's price series (which rescues events Polygon's reference
|
||||||
endpoint occasionally misses).
|
endpoint occasionally misses).
|
||||||
|
|
||||||
|
This is the same split feed that drives portfolio split adjustment: to
|
||||||
|
have a split reflected in your holdings' effective shares, set
|
||||||
|
[`splits_current_through`](../config/metadata-srf.md#stock-split-adjustment)
|
||||||
|
on the symbol's `metadata.srf` row.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -35,6 +40,7 @@ Split History for AAPL
|
||||||
|
|
||||||
- [`divs`](divs.md) -- dividend history for a symbol.
|
- [`divs`](divs.md) -- dividend history for a symbol.
|
||||||
- [`history`](history.md) -- split-adjusted price history.
|
- [`history`](history.md) -- split-adjusted price history.
|
||||||
|
- [`metadata.srf`](../config/metadata-srf.md#stock-split-adjustment) -- apply a split to your holdings via `splits_current_through`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,16 @@ symbol::AGG,sector::Bonds,geo::US,asset_class::Bonds
|
||||||
|
|
||||||
## Fields
|
## Fields
|
||||||
|
|
||||||
| Field | Type | Required | Default | Description |
|
| Field | Type | Required | Default | Description |
|
||||||
|---------------|--------|----------|-----------|---------------------------------------------------------------------------------------------------------------------------|
|
|--------------------------|--------|----------|-----------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `symbol` | string | Yes | -- | Ticker or CUSIP. Must match `symbol::` (or `ticker::`) on a portfolio lot. |
|
| `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. |
|
| `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`. |
|
| `asset_class` | string | No | -- | e.g. `US Large Cap`, `Bonds`, `International Developed`, `Emerging Markets`. |
|
||||||
| `sector` | string | No | -- | e.g. `Technology`, `Healthcare`, `Financials`, `Diversified`, `Bonds`. |
|
| `sector` | string | No | -- | e.g. `Technology`, `Healthcare`, `Financials`, `Diversified`, `Bonds`. |
|
||||||
| `geo` | string | No | -- | e.g. `US`, `International Developed`, `Emerging Markets`. |
|
| `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). |
|
| `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. |
|
| `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](#stock-split-adjustment). |
|
||||||
|
|
||||||
Cash and CD lots are classified as "Cash & CDs" automatically -- they
|
Cash and CD lots are classified as "Cash & CDs" automatically -- they
|
||||||
need no metadata entry.
|
need no metadata entry.
|
||||||
|
|
@ -64,6 +65,44 @@ symbol::02315N600,asset_class::Bonds,pct:num:15
|
||||||
symbol::02315N600,asset_class::Emerging Markets,pct:num:10
|
symbol::02315N600,asset_class::Emerging Markets,pct:num:10
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Stock split adjustment
|
||||||
|
|
||||||
|
Lots in [`portfolio.srf`](portfolio-srf.md) 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:
|
||||||
|
|
||||||
|
```srf
|
||||||
|
#!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`](../cli/splits.md).
|
||||||
|
|
||||||
|
[`zfin audit`](../cli/audit.md) 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`)
|
## Example (from `examples/pre-retirement-both`)
|
||||||
|
|
||||||
```srf
|
```srf
|
||||||
|
|
@ -81,6 +120,7 @@ symbol::AGG,sector::Bonds,geo::US,asset_class::Bonds
|
||||||
- [`zfin enrich`](../cli/enrich.md) -- bootstrap this file from Wikidata + SEC EDGAR.
|
- [`zfin enrich`](../cli/enrich.md) -- bootstrap this file from Wikidata + SEC EDGAR.
|
||||||
- [`zfin analysis`](../cli/analysis.md) -- the breakdowns this file feeds.
|
- [`zfin analysis`](../cli/analysis.md) -- the breakdowns this file feeds.
|
||||||
- [`zfin review`](../cli/review.md) -- the per-holding Sector column and grouping this file feeds.
|
- [`zfin review`](../cli/review.md) -- the per-holding Sector column and grouping this file feeds.
|
||||||
|
- [`zfin audit`](../cli/audit.md) -- flags symbols with an unhandled split that need `splits_current_through`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,11 +147,23 @@ Lots marked `drip:bool:true` are collapsed into short-term (ST) and
|
||||||
long-term (LT) groups in the position detail view (split on the
|
long-term (LT) groups in the position detail view (split on the
|
||||||
1-year capital-gains threshold) rather than listed individually.
|
1-year capital-gains threshold) rather than listed individually.
|
||||||
|
|
||||||
|
## Stock splits
|
||||||
|
|
||||||
|
Do **not** rewrite a lot's `shares` when a stock splits. A lot is an
|
||||||
|
immutable record of what you transacted -- rewriting it would corrupt
|
||||||
|
the history that [`zfin contributions`](../cli/contributions.md),
|
||||||
|
[`compare`](../cli/compare.md), and `audit` read from git. Instead,
|
||||||
|
opt the symbol into automatic split adjustment with a
|
||||||
|
[`splits_current_through`](metadata-srf.md#stock-split-adjustment) date
|
||||||
|
on its `metadata.srf` row; zfin then derives split-adjusted shares on
|
||||||
|
read. [`zfin audit`](../cli/audit.md) flags any held symbol that needs
|
||||||
|
this.
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [Build your portfolio](../../guides/set-up-your-portfolio.md) -- the task-oriented walkthrough.
|
- [Build your portfolio](../../guides/set-up-your-portfolio.md) -- the task-oriented walkthrough.
|
||||||
- [`accounts.srf`](accounts-srf.md) -- give each `account::` a tax type.
|
- [`accounts.srf`](accounts-srf.md) -- give each `account::` a tax type.
|
||||||
- [`metadata.srf`](metadata-srf.md) -- classify each `symbol::` for analysis.
|
- [`metadata.srf`](metadata-srf.md) -- classify each `symbol::` for analysis; opt into split adjustment.
|
||||||
- [`zfin portfolio`](../cli/portfolio.md) and [`zfin import`](../cli/import.md).
|
- [`zfin portfolio`](../cli/portfolio.md) and [`zfin import`](../cli/import.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue