-- Foxhunt HFT Trading System Database Initialization -- Creates database schema, users, and initial configuration -- Create database (if not exists via environment) -- This runs after the database specified in POSTGRES_DB is created \c foxhunt; -- Create extensions CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "pg_stat_statements"; CREATE EXTENSION IF NOT EXISTS "pgcrypto"; CREATE EXTENSION IF NOT EXISTS "hstore"; CREATE EXTENSION IF NOT EXISTS "ltree"; -- Create application roles DO $$ BEGIN -- Trading service role IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'foxhunt_trading') THEN CREATE ROLE foxhunt_trading LOGIN PASSWORD 'trading_secure_password_123!'; END IF; -- ML service role IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'foxhunt_ml') THEN CREATE ROLE foxhunt_ml LOGIN PASSWORD 'ml_secure_password_456!'; END IF; -- Backtesting service role IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'foxhunt_backtesting') THEN CREATE ROLE foxhunt_backtesting LOGIN PASSWORD 'backtesting_secure_password_789!'; END IF; -- Read-only role for reporting IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'foxhunt_readonly') THEN CREATE ROLE foxhunt_readonly LOGIN PASSWORD 'readonly_secure_password_101!'; END IF; END $$; -- Create schemas CREATE SCHEMA IF NOT EXISTS trading; CREATE SCHEMA IF NOT EXISTS ml; CREATE SCHEMA IF NOT EXISTS backtesting; CREATE SCHEMA IF NOT EXISTS config; CREATE SCHEMA IF NOT EXISTS audit; CREATE SCHEMA IF NOT EXISTS monitoring; -- Grant schema permissions GRANT USAGE ON SCHEMA trading TO foxhunt_trading; GRANT ALL PRIVILEGES ON SCHEMA trading TO foxhunt_trading; GRANT USAGE ON SCHEMA ml TO foxhunt_ml; GRANT ALL PRIVILEGES ON SCHEMA ml TO foxhunt_ml; GRANT USAGE ON SCHEMA backtesting TO foxhunt_backtesting; GRANT ALL PRIVILEGES ON SCHEMA backtesting TO foxhunt_backtesting; GRANT USAGE ON SCHEMA config TO foxhunt_trading, foxhunt_ml, foxhunt_backtesting; GRANT SELECT ON ALL TABLES IN SCHEMA config TO foxhunt_trading, foxhunt_ml, foxhunt_backtesting; -- Read-only access for monitoring GRANT USAGE ON ALL SCHEMAS TO foxhunt_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA trading TO foxhunt_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA ml TO foxhunt_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA backtesting TO foxhunt_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA config TO foxhunt_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA audit TO foxhunt_readonly; GRANT SELECT ON ALL TABLES IN SCHEMA monitoring TO foxhunt_readonly; -- Create configuration tables CREATE TABLE IF NOT EXISTS config.settings ( id SERIAL PRIMARY KEY, namespace VARCHAR(100) NOT NULL, key VARCHAR(100) NOT NULL, value TEXT NOT NULL, value_type VARCHAR(20) NOT NULL DEFAULT 'string', description TEXT, is_encrypted BOOLEAN DEFAULT FALSE, is_sensitive BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(namespace, key) ); -- Create audit trail table CREATE TABLE IF NOT EXISTS audit.events ( id BIGSERIAL PRIMARY KEY, event_id UUID DEFAULT uuid_generate_v4() UNIQUE, service_name VARCHAR(50) NOT NULL, event_type VARCHAR(50) NOT NULL, entity_type VARCHAR(50), entity_id VARCHAR(100), user_id VARCHAR(100), session_id VARCHAR(100), event_data JSONB, ip_address INET, user_agent TEXT, timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(), severity VARCHAR(20) DEFAULT 'INFO' ); -- Create indexes for performance CREATE INDEX IF NOT EXISTS idx_config_settings_namespace_key ON config.settings(namespace, key); CREATE INDEX IF NOT EXISTS idx_config_settings_updated_at ON config.settings(updated_at); CREATE INDEX IF NOT EXISTS idx_audit_events_timestamp ON audit.events(timestamp); CREATE INDEX IF NOT EXISTS idx_audit_events_service ON audit.events(service_name); CREATE INDEX IF NOT EXISTS idx_audit_events_type ON audit.events(event_type); CREATE INDEX IF NOT EXISTS idx_audit_events_user ON audit.events(user_id); CREATE INDEX IF NOT EXISTS idx_audit_events_session ON audit.events(session_id); -- Create NOTIFY trigger function for configuration changes CREATE OR REPLACE FUNCTION config.notify_config_change() RETURNS TRIGGER AS $$ BEGIN -- Notify all listening services of configuration changes IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN PERFORM pg_notify('config_change', json_build_object( 'operation', TG_OP, 'namespace', NEW.namespace, 'key', NEW.key, 'timestamp', extract(epoch from NOW()) )::text ); RETURN NEW; ELSIF TG_OP = 'DELETE' THEN PERFORM pg_notify('config_change', json_build_object( 'operation', TG_OP, 'namespace', OLD.namespace, 'key', OLD.key, 'timestamp', extract(epoch from NOW()) )::text ); RETURN OLD; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql; -- Create trigger for configuration notifications DROP TRIGGER IF EXISTS trigger_config_notify ON config.settings; CREATE TRIGGER trigger_config_notify AFTER INSERT OR UPDATE OR DELETE ON config.settings FOR EACH ROW EXECUTE FUNCTION config.notify_config_change(); -- Insert initial configuration INSERT INTO config.settings (namespace, key, value, value_type, description, is_sensitive) VALUES ('trading', 'max_position_size', '1000000', 'integer', 'Maximum position size in base currency', FALSE), ('trading', 'max_daily_loss', '50000', 'integer', 'Maximum daily loss threshold', FALSE), ('trading', 'circuit_breaker_enabled', 'true', 'boolean', 'Enable circuit breaker functionality', FALSE), ('trading', 'paper_trading_mode', 'false', 'boolean', 'Enable paper trading mode', FALSE), ('ml', 'model_training_enabled', 'true', 'boolean', 'Enable ML model training', FALSE), ('ml', 'inference_timeout_ms', '100', 'integer', 'ML inference timeout in milliseconds', FALSE), ('ml', 'model_update_frequency', '3600', 'integer', 'Model update frequency in seconds', FALSE), ('backtesting', 'max_concurrent_tests', '4', 'integer', 'Maximum concurrent backtests', FALSE), ('backtesting', 'default_commission', '0.001', 'float', 'Default commission rate', FALSE), ('compliance', 'best_execution_monitoring', 'true', 'boolean', 'Enable best execution monitoring', FALSE), ('compliance', 'transaction_reporting', 'true', 'boolean', 'Enable transaction reporting', FALSE), ('compliance', 'audit_trail_retention_days', '2555', 'integer', 'Audit trail retention period (7 years)', FALSE), ('monitoring', 'metrics_collection_interval', '10', 'integer', 'Metrics collection interval in seconds', FALSE), ('monitoring', 'health_check_interval', '30', 'integer', 'Health check interval in seconds', FALSE), ('security', 'jwt_expiry_hours', '24', 'integer', 'JWT token expiry in hours', FALSE), ('security', 'max_failed_logins', '5', 'integer', 'Maximum failed login attempts', FALSE) ON CONFLICT (namespace, key) DO NOTHING; -- Create function to update timestamps CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; -- Create trigger to automatically update timestamps DROP TRIGGER IF EXISTS trigger_update_config_timestamp ON config.settings; CREATE TRIGGER trigger_update_config_timestamp BEFORE UPDATE ON config.settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- Create monitoring tables CREATE TABLE IF NOT EXISTS monitoring.service_health ( id BIGSERIAL PRIMARY KEY, service_name VARCHAR(50) NOT NULL, status VARCHAR(20) NOT NULL, message TEXT, response_time_ms INTEGER, memory_usage_bytes BIGINT, cpu_usage_percent DECIMAL(5,2), timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_monitoring_service_health_service ON monitoring.service_health(service_name); CREATE INDEX IF NOT EXISTS idx_monitoring_service_health_timestamp ON monitoring.service_health(timestamp); CREATE INDEX IF NOT EXISTS idx_monitoring_service_health_status ON monitoring.service_health(status); -- Vacuum and analyze for optimal performance VACUUM ANALYZE; -- Display initialization summary SELECT 'Foxhunt HFT Database Initialized Successfully' AS status, (SELECT COUNT(*) FROM config.settings) AS config_entries, NOW() AS initialized_at;