Files
invest-copilot/init.sql
T
gitea a16050c80a
CI / lint-and-build (push) Has been cancelled
CI / python-checks (3.12) (push) Has been cancelled
feat: multiple updates - alerts, auth, sectors, rotation service, financials ingestion, task specs, and agent framework
2026-06-06 22:01:40 -04:00

224 lines
7.5 KiB
SQL

-- TimescaleDB initialization script
-- This script creates the necessary extensions and hypertables
-- Enable TimescaleDB extension
CREATE EXTENSION IF NOT EXISTS timescaledb;
-- Create stock profiles table
CREATE TABLE IF NOT EXISTS stock_profiles (
ticker VARCHAR(20) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
exchange VARCHAR(50),
sector VARCHAR(100),
industry VARCHAR(100),
market_cap NUMERIC(20, 2),
description TEXT,
website VARCHAR(500),
ceo VARCHAR(255),
employees INTEGER,
pe_ratio NUMERIC(10, 2),
eps NUMERIC(10, 2),
dividend_yield NUMERIC(8, 4),
beta NUMERIC(8, 4),
last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create users table
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(255),
timezone VARCHAR(50) DEFAULT 'UTC',
settings JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create prices table (hypertable for TimescaleDB)
CREATE TABLE IF NOT EXISTS prices (
ticker VARCHAR(20) NOT NULL,
date DATE NOT NULL,
open NUMERIC(12, 2),
high NUMERIC(12, 2),
low NUMERIC(12, 2),
close NUMERIC(12, 2),
volume BIGINT,
adjusted_close NUMERIC(12, 2),
PRIMARY KEY (ticker, date)
);
SELECT create_hypertable('prices', 'date', if_not_exists => TRUE);
-- Create watchlists table
CREATE TABLE IF NOT EXISTS watchlists (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
is_default BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create watchlist items table
CREATE TABLE IF NOT EXISTS watchlist_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE,
ticker VARCHAR(20) NOT NULL,
type VARCHAR(20) DEFAULT 'stock',
custom_notes TEXT,
added_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
price_at_addition NUMERIC(12, 2),
UNIQUE (watchlist_id, ticker)
);
-- Create strategies table
CREATE TABLE IF NOT EXISTS strategies (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
type VARCHAR(50) NOT NULL,
conditions JSONB NOT NULL,
backtest_results JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create screeners table
CREATE TABLE IF NOT EXISTS screeners (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
filters JSONB,
last_run_at TIMESTAMP WITH TIME ZONE,
results_count INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create screener runs table
CREATE TABLE IF NOT EXISTS screener_runs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
screener_id UUID NOT NULL REFERENCES screeners(id) ON DELETE CASCADE,
results JSONB NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create alerts table
CREATE TABLE IF NOT EXISTS alerts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE,
type VARCHAR(50) NOT NULL,
trigger_type VARCHAR(50),
message TEXT NOT NULL,
severity VARCHAR(20) DEFAULT 'info',
status VARCHAR(20) DEFAULT 'active',
ticker VARCHAR(20),
triggered_at TIMESTAMP WITH TIME ZONE,
resolved_at TIMESTAMP WITH TIME ZONE,
metadata JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create sector rotations table
CREATE TABLE IF NOT EXISTS sector_rotations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
detection_date DATE NOT NULL,
sector_ticker VARCHAR(20) NOT NULL,
sector_name VARCHAR(100) NOT NULL,
rank_now INTEGER,
rank_previous INTEGER,
rank_change INTEGER,
momentum_20d NUMERIC(10, 4),
momentum_50d NUMERIC(10, 4),
momentum_200d NUMERIC(10, 4),
relative_strength NUMERIC(10, 4),
rotation_signal VARCHAR(20),
macro_context TEXT,
analysis_summary TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create SEC filings table
CREATE TABLE IF NOT EXISTS sec_filings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
ticker VARCHAR(20) NOT NULL,
cik VARCHAR(20),
form_type VARCHAR(20),
filing_date DATE,
report_date DATE,
accession_number VARCHAR(50),
url TEXT,
content_summary TEXT,
key_metrics JSONB,
sentiment_score NUMERIC(5, 2),
tags TEXT[],
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create insider trades table
CREATE TABLE IF NOT EXISTS insider_trades (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
ticker VARCHAR(20) NOT NULL,
insider_name VARCHAR(255) NOT NULL,
insider_title VARCHAR(255),
transaction_date DATE NOT NULL,
transaction_type VARCHAR(20),
shares INTEGER,
price_per_share NUMERIC(12, 2),
total_value NUMERIC(15, 2),
shares_owned_after INTEGER,
filing_date DATE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create peer groups table
CREATE TABLE IF NOT EXISTS peer_groups (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
ticker VARCHAR(20) NOT NULL,
peer_ticker VARCHAR(20) NOT NULL,
similarity_score NUMERIC(5, 2),
UNIQUE (ticker, peer_ticker)
);
-- Create indexes for performance
CREATE INDEX IF NOT EXISTS idx_prices_ticker_date ON prices (ticker, date DESC);
CREATE INDEX IF NOT EXISTS idx_watchlists_user_id ON watchlists (user_id);
CREATE INDEX IF NOT EXISTS idx_strategies_user_id ON strategies (user_id);
CREATE INDEX IF NOT EXISTS idx_screeners_user_id ON screeners (user_id);
CREATE INDEX IF NOT EXISTS idx_alerts_watchlist_id ON alerts (watchlist_id);
CREATE INDEX IF NOT EXISTS idx_sec_filings_ticker ON sec_filings (ticker);
CREATE INDEX IF NOT EXISTS idx_insider_trades_ticker ON insider_trades (ticker);
CREATE INDEX IF NOT EXISTS idx_sector_rotations_date ON sector_rotations (detection_date DESC);
-- Financials table (income statement / balance sheet / cash flow snapshots)
CREATE TABLE IF NOT EXISTS financials (
ticker VARCHAR(20) NOT NULL,
filing_date DATE NOT NULL,
period VARCHAR(10) NOT NULL,
period_end DATE,
revenue NUMERIC(18,2),
cost_of_revenue NUMERIC(18,2),
gross_profit NUMERIC(18,2),
operating_expense NUMERIC(18,2),
operating_income NUMERIC(18,2),
net_income NUMERIC(18,2),
eps_basic NUMERIC(12,4),
eps_diluted NUMERIC(12,4),
total_assets NUMERIC(20,2),
total_liabilities NUMERIC(20,2),
total_equity NUMERIC(20,2),
operating_cashflow NUMERIC(18,2),
free_cashflow NUMERIC(18,2),
debt_to_equity NUMERIC(8,4),
roe NUMERIC(8,4),
roa NUMERIC(8,4),
created_at TIMESTAMPTZ DEFAULT now(),
PRIMARY KEY (ticker, filing_date, period)
);
CREATE INDEX IF NOT EXISTS idx_financials_ticker ON financials (ticker);
CREATE INDEX IF NOT EXISTS idx_financials_period ON financials (period);