-- ================================================================================================
-- Ensemble Audit Analysis Queries
-- Production-ready SQL queries for ensemble performance analysis and debugging
-- ================================================================================================

-- ================================================================================================
-- TOP PERFORMING MODELS (LAST 24 HOURS)
-- ================================================================================================

-- Query 1: Get top 5 models by Sharpe ratio (last 24 hours)
SELECT * FROM get_top_models_24h(NULL, 5);

-- Query 2: Get top performers for specific symbol
SELECT * FROM get_top_models_24h('ES.FUT', 10);

-- Query 3: Manual calculation for custom time windows
SELECT
    model_id,
    symbol,
    COUNT(*) as predictions,
    AVG(accuracy) as avg_accuracy,
    AVG(sharpe_ratio) as avg_sharpe,
    SUM(total_pnl) as cumulative_pnl,
    AVG(avg_weight) as avg_ensemble_weight
FROM model_performance_attribution
WHERE
    timestamp >= NOW() - INTERVAL '7 days'
    AND window_hours = 24
GROUP BY model_id, symbol
ORDER BY avg_sharpe DESC NULLS LAST
LIMIT 10;

-- ================================================================================================
-- MODEL CORRELATION MATRIX (LAST 7 DAYS)
-- ================================================================================================

-- Query 4: Calculate pairwise model correlations
SELECT * FROM calculate_model_correlation_7d(NULL);

-- Query 5: Model correlation for specific symbol
SELECT * FROM calculate_model_correlation_7d('NQ.FUT');

-- Query 6: Visual correlation matrix (pivot format)
WITH correlation_data AS (
    SELECT * FROM calculate_model_correlation_7d(NULL)
)
SELECT
    model_a,
    MAX(CASE WHEN model_b = 'PPO' THEN correlation END) as ppo_corr,
    MAX(CASE WHEN model_b = 'MAMBA2' THEN correlation END) as mamba2_corr,
    MAX(CASE WHEN model_b = 'TFT' THEN correlation END) as tft_corr
FROM correlation_data
WHERE model_a IN ('DQN', 'PPO', 'MAMBA2')
GROUP BY model_a
ORDER BY model_a;

-- ================================================================================================
-- ENSEMBLE VS INDIVIDUAL MODEL PERFORMANCE (LAST 30 DAYS)
-- ================================================================================================

-- Query 7: Compare ensemble Sharpe ratio to individual models
WITH ensemble_performance AS (
    SELECT
        symbol,
        COUNT(*) as total_predictions,
        AVG(ensemble_confidence) as avg_confidence,
        SUM(pnl) as total_pnl,
        STDDEV(pnl::DOUBLE PRECISION) as pnl_std,
        AVG(pnl::DOUBLE PRECISION) / NULLIF(STDDEV(pnl::DOUBLE PRECISION), 0) as sharpe_approx
    FROM ensemble_predictions
    WHERE
        timestamp >= NOW() - INTERVAL '30 days'
        AND pnl IS NOT NULL
    GROUP BY symbol
),
model_performance AS (
    SELECT
        model_id,
        symbol,
        AVG(sharpe_ratio) as avg_sharpe,
        SUM(total_pnl) as total_pnl
    FROM model_performance_attribution
    WHERE
        timestamp >= NOW() - INTERVAL '30 days'
        AND window_hours = 24
    GROUP BY model_id, symbol
)
SELECT
    ep.symbol,
    ep.total_predictions as ensemble_predictions,
    ep.sharpe_approx as ensemble_sharpe,
    ep.total_pnl as ensemble_pnl,
    mp_dqn.avg_sharpe as dqn_sharpe,
    mp_ppo.avg_sharpe as ppo_sharpe,
    mp_mamba2.avg_sharpe as mamba2_sharpe,
    mp_tft.avg_sharpe as tft_sharpe,
    GREATEST(
        COALESCE(mp_dqn.avg_sharpe, 0),
        COALESCE(mp_ppo.avg_sharpe, 0),
        COALESCE(mp_mamba2.avg_sharpe, 0),
        COALESCE(mp_tft.avg_sharpe, 0)
    ) as best_individual_sharpe,
    (ep.sharpe_approx - GREATEST(
        COALESCE(mp_dqn.avg_sharpe, 0),
        COALESCE(mp_ppo.avg_sharpe, 0),
        COALESCE(mp_mamba2.avg_sharpe, 0),
        COALESCE(mp_tft.avg_sharpe, 0)
    )) as ensemble_lift
