-- 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);
