initial setup

This commit is contained in:
Bojan Kucera 2025-06-02 08:15:20 -04:00
commit 232a63dfe8
61 changed files with 4985 additions and 0 deletions

View file

@ -0,0 +1,20 @@
-- Trading Bot Database Schema Initialization
-- Create schemas
CREATE SCHEMA IF NOT EXISTS trading;
CREATE SCHEMA IF NOT EXISTS strategy;
CREATE SCHEMA IF NOT EXISTS risk;
CREATE SCHEMA IF NOT EXISTS audit;
-- Set search path for the database
ALTER DATABASE trading_bot SET search_path TO trading, strategy, risk, audit, public;
-- Create extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "btree_gin";
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements";
-- Create a read-only user for analytics
CREATE USER trading_reader WITH PASSWORD 'reader_pass_dev';
GRANT CONNECT ON DATABASE trading_bot TO trading_reader;
GRANT USAGE ON SCHEMA trading, strategy, risk, audit TO trading_reader;

View file

@ -0,0 +1,93 @@
-- Core trading tables
-- Symbols and instruments
CREATE TABLE trading.symbols (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
symbol VARCHAR(20) NOT NULL UNIQUE,
name VARCHAR(255),
exchange VARCHAR(50),
asset_type VARCHAR(20) DEFAULT 'equity',
sector VARCHAR(100),
is_active BOOLEAN DEFAULT true,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Orders
CREATE TABLE trading.orders (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
symbol_id UUID REFERENCES trading.symbols(id),
strategy_id UUID,
order_type VARCHAR(20) NOT NULL, -- 'market', 'limit', 'stop', etc.
side VARCHAR(10) NOT NULL CHECK (side IN ('buy', 'sell')),
quantity DECIMAL(18,8) NOT NULL CHECK (quantity > 0),
price DECIMAL(18,8),
stop_price DECIMAL(18,8),
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'submitted', 'filled', 'cancelled', 'rejected')),
broker_order_id VARCHAR(100),
filled_quantity DECIMAL(18,8) DEFAULT 0,
avg_fill_price DECIMAL(18,8),
commission DECIMAL(18,8) DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
CONSTRAINT valid_prices CHECK (
(order_type = 'market') OR
(order_type = 'limit' AND price IS NOT NULL) OR
(order_type = 'stop' AND stop_price IS NOT NULL)
)
);
-- Positions
CREATE TABLE trading.positions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
symbol_id UUID REFERENCES trading.symbols(id),
strategy_id UUID,
quantity DECIMAL(18,8) NOT NULL,
avg_cost DECIMAL(18,8) NOT NULL,
market_value DECIMAL(18,8),
unrealized_pnl DECIMAL(18,8),
realized_pnl DECIMAL(18,8) DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(symbol_id, strategy_id)
);
-- Executions/Fills
CREATE TABLE trading.executions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
order_id UUID REFERENCES trading.orders(id),
symbol_id UUID REFERENCES trading.symbols(id),
side VARCHAR(10) NOT NULL CHECK (side IN ('buy', 'sell')),
quantity DECIMAL(18,8) NOT NULL,
price DECIMAL(18,8) NOT NULL,
commission DECIMAL(18,8) DEFAULT 0,
broker_execution_id VARCHAR(100),
executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Accounts/Portfolios
CREATE TABLE trading.accounts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(255) NOT NULL,
account_type VARCHAR(50) DEFAULT 'paper', -- 'paper', 'live'
broker VARCHAR(50),
cash_balance DECIMAL(18,2) DEFAULT 0,
buying_power DECIMAL(18,2) DEFAULT 0,
total_value DECIMAL(18,2) DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create indexes for performance
CREATE INDEX idx_orders_symbol_created ON trading.orders(symbol_id, created_at);
CREATE INDEX idx_orders_status ON trading.orders(status);
CREATE INDEX idx_orders_strategy ON trading.orders(strategy_id);
CREATE INDEX idx_positions_strategy ON trading.positions(strategy_id);
CREATE INDEX idx_executions_order ON trading.executions(order_id);
CREATE INDEX idx_executions_symbol_time ON trading.executions(symbol_id, executed_at);
-- Grant permissions to reader
GRANT SELECT ON ALL TABLES IN SCHEMA trading TO trading_reader;

View file

