repos
2.9 KB raw
-- finance migration 0008: ETF stats (Phase 28).
--
-- Layers Yahoo `quoteSummary` fund metadata onto the Phase 18 SEC N-PORT
-- fund profile so an ETF symbol page can read as densely as a stock's. Also
-- adds two N-PORT-derived aggregations (sector_mix, geography_mix) that
-- ride alongside the existing asset_mix on `fund_profiles`, and a curated
-- benchmark column on `symbols` for the relative-performance overlay.
--
-- Phase 26's stocks-only dividends path is lifted to ETFs in the same
-- phase, but that is a code-level filter change and needs no migration:
-- the `dividends` table already keys on (ticker, ex_date) for any ticker.

-- When the Yahoo `fund_metadata` scheduler section last refreshed this
-- ETF. NULL = never swept. ETFs only; stocks, indexes and futures keep
-- NULL forever.
ALTER TABLE symbols ADD COLUMN fund_metadata_synced_at INTEGER;

-- Curated benchmark index (a symbol such as `^SPX` / `^IXIC` / `^DJI` /
-- `^RUT`) that the fund aims to track. Hand-curated in
-- `universe/starter.csv` for the broad-market ETFs; a user-added ETF
-- simply omits it and the symbol page hides the relative-performance
-- overlay. NULL on every non-ETF row.
ALTER TABLE symbols ADD COLUMN benchmark TEXT;

-- N-PORT sector + geography exposure aggregated from each holding's
-- `industryCode` / issuer country at parse time. JSON of the same shape
-- as the existing `asset_mix` column: [[bucket, percent], ...] ordered
-- largest first, top ~10 buckets kept. NULL for a commodity-trust ETF
-- (GLD, SLV) that files no N-PORT, the same as `asset_mix` already is.
ALTER TABLE fund_profiles ADD COLUMN sector_mix TEXT;
ALTER TABLE fund_profiles ADD COLUMN geography_mix TEXT;

-- Yahoo `quoteSummary` fund metadata: the slow-moving figures the
-- prospectus carries that N-PORT does not (expense ratio, yield,
-- inception, category, fund family, the issuer's strategy paragraph),
-- plus NAV which drifts intraday. One row per ETF, replaced wholesale by
-- the `fund_metadata` scheduler section on each refresh. Kept separate
-- from `fund_profiles` because the two carry different sources and
-- staleness cadences (SEC quarterly vs Yahoo monthly).
CREATE TABLE fund_metadata (
    ticker             TEXT PRIMARY KEY REFERENCES symbols(ticker) ON DELETE CASCADE,
    expense_ratio      REAL,      -- annualReportExpenseRatio, decimal (e.g. 0.0003 = 0.03%)
    yield_pct          REAL,      -- summaryDetail.yield, decimal (e.g. 0.013 = 1.30%)
    trailing_yield_pct REAL,      -- summaryDetail.trailingAnnualDividendYield, decimal
    nav_price          REAL,      -- price.navPrice or fundProfile fallback, USD
    inception_date     TEXT,      -- YYYY-MM-DD; first trade date / fund start
    category           TEXT,      -- fundProfile.categoryName, e.g. "Large Blend"
    fund_family        TEXT,      -- fundProfile.family, e.g. "Vanguard"
    strategy_summary   TEXT,      -- assetProfile.longBusinessSummary (full paragraph)
    updated_at         INTEGER NOT NULL
);