-- 005_market_history.sql -- -- Adds the rolling market-history substrate (window length from env): -- * timeframe column + idempotent unique observation key on -- market_data_snapshots -- * tradable_assets cache for the daily Alpaca asset universe -- * market_data_sync_runs audit table -- See TODO.md ยง1. ALTER TABLE market_data_snapshots ADD COLUMN IF NOT EXISTS timeframe TEXT NOT NULL DEFAULT 'tick'; ALTER TABLE market_data_snapshots DROP CONSTRAINT IF EXISTS market_data_snapshots_unique_obs; ALTER TABLE market_data_snapshots ADD CONSTRAINT market_data_snapshots_unique_obs UNIQUE (symbol, metric, timeframe, as_of); CREATE INDEX IF NOT EXISTS market_data_snapshots_asof_idx ON market_data_snapshots (as_of DESC); CREATE TABLE IF NOT EXISTS tradable_assets ( symbol TEXT PRIMARY KEY, asset_class TEXT NOT NULL DEFAULT 'us_equity', exchange TEXT, name TEXT, tradable BOOLEAN NOT NULL DEFAULT true, fractionable BOOLEAN NOT NULL DEFAULT false, status TEXT NOT NULL DEFAULT 'active', raw JSONB, refreshed_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS tradable_assets_status_idx ON tradable_assets (status, tradable); CREATE TABLE IF NOT EXISTS market_data_sync_runs ( id BIGSERIAL PRIMARY KEY, kind TEXT NOT NULL, started_at TIMESTAMPTZ NOT NULL DEFAULT now(), finished_at TIMESTAMPTZ, rows_written INTEGER NOT NULL DEFAULT 0, rows_removed INTEGER NOT NULL DEFAULT 0, error TEXT ); CREATE INDEX IF NOT EXISTS market_data_sync_runs_kind_started_idx ON market_data_sync_runs (kind, started_at DESC); -- The market_data_archive table is intentionally deferred to TODO.md -- section 4.2 (Phase 2 archive mode) and will be added when -- MarketDataRetention.runArchiveAndCleanup is implemented.