@ -0,0 +1,105 @@
-- Strategy and Risk Management Tables
-- Strategies
CREATE TABLE strategy.strategies (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(255) NOT NULL,
description TEXT,
version VARCHAR(20) DEFAULT '1.0.0',
config JSONB DEFAULT '{}',
parameters JSONB DEFAULT '{}',
is_active BOOLEAN DEFAULT false,
is_enabled BOOLEAN DEFAULT true,
created_by VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Strategy executions/runs
CREATE TABLE strategy.executions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
strategy_id UUID REFERENCES strategy.strategies(id),
status VARCHAR(20) DEFAULT 'running' CHECK (status IN ('running', 'stopped', 'error', 'completed')),
started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
stopped_at TIMESTAMP WITH TIME ZONE,
error_message TEXT,
execution_stats JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Strategy signals
CREATE TABLE strategy.signals (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
strategy_id UUID REFERENCES strategy.strategies(id),
symbol_id UUID REFERENCES trading.symbols(id),
signal_type VARCHAR(20) NOT NULL CHECK (signal_type IN ('buy', 'sell', 'hold')),
strength DECIMAL(3,2) CHECK (strength >= 0 AND strength <= 1), -- 0.0 to 1.0
confidence DECIMAL(3,2) CHECK (confidence >= 0 AND confidence <= 1),
target_price DECIMAL(18,8),
stop_loss DECIMAL(18,8),
take_profit DECIMAL(18,8),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Risk limits
CREATE TABLE risk.limits (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
strategy_id UUID REFERENCES strategy.strategies(id),
account_id UUID REFERENCES trading.accounts(id),
limit_type VARCHAR(50) NOT NULL, -- 'max_position_size', 'max_daily_loss', 'max_drawdown', etc.
limit_value DECIMAL(18,8) NOT NULL,
current_value DECIMAL(18,8) DEFAULT 0,
threshold_warning DECIMAL(18,8), -- Warning at X% of limit
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Risk events/alerts
CREATE TABLE risk.events (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
limit_id UUID REFERENCES risk.limits(id),
strategy_id UUID,
event_type VARCHAR(50) NOT NULL, -- 'warning', 'breach', 'resolved'
severity VARCHAR(20) DEFAULT 'medium' CHECK (severity IN ('low', 'medium', 'high', 'critical')),
message TEXT NOT NULL,
current_value DECIMAL(18,8),
limit_value DECIMAL(18,8),
metadata JSONB DEFAULT '{}',
acknowledged BOOLEAN DEFAULT false,
acknowledged_by VARCHAR(255),
acknowledged_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Performance tracking
CREATE TABLE strategy.performance (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
strategy_id UUID REFERENCES strategy.strategies(id),
date DATE NOT NULL,
total_return DECIMAL(10,4),
daily_return DECIMAL(10,4),
sharpe_ratio DECIMAL(10,4),
max_drawdown DECIMAL(10,4),
win_rate DECIMAL(5,4),
profit_factor DECIMAL(10,4),
total_trades INTEGER DEFAULT 0,
winning_trades INTEGER DEFAULT 0,
losing_trades INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(strategy_id, date)
);
-- Create indexes
CREATE INDEX idx_strategies_active ON strategy.strategies(is_active, is_enabled);
CREATE INDEX idx_executions_strategy ON strategy.executions(strategy_id);
CREATE INDEX idx_signals_strategy_time ON strategy.signals(strategy_id, created_at);
CREATE INDEX idx_signals_symbol ON strategy.signals(symbol_id);
CREATE INDEX idx_limits_strategy ON risk.limits(strategy_id);
CREATE INDEX idx_risk_events_severity ON risk.events(severity, created_at);
CREATE INDEX idx_performance_strategy_date ON strategy.performance(strategy_id, date);
-- Grant permissions
GRANT SELECT ON ALL TABLES IN SCHEMA strategy TO trading_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA risk TO trading_reader;

View file

@ -0,0 +1,59 @@
-- Audit and System Tables
-- System events audit
CREATE TABLE audit.system_events (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
service_name VARCHAR(100) NOT NULL,
event_type VARCHAR(50) NOT NULL,
event_data JSONB DEFAULT '{}',
user_id VARCHAR(255),
ip_address INET,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Trading events audit
CREATE TABLE audit.trading_events (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
event_type VARCHAR(50) NOT NULL, -- 'order_created', 'order_filled', 'position_opened', etc.
entity_type VARCHAR(50) NOT NULL, -- 'order', 'position', 'execution'
entity_id UUID NOT NULL,
old_values JSONB,
new_values JSONB,
changed_by VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Service health monitoring
CREATE TABLE audit.service_health (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
service_name VARCHAR(100) NOT NULL,
status VARCHAR(20) NOT NULL CHECK (status IN ('healthy', 'unhealthy', 'degraded')),
version VARCHAR(50),
uptime_seconds INTEGER,
memory_usage_mb INTEGER,
cpu_usage_percent DECIMAL(5,2),
last_health_check TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Configuration changes
CREATE TABLE audit.config_changes (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
config_key VARCHAR(255) NOT NULL,
old_value TEXT,
new_value TEXT,
changed_by VARCHAR(255),
reason TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create indexes
CREATE INDEX idx_system_events_service_time ON audit.system_events(service_name, created_at);
CREATE INDEX idx_trading_events_type_time ON audit.trading_events(event_type, created_at);
CREATE INDEX idx_trading_events_entity ON audit.trading_events(entity_type, entity_id);
CREATE INDEX idx_service_health_name_time ON audit.service_health(service_name, created_at);
CREATE INDEX idx_config_changes_key_time ON audit.config_changes(config_key, created_at);
-- Grant permissions
GRANT SELECT ON ALL TABLES IN SCHEMA audit TO trading_reader;

View file

@ -0,0 +1,55 @@
-- Insert initial reference data
-- Insert common symbols
INSERT INTO trading.symbols (symbol, name, exchange, asset_type, sector) VALUES
('AAPL', 'Apple Inc.', 'NASDAQ', 'equity', 'Technology'),
('GOOGL', 'Alphabet Inc.', 'NASDAQ', 'equity', 'Technology'),
('MSFT', 'Microsoft Corporation', 'NASDAQ', 'equity', 'Technology'),
('AMZN', 'Amazon.com Inc.', 'NASDAQ', 'equity', 'Consumer Discretionary'),
('TSLA', 'Tesla Inc.', 'NASDAQ', 'equity', 'Consumer Discretionary'),
('NVDA', 'NVIDIA Corporation', 'NASDAQ', 'equity', 'Technology'),
('META', 'Meta Platforms Inc.', 'NASDAQ', 'equity', 'Technology'),
('NFLX', 'Netflix Inc.', 'NASDAQ', 'equity', 'Communication Services'),
('SPY', 'SPDR S&P 500 ETF Trust', 'NYSE', 'etf', 'Broad Market'),
('QQQ', 'Invesco QQQ Trust', 'NASDAQ', 'etf', 'Technology'),
('BTC-USD', 'Bitcoin USD', 'CRYPTO', 'cryptocurrency', 'Digital Assets'),
('ETH-USD', 'Ethereum USD', 'CRYPTO', 'cryptocurrency', 'Digital Assets');
-- Insert default trading account
INSERT INTO trading.accounts (name, account_type, broker, cash_balance, buying_power, total_value) VALUES
('Demo Account', 'paper', 'demo', 100000.00, 100000.00, 100000.00);
-- Insert demo strategy
INSERT INTO strategy.strategies (name, description, config, parameters, is_active) VALUES
('Demo Mean Reversion', 'Simple mean reversion strategy for demonstration',
'{"timeframe": "1h", "lookback_period": 20}',
'{"rsi_oversold": 30, "rsi_overbought": 70, "position_size": 0.1}',
false);
-- Insert basic risk limits
INSERT INTO risk.limits (strategy_id, limit_type, limit_value, threshold_warning)
SELECT s.id, 'max_position_size', 10000.00, 8000.00
FROM strategy.strategies s
WHERE s.name = 'Demo Mean Reversion';
INSERT INTO risk.limits (strategy_id, limit_type, limit_value, threshold_warning)
SELECT s.id, 'max_daily_loss', 5000.00, 4000.00
FROM strategy.strategies s
WHERE s.name = 'Demo Mean Reversion';
-- Create updated_at trigger function
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
-- Apply updated_at triggers
CREATE TRIGGER update_symbols_updated_at BEFORE UPDATE ON trading.symbols FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_orders_updated_at BEFORE UPDATE ON trading.orders FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_positions_updated_at BEFORE UPDATE ON trading.positions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_accounts_updated_at BEFORE UPDATE ON trading.accounts FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_strategies_updated_at BEFORE UPDATE ON strategy.strategies FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_limits_updated_at BEFORE UPDATE ON risk.limits FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();