Codebase audit identified 23 findings across 4 dimensions (production safety, code health, deployment readiness, test quality). This commit fixes all of them. Broker execution layer (was entirely stubbed): - Real IBKR TWS client via ibapi crate (950+ lines, feature-gated) - ICMarkets ctrader-openapi now always-on (removed feature flag) - Real broker routing with health monitoring and exponential backoff reconnect - Validated against live IB Gateway Docker (6/6 connectivity tests pass) Deployment blockers: - Fixed 6 broken Dockerfiles (removed COPY foxhunt-deploy) - Created foxhunt K8s namespace, secret templates, migration job - Added liveness probes to all 7 K8s services - IB Gateway manifest (ghcr.io/gnzsnz/ib-gateway:stable) - IBKR credentials in Scaleway Secret Manager via Terragrunt - Fixed port collisions and mismatches across services Production safety (9 critical + 6 high/medium fixes): - Asset-class-specific VaR volatility (not flat 2%) - Real parametric VaR with z-score 95th percentile - Kyle's lambda regression (100-bar rolling window) - Per-feature running statistics from historical data - VWAP-based slippage reference, regime duration tracking - Real Databento JSON parsing for OHLCV/Trade/Quote Code health: - Removed #![allow(dead_code)] from ml, data, config - Fixed log:: → tracing:: in 4 production files - Removed dead workspace deps (ratatui, crossterm) Verified: cargo check --workspace (0 errors), trading_engine 330 tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
206 lines
7.6 KiB
SQL
206 lines
7.6 KiB
SQL
-- Migration: Create backtesting tables
|
|
-- Version: 001
|
|
-- Description: Initial database schema for backtesting service
|
|
|
|
-- Backtests table - stores backtest metadata
|
|
CREATE TABLE IF NOT EXISTS backtests (
|
|
id SERIAL PRIMARY KEY,
|
|
backtest_id VARCHAR(255) UNIQUE NOT NULL,
|
|
strategy_name VARCHAR(255) NOT NULL,
|
|
symbols TEXT NOT NULL, -- JSON array of symbols
|
|
start_date TIMESTAMPTZ NOT NULL,
|
|
end_date TIMESTAMPTZ NOT NULL,
|
|
initial_capital DECIMAL(20, 8) NOT NULL,
|
|
parameters TEXT, -- JSON object of strategy parameters
|
|
description TEXT,
|
|
status VARCHAR(50) NOT NULL DEFAULT 'queued',
|
|
error_message TEXT,
|
|
|
|
-- Performance summary (filled when completed)
|
|
total_return DECIMAL(10, 6),
|
|
sharpe_ratio DECIMAL(10, 6),
|
|
max_drawdown DECIMAL(10, 6),
|
|
total_trades BIGINT,
|
|
win_rate DECIMAL(10, 6),
|
|
profit_factor DECIMAL(10, 6),
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
started_at TIMESTAMPTZ,
|
|
completed_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- Indexes for backtests
|
|
CREATE INDEX IF NOT EXISTS idx_backtests_backtest_id ON backtests(backtest_id);
|
|
CREATE INDEX IF NOT EXISTS idx_backtests_strategy_name ON backtests(strategy_name);
|
|
CREATE INDEX IF NOT EXISTS idx_backtests_status ON backtests(status);
|
|
CREATE INDEX IF NOT EXISTS idx_backtests_created_at ON backtests(created_at);
|
|
|
|
-- Backtest trades table - stores individual trade executions
|
|
CREATE TABLE IF NOT EXISTS backtest_trades (
|
|
id SERIAL PRIMARY KEY,
|
|
backtest_id VARCHAR(255) NOT NULL,
|
|
trade_id VARCHAR(255) NOT NULL,
|
|
symbol VARCHAR(50) NOT NULL,
|
|
side VARCHAR(10) NOT NULL, -- 'Buy' or 'Sell'
|
|
quantity DECIMAL(20, 8) NOT NULL,
|
|
entry_price DECIMAL(20, 8) NOT NULL,
|
|
exit_price DECIMAL(20, 8) NOT NULL,
|
|
entry_time TIMESTAMPTZ NOT NULL,
|
|
exit_time TIMESTAMPTZ NOT NULL,
|
|
pnl DECIMAL(20, 8) NOT NULL,
|
|
return_percent DECIMAL(10, 6) NOT NULL,
|
|
entry_signal TEXT,
|
|
exit_signal TEXT,
|
|
|
|
-- Foreign key
|
|
FOREIGN KEY (backtest_id) REFERENCES backtests(backtest_id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Indexes for backtest_trades
|
|
CREATE INDEX IF NOT EXISTS idx_trades_backtest_id ON backtest_trades(backtest_id);
|
|
CREATE INDEX IF NOT EXISTS idx_trades_symbol ON backtest_trades(symbol);
|
|
CREATE INDEX IF NOT EXISTS idx_trades_entry_time ON backtest_trades(entry_time);
|
|
CREATE INDEX IF NOT EXISTS idx_trades_pnl ON backtest_trades(pnl);
|
|
|
|
-- Backtest metrics table - stores detailed performance metrics
|
|
CREATE TABLE IF NOT EXISTS backtest_metrics (
|
|
id SERIAL PRIMARY KEY,
|
|
backtest_id VARCHAR(255) UNIQUE NOT NULL,
|
|
|
|
-- Return metrics
|
|
total_return DECIMAL(10, 6) NOT NULL,
|
|
annualized_return DECIMAL(10, 6) NOT NULL,
|
|
|
|
-- Risk metrics
|
|
sharpe_ratio DECIMAL(10, 6) NOT NULL,
|
|
sortino_ratio DECIMAL(10, 6) NOT NULL,
|
|
max_drawdown DECIMAL(10, 6) NOT NULL,
|
|
volatility DECIMAL(10, 6) NOT NULL,
|
|
calmar_ratio DECIMAL(10, 6) NOT NULL,
|
|
|
|
-- Trade metrics
|
|
win_rate DECIMAL(10, 6) NOT NULL,
|
|
profit_factor DECIMAL(10, 6) NOT NULL,
|
|
total_trades BIGINT NOT NULL,
|
|
winning_trades BIGINT NOT NULL,
|
|
losing_trades BIGINT NOT NULL,
|
|
avg_win DECIMAL(20, 8) NOT NULL,
|
|
avg_loss DECIMAL(20, 8) NOT NULL,
|
|
largest_win DECIMAL(20, 8) NOT NULL,
|
|
largest_loss DECIMAL(20, 8) NOT NULL,
|
|
|
|
-- Risk measures
|
|
var_95 DECIMAL(10, 6),
|
|
expected_shortfall DECIMAL(10, 6),
|
|
|
|
-- Benchmark comparison (optional)
|
|
beta DECIMAL(10, 6),
|
|
alpha DECIMAL(10, 6),
|
|
information_ratio DECIMAL(10, 6),
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
-- Foreign key
|
|
FOREIGN KEY (backtest_id) REFERENCES backtests(backtest_id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Index for backtest_metrics
|
|
CREATE INDEX IF NOT EXISTS idx_metrics_backtest_id ON backtest_metrics(backtest_id);
|
|
|
|
-- Equity curve table - stores equity progression over time
|
|
CREATE TABLE IF NOT EXISTS backtest_equity_curve (
|
|
id SERIAL PRIMARY KEY,
|
|
backtest_id VARCHAR(255) NOT NULL,
|
|
timestamp TIMESTAMPTZ NOT NULL,
|
|
equity DECIMAL(20, 8) NOT NULL,
|
|
drawdown DECIMAL(10, 6) NOT NULL,
|
|
benchmark_equity DECIMAL(20, 8),
|
|
|
|
-- Foreign key
|
|
FOREIGN KEY (backtest_id) REFERENCES backtests(backtest_id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Indexes for backtest_equity_curve
|
|
CREATE INDEX IF NOT EXISTS idx_equity_backtest_id ON backtest_equity_curve(backtest_id);
|
|
CREATE INDEX IF NOT EXISTS idx_equity_timestamp ON backtest_equity_curve(timestamp);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_equity_backtest_timestamp ON backtest_equity_curve(backtest_id, timestamp);
|
|
|
|
-- Drawdown periods table - stores significant drawdown periods
|
|
CREATE TABLE IF NOT EXISTS backtest_drawdown_periods (
|
|
id SERIAL PRIMARY KEY,
|
|
backtest_id VARCHAR(255) NOT NULL,
|
|
start_time TIMESTAMPTZ NOT NULL,
|
|
end_time TIMESTAMPTZ NOT NULL,
|
|
peak_value DECIMAL(20, 8) NOT NULL,
|
|
trough_value DECIMAL(20, 8) NOT NULL,
|
|
drawdown_percent DECIMAL(10, 6) NOT NULL,
|
|
duration_days INTEGER NOT NULL,
|
|
|
|
-- Foreign key
|
|
FOREIGN KEY (backtest_id) REFERENCES backtests(backtest_id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Indexes for backtest_drawdown_periods
|
|
CREATE INDEX IF NOT EXISTS idx_drawdown_backtest_id ON backtest_drawdown_periods(backtest_id);
|
|
CREATE INDEX IF NOT EXISTS idx_drawdown_start_time ON backtest_drawdown_periods(start_time);
|
|
CREATE INDEX IF NOT EXISTS idx_drawdown_percent ON backtest_drawdown_periods(drawdown_percent);
|
|
|
|
-- Market data table - stores historical market data for backtesting
|
|
CREATE TABLE IF NOT EXISTS market_data (
|
|
id SERIAL PRIMARY KEY,
|
|
symbol VARCHAR(50) NOT NULL,
|
|
timestamp TIMESTAMPTZ NOT NULL,
|
|
timeframe VARCHAR(10) NOT NULL, -- '1m', '5m', '1h', '1d', etc.
|
|
open_price DECIMAL(20, 8) NOT NULL,
|
|
high_price DECIMAL(20, 8) NOT NULL,
|
|
low_price DECIMAL(20, 8) NOT NULL,
|
|
close_price DECIMAL(20, 8) NOT NULL,
|
|
volume DECIMAL(20, 8) NOT NULL,
|
|
vwap DECIMAL(20, 8)
|
|
);
|
|
|
|
-- Indexes for market_data
|
|
CREATE INDEX IF NOT EXISTS idx_market_data_symbol ON market_data(symbol);
|
|
CREATE INDEX IF NOT EXISTS idx_market_data_timestamp ON market_data(timestamp);
|
|
CREATE INDEX IF NOT EXISTS idx_market_data_timeframe ON market_data(timeframe);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_market_data_symbol_timestamp_timeframe ON market_data(symbol, timestamp, timeframe);
|
|
|
|
-- Strategy configurations table - stores strategy parameter sets
|
|
CREATE TABLE IF NOT EXISTS strategy_configurations (
|
|
id SERIAL PRIMARY KEY,
|
|
strategy_name VARCHAR(255) NOT NULL,
|
|
configuration_name VARCHAR(255) NOT NULL,
|
|
parameters TEXT NOT NULL, -- JSON object
|
|
description TEXT,
|
|
is_default BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- Indexes for strategy_configurations
|
|
CREATE INDEX IF NOT EXISTS idx_strategy_configs_name ON strategy_configurations(strategy_name);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_strategy_config_unique ON strategy_configurations(strategy_name, configuration_name);
|
|
|
|
-- Backtest performance comparison table - for benchmark comparisons
|
|
CREATE TABLE IF NOT EXISTS backtest_comparisons (
|
|
id SERIAL PRIMARY KEY,
|
|
backtest_id VARCHAR(255) NOT NULL,
|
|
benchmark_symbol VARCHAR(50) NOT NULL,
|
|
correlation DECIMAL(10, 6),
|
|
beta DECIMAL(10, 6),
|
|
alpha DECIMAL(10, 6),
|
|
tracking_error DECIMAL(10, 6),
|
|
information_ratio DECIMAL(10, 6),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
-- Foreign key
|
|
FOREIGN KEY (backtest_id) REFERENCES backtests(backtest_id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Indexes for backtest_comparisons
|
|
CREATE INDEX IF NOT EXISTS idx_comparisons_backtest_id ON backtest_comparisons(backtest_id);
|
|
CREATE INDEX IF NOT EXISTS idx_comparisons_benchmark ON backtest_comparisons(benchmark_symbol);
|