FROM ensemble_performance ep
LEFT JOIN model_performance mp_dqn ON ep.symbol = mp_dqn.symbol AND mp_dqn.model_id = 'DQN'
LEFT JOIN model_performance mp_ppo ON ep.symbol = mp_ppo.symbol AND mp_ppo.model_id = 'PPO'
LEFT JOIN model_performance mp_mamba2 ON ep.symbol = mp_mamba2.symbol AND mp_mamba2.model_id = 'MAMBA2'
LEFT JOIN model_performance mp_tft ON ep.symbol = mp_tft.symbol AND mp_tft.model_id = 'TFT'
ORDER BY ep.sharpe_approx DESC NULLS LAST;

-- ================================================================================================
-- HIGH DISAGREEMENT EVENTS (LAST 24 HOURS)
-- ================================================================================================

-- Query 8: Get high disagreement events (threshold = 50%)
SELECT * FROM get_high_disagreement_events_24h(NULL, 0.5, 100);

-- Query 9: Very high disagreement (threshold = 70%)
SELECT * FROM get_high_disagreement_events_24h(NULL, 0.7, 50);

-- Query 10: Disagreement with market context (price volatility)
SELECT
    ep.timestamp,
    ep.symbol,
    ep.ensemble_action,
    ep.disagreement_rate,
    ep.dqn_vote,
    ep.ppo_vote,
    ep.mamba2_vote,
    ep.tft_vote,
    ep.executed_price,
    ep.pnl,
    -- Categorize disagreement level
    CASE
        WHEN ep.disagreement_rate >= 0.75 THEN 'CRITICAL'
        WHEN ep.disagreement_rate >= 0.5 THEN 'HIGH'
        WHEN ep.disagreement_rate >= 0.25 THEN 'MODERATE'
        ELSE 'LOW'
    END as disagreement_level
FROM ensemble_predictions ep
WHERE
    ep.timestamp >= NOW() - INTERVAL '24 hours'
    AND ep.disagreement_rate >= 0.25
ORDER BY ep.disagreement_rate DESC, ep.timestamp DESC
LIMIT 100;

-- ================================================================================================
-- P&L ATTRIBUTION BY MODEL (LAST 7 DAYS)
-- ================================================================================================

-- Query 11: Total P&L contribution per model
SELECT
    model_id,
    symbol,
    COUNT(*) as trades_with_contribution,
    SUM(total_pnl) / 100.0 as total_pnl_dollars, -- Convert cents to dollars
    AVG(total_pnl) / 100.0 as avg_pnl_per_trade_dollars,
    AVG(avg_weight) as avg_ensemble_weight,
    SUM(total_pnl) / NULLIF(AVG(avg_weight), 0) / 100.0 as pnl_per_unit_weight
FROM model_performance_attribution
WHERE
    timestamp >= NOW() - INTERVAL '7 days'
    AND window_hours = 24
GROUP BY model_id, symbol
ORDER BY total_pnl_dollars DESC;

-- Query 12: Daily P&L attribution breakdown
SELECT
    DATE_TRUNC('day', timestamp) as trading_day,
    model_id,
    SUM(total_pnl) / 100.0 as daily_pnl_dollars,
    AVG(accuracy) as avg_accuracy,
    AVG(sharpe_ratio) as avg_sharpe
FROM model_performance_attribution
WHERE
    timestamp >= NOW() - INTERVAL '7 days'
    AND window_hours = 24
GROUP BY trading_day, model_id
ORDER BY trading_day DESC, daily_pnl_dollars DESC;

-- Query 13: Per-prediction P&L attribution (detailed view)
SELECT
    ep.timestamp,
    ep.symbol,
    ep.ensemble_action,
    ep.order_id,
    ep.pnl / 100.0 as ensemble_pnl_dollars,
    -- Approximate per-model P&L based on weights
    (ep.pnl * ep.dqn_weight) / 100.0 as dqn_attributed_pnl_dollars,
    (ep.pnl * ep.ppo_weight) / 100.0 as ppo_attributed_pnl_dollars,
    (ep.pnl * ep.mamba2_weight) / 100.0 as mamba2_attributed_pnl_dollars,
    (ep.pnl * ep.tft_weight) / 100.0 as tft_attributed_pnl_dollars,
    ep.commission / 100.0 as commission_dollars,
    ep.slippage_bps as slippage_basis_points
