-- Backtest Q≥95 + Instant Reversal + HTF + 5-Candle Exit Strategy
-- Compares current strategy results with proposed new filters

-- Configuration
\set STARTING_CAPITAL 97.55
\set Q_THRESHOLD 95
\set HTF_Q_THRESHOLD 85
\set TIME_EXIT_CANDLES 5
\set TIME_EXIT_MFE_THRESHOLD 30.00

-- Full backtest with all filters
WITH trades_with_htf AS (
  SELECT 
    t.*,
    EXTRACT(EPOCH FROM (t."exitTime" - t."entryTime"))/300 AS candles_in_trade,
    (
      SELECT direction 
      FROM "BlockedSignal" 
      WHERE timeframe = '15' 
        AND "createdAt" <= t."entryTime" 
      ORDER BY "createdAt" DESC 
      LIMIT 1
    ) AS htf_direction
  FROM "Trade" t
  WHERE t.timeframe = '5'
    AND t."signalSource" != 'manual'
    AND t.status = 'closed'
    AND t."exitReason" IS NOT NULL
    AND t."entryTime" >= '2024-11-19'
),

trades_with_filters AS (
  SELECT 
    t.*,
    -- HTF blocked flag
    CASE 
      WHEN t.direction = t.htf_direction 
        AND t."signalQualityScore" < :HTF_Q_THRESHOLD
      THEN 1 
      ELSE 0 
    END AS htf_blocked,
    
    -- Instant reversal flag (SL within 1 candle)
    CASE 
      WHEN t."exitReason" = 'SL' 
        AND t.candles_in_trade <= 1
      THEN 1 
      ELSE 0 
    END AS instant_reversal,
    
    -- Quality check
    CASE 
      WHEN t."signalQualityScore" >= :Q_THRESHOLD THEN 1 
      ELSE 0 
    END AS quality_pass,
    
    -- Simulated PnL with time exit rule
    CASE 
      -- Natural good exits: keep realized PnL
      WHEN t."exitReason" IN ('TP1', 'TP2', 'TRAILING_SL') 
        THEN CAST(t."realizedPnL" AS NUMERIC(10,2))
      
      -- High MFE achieved: keep realized PnL  
      WHEN CAST(t."maxFavorableExcursion" AS NUMERIC(10,2)) >= :TIME_EXIT_MFE_THRESHOLD
        THEN CAST(t."realizedPnL" AS NUMERIC(10,2))
      
      -- Exited within time window: keep realized PnL
      WHEN t.candles_in_trade <= :TIME_EXIT_CANDLES
        THEN CAST(t."realizedPnL" AS NUMERIC(10,2))
      
      -- Simulate time exit: 50% of MFE or MAE (whichever better)
      ELSE GREATEST(
        CAST(t."maxFavorableExcursion" AS NUMERIC(10,2)) * 0.5,
        CAST(t."maxAdverseExcursion" AS NUMERIC(10,2))
      )
    END AS simulated_pnl,
    
    -- Exit reason for new strategy
    CASE 
      WHEN t."exitReason" IN ('TP1', 'TP2', 'TRAILING_SL') 
        THEN t."exitReason"
      WHEN CAST(t."maxFavorableExcursion" AS NUMERIC(10,2)) >= :TIME_EXIT_MFE_THRESHOLD
        THEN t."exitReason"
      WHEN t.candles_in_trade <= :TIME_EXIT_CANDLES
        THEN t."exitReason"
      ELSE 'TIME_EXIT_5_CANDLE'
    END AS simulated_exit_reason
    
  FROM trades_with_htf t
),

-- Original strategy (all trades)
original_strategy AS (
  SELECT 
    COUNT(*) AS trades,
    SUM(CASE WHEN "realizedPnL" > 0 THEN 1 ELSE 0 END) AS wins,
    CAST(SUM("realizedPnL") AS NUMERIC(10,2)) AS total_pnl,
    CAST(AVG("realizedPnL") AS NUMERIC(10,2)) AS avg_pnl,
    MIN("entryTime") AS start_date,
    MAX("entryTime") AS end_date,
    EXTRACT(days FROM (MAX("entryTime") - MIN("entryTime"))) AS days
  FROM trades_with_filters
),

