#!/usr/bin/env python3
"""Backtest FINAL - Stratégie Probabiliste Optimisée BNB 1m"""

import pandas as pd
import numpy as np
import requests
import json
from datetime import datetime
from final_probabilistic_strategy import FinalProbabilisticStrategy

def get_bnb_data():
    url = "https://api.binance.com/api/v3/klines"
    params = {'symbol': 'BNBUSDT', 'interval': '1m', 'limit': 1000}
    response = requests.get(url, params=params, timeout=10)
    data = response.json()
    
    df = pd.DataFrame(data, columns=[
        'timestamp', 'open', 'high', 'low', 'close', 'volume',
        'close_time', 'quote_volume', 'trades', 'taker_buy_base',
        'taker_buy_quote', 'ignore'
    ])
    
    df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
    for col in ['open', 'high', 'low', 'close', 'volume']:
        df[col] = df[col].astype(float)
    
    return df

def backtest(df, strategy, name):
    capital = 100.0
    trades = []
    open_position = None
    
    for i in range(strategy.lookback_window + 50, len(df)):
        window = df.iloc[:i+1]
        current_price = window['close'].iloc[-1]
        
        if open_position:
            entry = open_position['entry_price']
            leverage = open_position['leverage']
            
            if open_position['side'] == 'LONG':
                pnl_pct = ((current_price - entry) / entry) * 100 * leverage
            else:
                pnl_pct = ((entry - current_price) / entry) * 100 * leverage
            
            # Limite -100%
            pnl_pct = max(pnl_pct, -100)
            
            # Check liquidation
            if pnl_pct <= -100:
                pnl_usd = capital * -1.0
                capital += pnl_usd
                trades.append({
                    'pnl_pct': -100,
                    'pnl_usd': pnl_usd,
                    'exit_reason': 'LIQUIDATION',
                    'probability': open_position['probability'],
                    'trend_context': open_position['trend_context']
                })
                open_position = None
                continue
            
            # Check SL/TP
            hit_sl = (
                (open_position['side'] == 'LONG' and current_price <= open_position['stop_loss']) or
                (open_position['side'] == 'SHORT' and current_price >= open_position['stop_loss'])
            )
            
            hit_tp = (
                (open_position['side'] == 'LONG' and current_price >= open_position['take_profit']) or
                (open_position['side'] == 'SHORT' and current_price <= open_position['take_profit'])
            )
            
            if hit_sl or hit_tp:
                pnl_usd = capital * (pnl_pct / 100)
                capital += pnl_usd
                trades.append({
                    'pnl_pct': pnl_pct,
                    'pnl_usd': pnl_usd,
                    'exit_reason': 'TP' if hit_tp else 'SL',
                    'probability': open_position['probability'],
                    'trend_context': open_position['trend_context']
                })
                open_position = None
        
        if not open_position and capital > 0:
            signal = strategy.analyze('BNB', window)
            if signal:
                open_position = {
                    'side': signal.side,
                    'entry_price': signal.entry_price,
                    'stop_loss': signal.stop_loss,
                    'take_profit': signal.take_profit,
                    'leverage': signal.leverage,
                    'probability': signal.probability,
                    'trend_context': signal.trend_context
                }
    
    if not trades:
        return None
    
    winners = [t for t in trades if t['pnl_pct'] > 0]
    losers = [t for t in trades if t['pnl_pct'] <= 0]
    
    total_win = sum(t['pnl_usd'] for t in winners)
    total_loss = abs(sum(t['pnl_usd'] for t in losers))
    
    pf = (total_win / total_loss) if total_loss > 0 else float('inf')
    pnl_pct = ((capital - 100) / 100) * 100
    
    # Calibration error
    avg_prob = np.mean([t['probability'] for t in trades])
    actual_wr = (len(winners) / len(trades)) * 100
    calib_err = abs(avg_prob * 100 - actual_wr)
    
    return {
        'name': name,
        'trades': len(trades),
        'winners': len(winners),
        'losers': len(losers),
        'win_rate': actual_wr,
        'profit_factor': pf,
        'pnl_pct': pnl_pct,
        'final_capital': capital,
        'calib_error': calib_err
    }

