pg_schema.sql: drop CREATE TABLE for 10 zero-reference tables (operator DROP list in plans/002-deletions.log — production tables untouched until run). projections.py: remove 4 zero-consumer query functions. Clear all 'plan 002' ruff pins from the CI gate (files now F-clean); api/main.py:F821 pin remains for plan 007. README repo-map/test-count fixed; pydantic-settings removed (zero imports). Full receipts: plans/002-deletions.log Suite: 351 passed (16 schwab/dead-module tests removed), 15 failures = the known WSL-loopback dashboard set only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
337 lines
11 KiB
SQL
337 lines
11 KiB
SQL
-- PostgreSQL schema for the momentum system (single datastore).
|
|
--
|
|
-- Port of storage/schema.py (DuckDB) + the event store `events` table that
|
|
-- previously lived in storage/event_store.py. Dialect deltas applied:
|
|
-- DOUBLE -> DOUBLE PRECISION
|
|
-- payload index -> on event_type/correlation_id (a btree on unbounded
|
|
-- TEXT payload is invalid in Postgres)
|
|
-- everything else -> already Postgres-compatible (DuckDB dialect is
|
|
-- Postgres-derived: IF NOT EXISTS, BOOLEAN, VARCHAR,
|
|
-- composite PKs, current_timestamp defaults all work).
|
|
--
|
|
-- Idempotent: safe to run repeatedly (CREATE ... IF NOT EXISTS throughout).
|
|
|
|
-- =====================================================================
|
|
-- Operational event store (append-only source of truth)
|
|
-- =====================================================================
|
|
CREATE TABLE IF NOT EXISTS events (
|
|
id VARCHAR PRIMARY KEY,
|
|
timestamp TIMESTAMP,
|
|
mode VARCHAR,
|
|
event_type VARCHAR,
|
|
correlation_id VARCHAR,
|
|
message VARCHAR,
|
|
payload_json TEXT,
|
|
created_at TIMESTAMP DEFAULT current_timestamp
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events (timestamp);
|
|
CREATE INDEX IF NOT EXISTS idx_events_correlation ON events (correlation_id);
|
|
CREATE INDEX IF NOT EXISTS idx_events_type ON events (event_type);
|
|
|
|
-- =====================================================================
|
|
-- Universe metadata
|
|
-- =====================================================================
|
|
CREATE TABLE IF NOT EXISTS symbols (
|
|
symbol VARCHAR PRIMARY KEY,
|
|
security_name VARCHAR,
|
|
exchange VARCHAR,
|
|
asset_type VARCHAR DEFAULT 'common_stock',
|
|
sector VARCHAR,
|
|
industry VARCHAR,
|
|
shares_outstanding BIGINT,
|
|
float_shares BIGINT,
|
|
market_cap DOUBLE PRECISION,
|
|
is_etf BOOLEAN DEFAULT FALSE,
|
|
is_otc BOOLEAN DEFAULT FALSE,
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
created_at TIMESTAMP DEFAULT current_timestamp,
|
|
updated_at TIMESTAMP DEFAULT current_timestamp
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS trading_days (
|
|
trade_date DATE PRIMARY KEY,
|
|
session_open TIMESTAMP,
|
|
session_close TIMESTAMP,
|
|
premarket_open TIMESTAMP,
|
|
afterhours_close TIMESTAMP,
|
|
is_half_day BOOLEAN DEFAULT FALSE,
|
|
is_holiday_adjacent BOOLEAN DEFAULT FALSE,
|
|
tape_regime VARCHAR,
|
|
market_regime VARCHAR,
|
|
volatility_regime VARCHAR,
|
|
gap_activity_level INTEGER,
|
|
momentum_density INTEGER
|
|
);
|
|
|
|
-- =====================================================================
|
|
-- Bars
|
|
-- =====================================================================
|
|
CREATE TABLE IF NOT EXISTS daily_bars (
|
|
symbol VARCHAR,
|
|
trade_date DATE,
|
|
open DOUBLE PRECISION,
|
|
high DOUBLE PRECISION,
|
|
low DOUBLE PRECISION,
|
|
close DOUBLE PRECISION,
|
|
volume BIGINT,
|
|
vwap DOUBLE PRECISION,
|
|
previous_close DOUBLE PRECISION,
|
|
true_range DOUBLE PRECISION,
|
|
atr_14 DOUBLE PRECISION,
|
|
rolling_avg_volume_20d DOUBLE PRECISION,
|
|
rolling_avg_volume_50d DOUBLE PRECISION,
|
|
prior_day_gain_pct DOUBLE PRECISION,
|
|
multi_day_runner_flag BOOLEAN DEFAULT FALSE,
|
|
PRIMARY KEY (symbol, trade_date)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS minute_bars (
|
|
symbol VARCHAR,
|
|
timestamp TIMESTAMP,
|
|
session_date DATE,
|
|
is_premarket BOOLEAN,
|
|
is_regular_hours BOOLEAN,
|
|
is_afterhours BOOLEAN,
|
|
open DOUBLE PRECISION,
|
|
high DOUBLE PRECISION,
|
|
low DOUBLE PRECISION,
|
|
close DOUBLE PRECISION,
|
|
volume BIGINT,
|
|
vwap DOUBLE PRECISION,
|
|
spread_pct DOUBLE PRECISION,
|
|
halt_status BOOLEAN DEFAULT FALSE,
|
|
source_provider VARCHAR DEFAULT 'synthetic',
|
|
quality_score DOUBLE PRECISION,
|
|
PRIMARY KEY (symbol, timestamp)
|
|
);
|
|
-- Fast per-symbol/session bar lookups (the `inspect bars` path).
|
|
CREATE INDEX IF NOT EXISTS idx_minute_bars_symbol_session
|
|
ON minute_bars (symbol, session_date);
|
|
|
|
-- =====================================================================
|
|
-- News / catalysts / halts / context
|
|
-- =====================================================================
|
|
CREATE TABLE IF NOT EXISTS news_events (
|
|
id VARCHAR,
|
|
symbol VARCHAR,
|
|
headline VARCHAR,
|
|
source VARCHAR,
|
|
published_at TIMESTAMP,
|
|
catalyst_freshness_minutes DOUBLE PRECISION,
|
|
category VARCHAR,
|
|
sentiment DOUBLE PRECISION,
|
|
is_earnings BOOLEAN DEFAULT FALSE,
|
|
is_offering BOOLEAN DEFAULT FALSE,
|
|
is_halt_related BOOLEAN DEFAULT FALSE,
|
|
PRIMARY KEY (id)
|
|
);
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS dilution_events (
|
|
id VARCHAR PRIMARY KEY,
|
|
symbol VARCHAR,
|
|
event_type VARCHAR,
|
|
announced_at TIMESTAMP,
|
|
effective_date DATE,
|
|
share_count BIGINT,
|
|
price_per_share DOUBLE PRECISION,
|
|
gross_proceeds DOUBLE PRECISION
|
|
);
|
|
|
|
|
|
-- =====================================================================
|
|
-- Features / setups / outcomes / backtests
|
|
-- =====================================================================
|
|
CREATE TABLE IF NOT EXISTS engineered_features (
|
|
id VARCHAR PRIMARY KEY,
|
|
timestamp TIMESTAMP,
|
|
symbol VARCHAR,
|
|
session_date DATE,
|
|
feature_version VARCHAR,
|
|
gap_pct DOUBLE PRECISION,
|
|
premarket_gap_pct DOUBLE PRECISION,
|
|
relative_volume DOUBLE PRECISION,
|
|
time_of_day_adjusted_relative_volume DOUBLE PRECISION,
|
|
float_rotation_pct DOUBLE PRECISION,
|
|
vwap DOUBLE PRECISION,
|
|
distance_from_vwap DOUBLE PRECISION,
|
|
ema9 DOUBLE PRECISION,
|
|
ema20 DOUBLE PRECISION,
|
|
pullback_volume_ratio DOUBLE PRECISION,
|
|
pullback_candle_type VARCHAR,
|
|
catalyst_freshness_minutes DOUBLE PRECISION,
|
|
catalyst_type VARCHAR,
|
|
tape_regime VARCHAR,
|
|
spy_intraday_return DOUBLE PRECISION,
|
|
vix_level DOUBLE PRECISION,
|
|
metadata_json VARCHAR
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS setup_events (
|
|
setup_id VARCHAR PRIMARY KEY,
|
|
symbol VARCHAR,
|
|
setup_time TIMESTAMP,
|
|
session_date DATE,
|
|
setup_name VARCHAR DEFAULT 'first_pullback',
|
|
setup_version VARCHAR DEFAULT 'v1',
|
|
entry_reference_price DOUBLE PRECISION,
|
|
invalidation_price DOUBLE PRECISION,
|
|
target_r_multiple DOUBLE PRECISION DEFAULT 2.0,
|
|
impulse_start_price DOUBLE PRECISION,
|
|
impulse_end_price DOUBLE PRECISION,
|
|
impulse_pct DOUBLE PRECISION,
|
|
pullback_low DOUBLE PRECISION,
|
|
pullback_depth_pct DOUBLE PRECISION,
|
|
pullback_bars INTEGER,
|
|
pullback_volume_ratio DOUBLE PRECISION,
|
|
above_vwap_flag BOOLEAN,
|
|
vwap_at_trigger DOUBLE PRECISION,
|
|
gap_pct DOUBLE PRECISION,
|
|
relative_volume DOUBLE PRECISION,
|
|
float_rotation_at_trigger DOUBLE PRECISION,
|
|
catalyst_freshness_at_trigger DOUBLE PRECISION,
|
|
session_minute_number INTEGER,
|
|
tape_regime_at_trigger VARCHAR,
|
|
spy_intraday_return_pct_at_trigger DOUBLE PRECISION
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS outcome_labels (
|
|
setup_id VARCHAR PRIMARY KEY,
|
|
label_version VARCHAR DEFAULT 'v1',
|
|
max_upside_next_5m DOUBLE PRECISION,
|
|
max_upside_next_15m DOUBLE PRECISION,
|
|
max_upside_next_60m DOUBLE PRECISION,
|
|
max_drawdown_next_5m DOUBLE PRECISION,
|
|
max_drawdown_next_15m DOUBLE PRECISION,
|
|
max_drawdown_next_60m DOUBLE PRECISION,
|
|
reached_1r_before_minus_1r BOOLEAN,
|
|
reached_2r_before_minus_1r BOOLEAN,
|
|
held_vwap_5m BOOLEAN,
|
|
held_vwap_15m BOOLEAN,
|
|
trend_day_flag BOOLEAN,
|
|
failed_breakout_flag BOOLEAN,
|
|
time_to_max_upside_minutes DOUBLE PRECISION,
|
|
time_to_max_drawdown_minutes DOUBLE PRECISION
|
|
);
|
|
|
|
|
|
-- =====================================================================
|
|
-- Paper trading
|
|
-- =====================================================================
|
|
|
|
|
|
|
|
|
|
|
|
-- =====================================================================
|
|
-- Raw landing (append-only) + telemetry + scanner snapshots
|
|
-- =====================================================================
|
|
CREATE TABLE IF NOT EXISTS raw_fetch_attempts (
|
|
id VARCHAR PRIMARY KEY,
|
|
source VARCHAR NOT NULL,
|
|
capability VARCHAR NOT NULL,
|
|
request_window_start TIMESTAMP,
|
|
request_window_end TIMESTAMP,
|
|
fetched_at TIMESTAMP NOT NULL,
|
|
ingest_run_id VARCHAR,
|
|
http_status INTEGER,
|
|
item_count INTEGER,
|
|
error_msg VARCHAR,
|
|
payload_hash VARCHAR,
|
|
parser_version VARCHAR
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_raw_fetch_attempts_source_window
|
|
ON raw_fetch_attempts (source, capability, request_window_start, request_window_end);
|
|
CREATE INDEX IF NOT EXISTS idx_raw_fetch_attempts_ingest_run
|
|
ON raw_fetch_attempts (ingest_run_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS raw_news_items (
|
|
id VARCHAR PRIMARY KEY,
|
|
fetch_attempt_id VARCHAR,
|
|
source VARCHAR,
|
|
raw_url VARCHAR,
|
|
raw_title VARCHAR,
|
|
raw_published_at VARCHAR,
|
|
raw_body_snippet VARCHAR,
|
|
raw_tickers VARCHAR,
|
|
payload_hash VARCHAR,
|
|
parser_version VARCHAR,
|
|
fetched_at TIMESTAMP,
|
|
ingest_run_id VARCHAR
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_raw_news_items_fetch_attempt
|
|
ON raw_news_items (fetch_attempt_id);
|
|
CREATE INDEX IF NOT EXISTS idx_raw_news_items_source_published
|
|
ON raw_news_items (source, raw_published_at);
|
|
|
|
-- Local-LLM (Ollama) catalyst enrichment cache. One row per (headline, ticker);
|
|
-- headline_hash = raw_news_items.payload_hash (sha256(source|url|title)) so we
|
|
-- dedupe and join for free. Read model for the dashboard advisory + Phase 2.
|
|
CREATE TABLE IF NOT EXISTS news_catalyst_cache (
|
|
headline_hash VARCHAR,
|
|
symbol VARCHAR,
|
|
headline VARCHAR,
|
|
source VARCHAR,
|
|
catalyst_type VARCHAR,
|
|
sentiment DOUBLE PRECISION,
|
|
conviction DOUBLE PRECISION,
|
|
is_dilutive BOOLEAN DEFAULT FALSE,
|
|
rationale VARCHAR,
|
|
model VARCHAR,
|
|
enriched_at TIMESTAMP DEFAULT current_timestamp,
|
|
PRIMARY KEY (headline_hash, symbol)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_news_catalyst_cache_symbol
|
|
ON news_catalyst_cache (symbol);
|
|
CREATE INDEX IF NOT EXISTS idx_news_catalyst_cache_enriched
|
|
ON news_catalyst_cache (enriched_at);
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS scanner_snapshots (
|
|
id VARCHAR PRIMARY KEY,
|
|
snapshot_time TIMESTAMP,
|
|
symbol VARCHAR,
|
|
rank INTEGER,
|
|
price DOUBLE PRECISION,
|
|
gap_pct DOUBLE PRECISION,
|
|
premarket_gap_pct DOUBLE PRECISION,
|
|
cumulative_volume BIGINT,
|
|
minute_volume BIGINT,
|
|
premarket_volume BIGINT,
|
|
relative_volume DOUBLE PRECISION,
|
|
float_rotation_pct DOUBLE PRECISION,
|
|
vwap DOUBLE PRECISION,
|
|
distance_from_vwap DOUBLE PRECISION,
|
|
ema9 DOUBLE PRECISION,
|
|
ema20 DOUBLE PRECISION,
|
|
intraday_range DOUBLE PRECISION,
|
|
intraday_range_vs_atr DOUBLE PRECISION,
|
|
distance_to_premarket_high DOUBLE PRECISION,
|
|
distance_to_premarket_low DOUBLE PRECISION,
|
|
distance_to_day_high DOUBLE PRECISION,
|
|
distance_to_day_low DOUBLE PRECISION,
|
|
news_flag BOOLEAN,
|
|
catalyst_freshness_minutes DOUBLE PRECISION,
|
|
catalyst_type VARCHAR,
|
|
float_bucket VARCHAR,
|
|
market_cap_bucket VARCHAR,
|
|
spread_pct DOUBLE PRECISION,
|
|
halt_flag BOOLEAN,
|
|
dilution_risk_flag BOOLEAN,
|
|
sympathy_move_candidate_flag BOOLEAN,
|
|
lead_runner_symbol VARCHAR,
|
|
sympathy_cluster_id VARCHAR,
|
|
early_leader_flag BOOLEAN,
|
|
rank_stability DOUBLE PRECISION,
|
|
momentum_score DOUBLE PRECISION,
|
|
scanner_version VARCHAR
|
|
);
|
|
|
|
-- =====================================================================
|
|
-- Late-added columns (parity with storage/schema.py:create_schema)
|
|
-- Postgres supports ADD COLUMN IF NOT EXISTS (9.6+).
|
|
-- =====================================================================
|
|
ALTER TABLE setup_events ADD COLUMN IF NOT EXISTS tape_regime_at_trigger VARCHAR;
|
|
ALTER TABLE setup_events ADD COLUMN IF NOT EXISTS spy_intraday_return_pct_at_trigger DOUBLE PRECISION;
|