-- New strategy (Q>=95 + filters)
new_strategy AS (
  SELECT 
    COUNT(*) AS trades,
    SUM(CASE WHEN simulated_pnl > 0 THEN 1 ELSE 0 END) AS wins,
    CAST(SUM(simulated_pnl) AS NUMERIC(10,2)) AS total_pnl,
    CAST(AVG(simulated_pnl) AS NUMERIC(10,2)) AS avg_pnl
  FROM trades_with_filters
  WHERE quality_pass = 1
    AND htf_blocked = 0
    AND instant_reversal = 0
),

-- Filter breakdown
filter_stats AS (
  SELECT 
    COUNT(*) FILTER (WHERE "signalQualityScore" < :Q_THRESHOLD) AS blocked_by_q,
    COUNT(*) FILTER (WHERE htf_blocked = 1 AND "signalQualityScore" >= :Q_THRESHOLD) AS blocked_by_htf,
    COUNT(*) FILTER (WHERE instant_reversal = 1 AND htf_blocked = 0 AND "signalQualityScore" >= :Q_THRESHOLD) AS blocked_by_instant_reversal
  FROM trades_with_filters
)

-- Main report
SELECT 
  '================================================================================' AS separator_1
UNION ALL
SELECT 'BACKTEST REPORT: Q≥95 + Instant Reversal + HTF + 5-Candle Exit'
UNION ALL
SELECT '================================================================================'
UNION ALL
SELECT ''
UNION ALL
SELECT 'Period: ' || TO_CHAR(o.start_date, 'YYYY-MM-DD') || ' to ' || TO_CHAR(o.end_date, 'YYYY-MM-DD') || ' (' || o.days || ' days)'
FROM original_strategy o
UNION ALL
SELECT 'Starting Capital: $' || :STARTING_CAPITAL
UNION ALL
SELECT ''
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'ORIGINAL STRATEGY (Current Live)'
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'Trades:          ' || o.trades FROM original_strategy o
UNION ALL
SELECT 'Wins:            ' || o.wins || ' (' || ROUND(o.wins::numeric / NULLIF(o.trades,0) * 100, 1) || '%)' FROM original_strategy o
UNION ALL
SELECT 'Total PnL:       $' || o.total_pnl FROM original_strategy o
UNION ALL
SELECT 'Ending Capital:  $' || CAST(:STARTING_CAPITAL + o.total_pnl AS NUMERIC(10,2)) FROM original_strategy o
UNION ALL
SELECT 'Total Return:    ' || ROUND(o.total_pnl / :STARTING_CAPITAL * 100, 2) || '%' FROM original_strategy o
UNION ALL
SELECT 'Daily Return:    ' || ROUND(o.total_pnl / :STARTING_CAPITAL / NULLIF(o.days,0) * 100, 3) || '%' FROM original_strategy o
UNION ALL
SELECT ''
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'NEW STRATEGY (Q≥95 + Filters)'
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'Trades:          ' || n.trades FROM new_strategy n
UNION ALL
SELECT 'Wins:            ' || n.wins || ' (' || ROUND(n.wins::numeric / NULLIF(n.trades,0) * 100, 1) || '%)' FROM new_strategy n
UNION ALL
SELECT 'Total PnL:       $' || n.total_pnl FROM new_strategy n
UNION ALL
SELECT 'Ending Capital:  $' || CAST(:STARTING_CAPITAL + n.total_pnl AS NUMERIC(10,2)) FROM new_strategy n
UNION ALL
SELECT 'Total Return:    ' || ROUND(n.total_pnl / :STARTING_CAPITAL * 100, 2) || '%' FROM new_strategy n
UNION ALL
SELECT 'Daily Return:    ' || ROUND(n.total_pnl / :STARTING_CAPITAL / (SELECT days FROM original_strategy) * 100, 3) || '%' FROM new_strategy n
UNION ALL
SELECT ''
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'FILTER IMPACT'
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'Blocked by Q<' || :Q_THRESHOLD || ':           ' || f.blocked_by_q || ' trades' FROM filter_stats f
UNION ALL
SELECT 'Blocked by HTF:                      ' || f.blocked_by_htf || ' trades' FROM filter_stats f
UNION ALL
SELECT 'Blocked by Instant Reversal:         ' || f.blocked_by_instant_reversal || ' trades' FROM filter_stats f
UNION ALL
SELECT 'Total Filtered Out:                  ' || (o.trades - n.trades) || ' trades' FROM original_strategy o, new_strategy n
UNION ALL
SELECT ''
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'COMPARISON'
UNION ALL
SELECT '--------------------------------------------------------------------------------'
UNION ALL
SELECT 'PnL Change:      $' || CAST(n.total_pnl - o.total_pnl AS NUMERIC(10,2)) || ' (' || 
       ROUND((n.total_pnl - o.total_pnl) / :STARTING_CAPITAL * 100, 2) || '%)' 