FROM ensemble_predictions ep
WHERE
    ep.timestamp >= NOW() - INTERVAL '7 days'
    AND ep.pnl IS NOT NULL
ORDER BY ep.timestamp DESC
LIMIT 1000;

-- ================================================================================================
-- A/B TEST ANALYSIS
-- ================================================================================================

-- Query 14: A/B test performance comparison (active tests)
WITH ab_metrics AS (
    SELECT
        ab_test_id,
        ab_group,
        COUNT(*) as predictions,
        AVG(ensemble_confidence) as avg_confidence,
        AVG(disagreement_rate) as avg_disagreement,
        SUM(pnl) / 100.0 as total_pnl_dollars,
        STDDEV(pnl::DOUBLE PRECISION) as pnl_std,
        AVG(pnl::DOUBLE PRECISION) / NULLIF(STDDEV(pnl::DOUBLE PRECISION), 0) as sharpe_approx,
        COUNT(CASE WHEN pnl > 0 THEN 1 END) as winning_trades,
        COUNT(CASE WHEN pnl IS NOT NULL THEN 1 END) as total_trades
    FROM ensemble_predictions
    WHERE
        ab_test_id IS NOT NULL
        AND timestamp >= NOW() - INTERVAL '7 days'
    GROUP BY ab_test_id, ab_group
)
SELECT
    test.test_name,
    control.predictions as control_predictions,
    treatment.predictions as treatment_predictions,
    control.sharpe_approx as control_sharpe,
    treatment.sharpe_approx as treatment_sharpe,
    (treatment.sharpe_approx - control.sharpe_approx) as sharpe_diff,
    (treatment.sharpe_approx - control.sharpe_approx) / NULLIF(control.sharpe_approx, 0) * 100 as sharpe_lift_percent,
    control.total_pnl_dollars as control_pnl,
    treatment.total_pnl_dollars as treatment_pnl,
    (treatment.total_pnl_dollars - control.total_pnl_dollars) as pnl_diff,
    control.winning_trades::FLOAT / NULLIF(control.total_trades, 0) as control_win_rate,
    treatment.winning_trades::FLOAT / NULLIF(treatment.total_trades, 0) as treatment_win_rate
FROM ab_test_experiments test
LEFT JOIN ab_metrics control ON test.test_id = control.ab_test_id AND control.ab_group = 'control'
LEFT JOIN ab_metrics treatment ON test.test_id = treatment.ab_test_id AND treatment.ab_group = 'treatment'
WHERE test.status = 'running'
ORDER BY test.started_at DESC;

-- Query 15: Statistical significance test (Welch's t-test approximation)
-- NOTE: For production, use actual statistical libraries; this is a simplified version
WITH ab_pnl_samples AS (
    SELECT
        ab_test_id,
        ab_group,
        pnl::DOUBLE PRECISION as pnl_sample
    FROM ensemble_predictions
    WHERE
        ab_test_id IS NOT NULL
        AND pnl IS NOT NULL
        AND timestamp >= NOW() - INTERVAL '7 days'
),
ab_stats AS (
    SELECT
        ab_test_id,
        ab_group,
        COUNT(*) as n,
        AVG(pnl_sample) as mean_pnl,
        STDDEV(pnl_sample) as std_pnl
    FROM ab_pnl_samples
    GROUP BY ab_test_id, ab_group
)
SELECT
    test.test_name,
    control.n as control_n,
    treatment.n as treatment_n,
    control.mean_pnl / 100.0 as control_mean_pnl_dollars,
    treatment.mean_pnl / 100.0 as treatment_mean_pnl_dollars,
    (treatment.mean_pnl - control.mean_pnl) / 100.0 as mean_pnl_diff_dollars,
    control.std_pnl / 100.0 as control_std_dollars,
    treatment.std_pnl / 100.0 as treatment_std_dollars,
    -- Welch's t-statistic approximation
    (treatment.mean_pnl - control.mean_pnl) /
        SQRT((control.std_pnl * control.std_pnl) / control.n +
             (treatment.std_pnl * treatment.std_pnl) / treatment.n) as t_statistic,
    CASE
        WHEN ABS((treatment.mean_pnl - control.mean_pnl) /
            SQRT((control.std_pnl * control.std_pnl) / control.n +
                 (treatment.std_pnl * treatment.std_pnl) / treatment.n)) > 1.96
        THEN 'SIGNIFICANT (p < 0.05)'
        ELSE 'NOT SIGNIFICANT'
    END as significance_95pct
FROM ab_test_experiments test
LEFT JOIN ab_stats control ON test.test_id = control.ab_test_id AND control.ab_group = 'control'
LEFT JOIN ab_stats treatment ON test.test_id = treatment.ab_test_id AND treatment.ab_group = 'treatment'
WHERE test.status = 'running'
ORDER BY test.started_at DESC;

-- ================================================================================================
-- LATENCY ANALYSIS
-- ================================================================================================

-- Query 16: P50/P95/P99 inference latency by symbol
SELECT
    symbol,
    COUNT(*) as predictions,
    PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY inference_latency_us) as p50_latency_us,
    PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY inference_latency_us) as p95_latency_us,
    PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY inference_latency_us) as p99_latency_us,
    AVG(inference_latency_us) as avg_latency_us,
    MAX(inference_latency_us) as max_latency_us
