feat: Phase 3 FINRA bulk adapter + Phase 4 three-way merge with discrepancy flagging
Phase 3 — FINRA bulk short-interest ingest: - Add finra_short_interest table to schema (per-symbol, per-settlement-date, per-exchange, with short/exempt/total volume, avg daily vol, days to cover) - Create FinraIngestService: downloads FINRA consolidated pipe-delimited file from configurable base URL, parses Market|Symbol|ShortVolume|ShortExemptVolume|TotalVolume, stores in finra_short_interest table - Create FinraBulkAdapter: SourceFetch that calls downloadAndIngestFinra, registers as finra-bulk source kind with finraShortinterest cache handler - finraShortinterest handler reads latest settlement row per symbol from finra_short_interest table (no per-symbol kv_cache write; data is bulk-ingested) - Register in index.ts adapter map + HANDLERS + del case Phase 4 — three-way merge with discrepancy detection: - shortInterest tRPC procedure now reads all 3 caches (yfinance, nasdaq, finra-bulk) in parallel - Reconciliation hierarchy: FINRA (shares short) > NASDAQ > Yahoo - daysToCover: NASDAQ (specific) > FINRA (computed) > Yahoo (short ratio fallback) - settlementDate: FINRA > NASDAQ > Yahoo - Discrepancy detection: compares sharesShort across available sources, flags >10% difference with discrepancyPct + discrepancyBetween - Updated ShortInterestPanel: FINRA source badge, discrepancy warning banner, three-source disclaimer - Updated trpc.ts client type for new shape
This commit is contained in:
@@ -676,3 +676,21 @@ CREATE TABLE IF NOT EXISTS rotation_state (
|
||||
sub_group TEXT, -- the strongest sub-group (e.g. "Financials")
|
||||
checked_at TEXT
|
||||
);
|
||||
|
||||
-- ===== Slice 22 — FINRA Short Interest (bulk ingest, twice-monthly) =====
|
||||
CREATE TABLE IF NOT EXISTS finra_short_interest (
|
||||
symbol TEXT NOT NULL,
|
||||
settlement_date TEXT NOT NULL, -- YYYY-MM-DD of the short interest report
|
||||
exchange TEXT, -- NASDAQ | NYSE | NYSE_AMERICAN | NYSE_ARCA | ALL
|
||||
short_volume REAL, -- shares sold short
|
||||
short_exempt REAL, -- short exempt volume
|
||||
total_volume REAL, -- short + exempt
|
||||
avg_daily_vol REAL, -- average daily volume (for days-to-cover)
|
||||
days_to_cover REAL, -- computed: short_volume / avg_daily_vol
|
||||
source_file TEXT, -- origin filename for audit
|
||||
ingested_at TEXT NOT NULL,
|
||||
PRIMARY KEY (symbol, settlement_date, exchange)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_finra_symbol ON finra_short_interest(symbol);
|
||||
CREATE INDEX IF NOT EXISTS idx_finra_settlement ON finra_short_interest(settlement_date);
|
||||
|
||||
Reference in New Issue
Block a user