FROM original_strategy o, new_strategy n
UNION ALL
SELECT 'Trade Count:     ' || (n.trades - o.trades) || ' (' || n.trades || ' vs ' || o.trades || ')' 
FROM original_strategy o, new_strategy n
UNION ALL
SELECT 'Hit Rate Change: ' || ROUND((n.wins::numeric / NULLIF(n.trades,0) - o.wins::numeric / NULLIF(o.trades,0)) * 100, 1) || '%' 
FROM original_strategy o, new_strategy n
UNION ALL
SELECT 'Avg PnL/Trade:   $' || n.avg_pnl FROM new_strategy n WHERE n.trades > 0
UNION ALL
SELECT ''
UNION ALL
SELECT '================================================================================'
UNION ALL
SELECT ''
UNION ALL
SELECT 'RECOMMENDATION:'
UNION ALL
(
  SELECT CASE
    WHEN n.total_pnl > 0 AND (n.wins::numeric / NULLIF(n.trades,0)) >= 0.40 AND n.trades >= 10 THEN
      E'✓ NEW STRATEGY LOOKS PROMISING\n' ||
      '  - Positive PnL ($' || n.total_pnl || E')\n' ||
      '  - Decent hit rate (' || ROUND(n.wins::numeric / NULLIF(n.trades,0) * 100, 1) || E'%)\n' ||
      '  - Sufficient trades (' || n.trades || E')\n' ||
      '  → Consider implementing with shadow mode first'
    WHEN n.total_pnl > o.total_pnl THEN
      E'⚠ NEW STRATEGY SHOWS IMPROVEMENT BUT NEEDS MORE DATA\n' ||
      '  - Better PnL ($' || CAST(n.total_pnl - o.total_pnl AS NUMERIC(10,2)) || E')\n' ||
      '  - Only ' || n.trades || E' trades (need ≥100 for confidence)\n' ||
      '  → Run shadow mode for 4-6 weeks before live deployment'
    ELSE
      E'✗ NEW STRATEGY DOES NOT IMPROVE RESULTS\n' ||
      '  - PnL worse by $' || CAST(o.total_pnl - n.total_pnl AS NUMERIC(10,2)) || E'\n' ||
      '  → Do not deploy; revisit filter thresholds'
  END
  FROM original_strategy o, new_strategy n
)
UNION ALL
SELECT '================================================================================'
;

-- Sample qualified trades
\echo ''
\echo 'SAMPLE QUALIFIED TRADES (First 10):'
\echo '--------------------------------------------------------------------------------'

SELECT 
  ROW_NUMBER() OVER (ORDER BY "entryTime") AS "#",
  TO_CHAR("entryTime", 'YYYY-MM-DD') AS date,
  UPPER(direction) AS dir,
  "signalQualityScore" AS q,
  simulated_exit_reason AS exit_reason,
  '$' || CAST(simulated_pnl AS NUMERIC(7,2)) AS pnl
FROM trades_with_filters
WHERE quality_pass = 1
  AND htf_blocked = 0
  AND instant_reversal = 0
ORDER BY "entryTime"
LIMIT 10;