FROM ensemble_predictions
WHERE
    timestamp >= NOW() - INTERVAL '24 hours'
    AND inference_latency_us IS NOT NULL
GROUP BY symbol
ORDER BY p99_latency_us DESC;

-- Query 17: Aggregation latency distribution
SELECT
    symbol,
    COUNT(*) as predictions,
    PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY aggregation_latency_us) as p50_agg_us,
    PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY aggregation_latency_us) as p95_agg_us,
    PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY aggregation_latency_us) as p99_agg_us,
    AVG(aggregation_latency_us) as avg_agg_us
FROM ensemble_predictions
WHERE
    timestamp >= NOW() - INTERVAL '24 hours'
    AND aggregation_latency_us IS NOT NULL
GROUP BY symbol
ORDER BY p99_agg_us DESC;

-- ================================================================================================
-- CHECKPOINT TRACKING
-- ================================================================================================

-- Query 18: Active checkpoints by model
SELECT DISTINCT ON (model_id, symbol)
    CASE
        WHEN dqn_checkpoint_id IS NOT NULL THEN 'DQN'
        WHEN ppo_checkpoint_id IS NOT NULL THEN 'PPO'
        WHEN mamba2_checkpoint_id IS NOT NULL THEN 'MAMBA2'
        WHEN tft_checkpoint_id IS NOT NULL THEN 'TFT'
    END as model_id,
    symbol,
    COALESCE(dqn_checkpoint_id, ppo_checkpoint_id, mamba2_checkpoint_id, tft_checkpoint_id) as checkpoint_id,
    timestamp as last_used_at
FROM ensemble_predictions
WHERE timestamp >= NOW() - INTERVAL '24 hours'
ORDER BY model_id, symbol, timestamp DESC;

-- Query 19: Checkpoint performance comparison
WITH checkpoint_metrics AS (
    SELECT
        CASE
            WHEN dqn_checkpoint_id IS NOT NULL THEN 'DQN'
            WHEN ppo_checkpoint_id IS NOT NULL THEN 'PPO'
            WHEN mamba2_checkpoint_id IS NOT NULL THEN 'MAMBA2'
            WHEN tft_checkpoint_id IS NOT NULL THEN 'TFT'
        END as model_id,
        COALESCE(dqn_checkpoint_id, ppo_checkpoint_id, mamba2_checkpoint_id, tft_checkpoint_id) as checkpoint_id,
        COUNT(*) as predictions,
        AVG(ensemble_confidence) as avg_confidence,
        SUM(pnl) / 100.0 as total_pnl_dollars
    FROM ensemble_predictions
    WHERE
        timestamp >= NOW() - INTERVAL '7 days'
        AND pnl IS NOT NULL
    GROUP BY model_id, checkpoint_id
)
SELECT *
FROM checkpoint_metrics
ORDER BY model_id, total_pnl_dollars DESC;

