-- Foxhunt HFT Trading System - Initial Database Schema -- Model Management Configuration Tables -- Create extensions CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "pg_notify"; -- Configuration table for system settings CREATE TABLE IF NOT EXISTS config_entries ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), key VARCHAR(255) UNIQUE NOT NULL, value TEXT NOT NULL, description TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Model configuration table for ML model management CREATE TABLE IF NOT EXISTS model_config ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(255) NOT NULL, version VARCHAR(50) NOT NULL, s3_path TEXT NOT NULL, cache_path TEXT, metadata JSONB DEFAULT '{}', is_active BOOLEAN DEFAULT false, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(name, version) ); -- Model versions table for version tracking CREATE TABLE IF NOT EXISTS model_versions ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), model_config_id UUID NOT NULL REFERENCES model_config(id) ON DELETE CASCADE, version VARCHAR(50) NOT NULL, s3_path TEXT NOT NULL, cache_path TEXT, checksum VARCHAR(64), size_bytes BIGINT, performance_metrics JSONB DEFAULT '{}', training_metadata JSONB DEFAULT '{}', is_current BOOLEAN DEFAULT false, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(model_config_id, version) ); -- Trading positions CREATE TABLE IF NOT EXISTS positions ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), symbol VARCHAR(50) NOT NULL, quantity DECIMAL(18,8) NOT NULL, entry_price DECIMAL(18,8) NOT NULL, current_price DECIMAL(18,8), pnl DECIMAL(18,8), created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Order history CREATE TABLE IF NOT EXISTS orders ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), symbol VARCHAR(50) NOT NULL, order_type VARCHAR(20) NOT NULL, side VARCHAR(10) NOT NULL, quantity DECIMAL(18,8) NOT NULL, price DECIMAL(18,8) NOT NULL, status VARCHAR(20) NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Indexes for fast lookups -- Config entries indexes CREATE INDEX IF NOT EXISTS idx_config_entries_key ON config_entries(key); CREATE INDEX IF NOT EXISTS idx_config_entries_updated_at ON config_entries(updated_at); -- Model config indexes CREATE INDEX IF NOT EXISTS idx_model_config_name ON model_config(name); CREATE INDEX IF NOT EXISTS idx_model_config_active ON model_config(is_active); CREATE INDEX IF NOT EXISTS idx_model_config_name_version ON model_config(name, version); CREATE INDEX IF NOT EXISTS idx_model_config_updated_at ON model_config(updated_at); -- Model versions indexes CREATE INDEX IF NOT EXISTS idx_model_versions_config_id ON model_versions(model_config_id); CREATE INDEX IF NOT EXISTS idx_model_versions_current ON model_versions(is_current); CREATE INDEX IF NOT EXISTS idx_model_versions_version ON model_versions(version); CREATE INDEX IF NOT EXISTS idx_model_versions_created_at ON model_versions(created_at); -- Trading indexes CREATE INDEX IF NOT EXISTS idx_positions_symbol ON positions(symbol); CREATE INDEX IF NOT EXISTS idx_positions_created_at ON positions(created_at); CREATE INDEX IF NOT EXISTS idx_orders_symbol ON orders(symbol); CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status); CREATE INDEX IF NOT EXISTS idx_orders_created_at ON orders(created_at); -- Update triggers for updated_at columns CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ language 'plpgsql'; CREATE TRIGGER update_config_entries_updated_at BEFORE UPDATE ON config_entries FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_model_config_updated_at BEFORE UPDATE ON model_config FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_model_versions_updated_at BEFORE UPDATE ON model_versions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_positions_updated_at BEFORE UPDATE ON positions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_orders_updated_at BEFORE UPDATE ON orders FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- Notification triggers for configuration hot-reload CREATE OR REPLACE FUNCTION notify_config_change() RETURNS TRIGGER AS $$ BEGIN CASE TG_OP WHEN 'INSERT', 'UPDATE' THEN PERFORM pg_notify('config_change', json_build_object( 'operation', TG_OP, 'table', TG_TABLE_NAME, 'id', NEW.id, 'key', COALESCE(NEW.key, NEW.name), 'timestamp', extract(epoch from NOW()) )::text ); RETURN NEW; WHEN 'DELETE' THEN PERFORM pg_notify('config_change', json_build_object( 'operation', TG_OP, 'table', TG_TABLE_NAME, 'id', OLD.id, 'key', COALESCE(OLD.key, OLD.name), 'timestamp', extract(epoch from NOW()) )::text ); RETURN OLD; END CASE; END; $$ language 'plpgsql'; -- Apply notification triggers CREATE TRIGGER notify_config_entries_change AFTER INSERT OR UPDATE OR DELETE ON config_entries FOR EACH ROW EXECUTE FUNCTION notify_config_change(); CREATE TRIGGER notify_model_config_change AFTER INSERT OR UPDATE OR DELETE ON model_config FOR EACH ROW EXECUTE FUNCTION notify_config_change(); CREATE TRIGGER notify_model_versions_change AFTER INSERT OR UPDATE OR DELETE ON model_versions FOR EACH ROW EXECUTE FUNCTION notify_config_change(); -- Initial configuration data INSERT INTO config_entries (key, value, description) VALUES ('system.latency_target_ns', '14', 'Target latency in nanoseconds'), ('trading.max_position_size', '1000000', 'Maximum position size in base currency'), ('risk.var_confidence', '0.95', 'VaR confidence level'), ('ml.model_cache_ttl', '3600', 'Model cache TTL in seconds'), ('s3.model_bucket', 'foxhunt-models', 'S3 bucket for model storage'), ('s3.model_prefix', 'models/', 'S3 prefix for models') ON CONFLICT (key) DO NOTHING;