def main():
    print("="*80)
    print("🎯 BACKTEST FINAL - STRATÉGIE PROBABILISTE OPTIMISÉE")
    print("="*80)
    
    df = get_bnb_data()
    print(f"\n📊 Données: {len(df)} bougies BNB 1m")
    print(f"   Période: {df['timestamp'].iloc[0]} → {df['timestamp'].iloc[-1]}")
    
    results = []
    
    # Test 1: Standard
    print("\n📊 TEST 1: Standard (Lev 100x)")
    s1 = FinalProbabilisticStrategy(leverage=100, z_threshold=1.8, min_probability=0.50)
    r1 = backtest(df, s1, "Standard 100x")
    if r1:
        results.append(r1)
        print(f"   Trades:{r1['trades']} | WR:{r1['win_rate']:.1f}% | PF:{r1['profit_factor']:.2f} | PnL:{r1['pnl_pct']:.1f}%")
    
    # Test 2: Conservateur
    print("\n📊 TEST 2: Conservateur (Lev 50x)")
    s2 = FinalProbabilisticStrategy(leverage=50, sl_pct=0.06, tp_pct=0.12, z_threshold=2.0, min_probability=0.52)
    r2 = backtest(df, s2, "Conservateur 50x")
    if r2:
        results.append(r2)
        print(f"   Trades:{r2['trades']} | WR:{r2['win_rate']:.1f}% | PF:{r2['profit_factor']:.2f} | PnL:{r2['pnl_pct']:.1f}%")
    
    # Test 3: Agressif
    print("\n📊 TEST 3: Agressif (Lev 150x)")
    s3 = FinalProbabilisticStrategy(leverage=150, z_threshold=1.7, min_probability=0.48, min_ev=0.12)
    r3 = backtest(df, s3, "Agressif 150x")
    if r3:
        results.append(r3)
        print(f"   Trades:{r3['trades']} | WR:{r3['win_rate']:.1f}% | PF:{r3['profit_factor']:.2f} | PnL:{r3['pnl_pct']:.1f}%")
    
    # Test 4: Sans filtre tendance
    print("\n📊 TEST 4: Sans Filtre Tendance (Lev 100x)")
    s4 = FinalProbabilisticStrategy(leverage=100, z_threshold=1.8, trend_filter_enabled=False)
    r4 = backtest(df, s4, "Sans Filtre 100x")
    if r4:
        results.append(r4)
        print(f"   Trades:{r4['trades']} | WR:{r4['win_rate']:.1f}% | PF:{r4['profit_factor']:.2f} | PnL:{r4['pnl_pct']:.1f}%")
    
    # Comparaison
    if results:
        print("\n" + "="*100)
        print("🏆 COMPARAISON")
        print("="*100)
        print(f"\n{'Stratégie':<20} | {'Trades':<7} | {'WR%':<7} | {'PF':<7} | {'PnL%':<10} | {'CalibErr%':<10}")
        print("-"*100)
        
        best_pnl = -float('inf')
        best_name = ""
        
        for r in results:
            print(f"{r['name']:<20} | {r['trades']:<7} | {r['win_rate']:<7.1f} | {r['profit_factor']:<7.2f} | {r['pnl_pct']:<10.1f} | {r['calib_error']:<10.1f}")
            if r['pnl_pct'] > best_pnl:
                best_pnl = r['pnl_pct']
                best_name = r['name']
        
        print("-"*100)
        print(f"\n🏆 MEILLEUR: {best_name} ({best_pnl:.1f}%)")
        
        # Sauvegarder
        output = {
            'asset': 'BNBUSDT',
            'interval': '1m',
            'date': datetime.now().isoformat(),
            'results': results,
            'best': best_name
        }
        
        with open('final_probabilistic_results.json', 'w') as f:
            json.dump(output, f, indent=2)
        
        print("\n💾 Résultats: final_probabilistic_results.json")
    
    print("\n✅ BACKTEST FINAL TERMINÉ\n")

if __name__ == '__main__':
    main()