-- ================================================================================================
-- CONTINUOUS AGGREGATE VIEWS (PRE-COMPUTED)
-- ================================================================================================

-- Query 20: Hourly ensemble performance (pre-aggregated)
SELECT
    bucket,
    symbol,
    ensemble_action,
    prediction_count,
    avg_confidence,
    avg_disagreement,
    avg_latency_us,
    total_pnl / 100.0 as total_pnl_dollars,
    CASE WHEN total_trades > 0 THEN winning_trades::FLOAT / total_trades ELSE 0 END as win_rate
FROM ensemble_performance_hourly
WHERE bucket >= NOW() - INTERVAL '24 hours'
ORDER BY bucket DESC, symbol;

-- Query 21: Daily model performance (pre-aggregated)
SELECT
    bucket,
    model_id,
    symbol,
    total_predictions,
    avg_accuracy,
    total_pnl / 100.0 as total_pnl_dollars,
    avg_sharpe_ratio,
    avg_weight,
    avg_disagreement_rate
FROM model_performance_daily
WHERE bucket >= NOW() - INTERVAL '7 days'
ORDER BY bucket DESC, avg_sharpe_ratio DESC NULLS LAST;

-- ================================================================================================
-- DEBUGGING QUERIES
-- ================================================================================================

-- Query 22: Failed predictions (high disagreement + negative P&L)
SELECT
    timestamp,
    symbol,
    ensemble_action,
    ensemble_confidence,
    disagreement_rate,
    pnl / 100.0 as pnl_dollars,
    dqn_vote,
    ppo_vote,
    mamba2_vote,
    tft_vote,
    feature_snapshot
FROM ensemble_predictions
WHERE
    timestamp >= NOW() - INTERVAL '7 days'
    AND pnl IS NOT NULL
    AND pnl < 0
    AND disagreement_rate > 0.5
ORDER BY pnl ASC
LIMIT 50;

-- Query 23: Model weight evolution over time
SELECT
    DATE_TRUNC('hour', timestamp) as hour,
    model_id,
    AVG(avg_weight) as avg_weight
FROM model_performance_attribution
WHERE
    timestamp >= NOW() - INTERVAL '7 days'
    AND window_hours = 1
GROUP BY hour, model_id
ORDER BY hour DESC, model_id;

-- Query 24: Data quality checks (missing model votes)
SELECT
    COUNT(*) as total_predictions,
    COUNT(dqn_signal) as dqn_present,
    COUNT(ppo_signal) as ppo_present,
    COUNT(mamba2_signal) as mamba2_present,
    COUNT(tft_signal) as tft_present,
    COUNT(*) - COUNT(dqn_signal) as dqn_missing,
    COUNT(*) - COUNT(ppo_signal) as ppo_missing,
    COUNT(*) - COUNT(mamba2_signal) as mamba2_missing,
    COUNT(*) - COUNT(tft_signal) as tft_missing
FROM ensemble_predictions
WHERE timestamp >= NOW() - INTERVAL '24 hours';

-- ================================================================================================
-- PERFORMANCE OPTIMIZATION QUERIES
-- ================================================================================================

-- Query 25: Index usage statistics
SELECT
    schemaname,
    tablename,
    indexname,
    idx_scan as index_scans,
    idx_tup_read as tuples_read,
    idx_tup_fetch as tuples_fetched
FROM pg_stat_user_indexes
WHERE schemaname = 'public'
  AND tablename IN ('ensemble_predictions', 'model_performance_attribution')
ORDER BY idx_scan DESC;

-- Query 26: Table size and compression stats
SELECT
    hypertable_name,
    table_bytes,
    index_bytes,
    toast_bytes,
    total_bytes,
    pg_size_pretty(total_bytes) as total_size,
    compression_enabled,
    compressed_total_bytes,
    pg_size_pretty(compressed_total_bytes) as compressed_size,
    CASE
        WHEN total_bytes > 0 THEN
            ROUND(100.0 * (1 - compressed_total_bytes::FLOAT / total_bytes), 2)
        ELSE 0
    END as compression_ratio_percent
FROM timescaledb_information.hypertable
WHERE hypertable_name IN ('ensemble_predictions', 'model_performance_attribution');

-- ================================================================================================
-- END OF ANALYSIS QUERIES
-- ================================================================================================
