#!/usr/bin/env python3
"""
MASSIVE BACKTEST - Teste TOUTES les stratégies en parallèle
"""

import pandas as pd
import numpy as np
import requests
import json
from datetime import datetime
from ultra_probabilistic_strategies import (
    ProbabilisticTA,
    MomentumProbabilistic,
    EmpiricalProbabilities,
    UltraScalping,
    BreakoutProbabilistic
)


def get_bnb_data(interval='1m', limit=1000):
    """Récupère données BNB"""
    url = "https://api.binance.com/api/v3/klines"
    params = {'symbol': 'BNBUSDT', 'interval': interval, 'limit': limit}
    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_strategy(df, strategy, name, initial_capital=100.0):
    """Backtest une stratégie"""
    capital = initial_capital
    trades = []
    open_position = None

    start_idx = 250  # Besoin de warm-up pour indicateurs

    for i in range(start_idx, len(df)):
        window = df.iloc[:i+1].copy()
        current_price = window['close'].iloc[-1]

        # Gérer position ouverte
        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% (liquidation)
            pnl_pct = max(pnl_pct, -100)

            if pnl_pct <= -100:
                pnl_usd = capital * -1.0
                capital += pnl_usd
                trades.append({
                    'pnl_pct': -100,
                    'pnl_usd': pnl_usd,
                    'exit': 'LIQUIDATION',
                    'probability': open_position['probability']
                })
                open_position = None
                if capital <= 0:
                    break
                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': 'TP' if hit_tp else 'SL',
                    'probability': open_position['probability']
                })
                open_position = None

        # Chercher nouveau signal
        if not open_position and capital > 0:
            try:
                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
                    }
            except Exception as e:
                # Skip errors silencieusement
                pass

    # Résultats
    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]
    liquidations = len([t for t in trades if t['exit'] == 'LIQUIDATION'])

    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') if total_win > 0 else 0)
    pnl_pct = ((capital - initial_capital) / initial_capital) * 100

    # Avg probability vs actual win rate
    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)

    # Max drawdown
    capital_curve = [initial_capital]
    running = initial_capital
    for t in trades:
        running += t['pnl_usd']
        capital_curve.append(running)

    peak = capital_curve[0]
    max_dd = 0
    for cap in capital_curve:
        if cap > peak:
            peak = cap
        dd = ((peak - cap) / peak) * 100 if peak > 0 else 0
        if dd > max_dd:
            max_dd = dd

    return {
        'name': name,
        'trades': len(trades),
        'winners': len(winners),
        'losers': len(losers),
        'liquidations': liquidations,
        'win_rate': actual_wr,
        'profit_factor': pf,
        'pnl_pct': pnl_pct,
        'final_capital': capital,
        'avg_prob': avg_prob * 100,
        'calib_error': calib_err,
        'max_dd': max_dd,
        'avg_win': total_win / len(winners) if winners else 0,
        'avg_loss': total_loss / len(losers) if losers else 0
    }


def main():
    print("=" * 100)
    print("🔥 MASSIVE BACKTEST - TOUTES LES STRATÉGIES PROBABILISTES")
    print("=" * 100)

    # Charger données
    print("\n📊 Chargement données BNB 1m...")
    df = get_bnb_data(interval='1m', limit=1000)
    print(f"   ✅ {len(df)} bougies | {df['timestamp'].iloc[0]} → {df['timestamp'].iloc[-1]}")

    # Définir toutes les stratégies à tester
    strategies = [
        (ProbabilisticTA(leverage=50), "Prob+TA (Lev 50)"),
        (ProbabilisticTA(leverage=30), "Prob+TA (Lev 30)"),
        (MomentumProbabilistic(leverage=75), "Momentum (Lev 75)"),
        (MomentumProbabilistic(leverage=50), "Momentum (Lev 50)"),
        (EmpiricalProbabilities(leverage=60), "Empirical (Lev 60)"),
        (EmpiricalProbabilities(leverage=40), "Empirical (Lev 40)"),
        (UltraScalping(leverage=20), "Ultra Scalp (Lev 20)"),
        (UltraScalping(leverage=15), "Ultra Scalp (Lev 15)"),
        (BreakoutProbabilistic(leverage=80), "Breakout (Lev 80)"),
        (BreakoutProbabilistic(leverage=60), "Breakout (Lev 60)"),
    ]

    print(f"\n🎯 Testing {len(strategies)} stratégies...\n")

    results = []
    for strategy, name in strategies:
        print(f"   Testing: {name}...", end=" ")
        result = backtest_strategy(df, strategy, name)
        if result:
            results.append(result)
            print(f"✅ {result['trades']} trades | {result['pnl_pct']:+.1f}%")
        else:
            print("⚠️  No trades")

    # Résultats
    if results:
        print("\n" + "=" * 130)
        print("🏆 RÉSULTATS COMPARATIFS")
        print("=" * 130)

        # Trier par PnL
        results.sort(key=lambda x: x['pnl_pct'], reverse=True)

        print(f"\n{'Stratégie':<25} | {'Trades':<7} | {'W/L':<8} | {'WR%':<6} | {'PF':<6} | {'PnL%':<10} | {'DD%':<7} | {'CalibErr':<9}")
        print("-" * 130)

        for r in results:
            wl_ratio = f"{r['winners']}/{r['losers']}"
            print(f"{r['name']:<25} | {r['trades']:<7} | {wl_ratio:<8} | {r['win_rate']:<6.1f} | "
                  f"{r['profit_factor']:<6.2f} | {r['pnl_pct']:<10.1f} | {r['max_dd']:<7.1f} | {r['calib_error']:<9.1f}")

        print("-" * 130)

        # Top 3
        print("\n🥇 TOP 3:")
        for i, r in enumerate(results[:3], 1):
            print(f"   {i}. {r['name']}: {r['pnl_pct']:+.1f}% (WR:{r['win_rate']:.1f}%, PF:{r['profit_factor']:.2f})")

        # Analyse
        profitable = [r for r in results if r['pnl_pct'] > 0]
        print(f"\n📊 STATISTIQUES:")
        print(f"   Stratégies profitables: {len(profitable)}/{len(results)} ({len(profitable)/len(results)*100:.0f}%)")

        if profitable:
            best = results[0]
            print(f"\n🎯 MEILLEURE STRATÉGIE: {best['name']}")
            print(f"   PnL: {best['pnl_pct']:+.1f}%")
            print(f"   Trades: {best['trades']} (W:{best['winners']}/L:{best['losers']}/LIQ:{best['liquidations']})")
            print(f"   Win rate: {best['win_rate']:.1f}%")
            print(f"   Profit factor: {best['profit_factor']:.2f}")
            print(f"   Max DD: {best['max_dd']:.1f}%")
            print(f"   Calibration error: {best['calib_error']:.1f}%")
            print(f"   Avg win: ${best['avg_win']:.2f} | Avg loss: ${best['avg_loss']:.2f}")

        # Sauvegarder
        output = {
            'date': datetime.now().isoformat(),
            'asset': 'BNBUSDT',
            'interval': '1m',
            'period': f"{df['timestamp'].iloc[0]} to {df['timestamp'].iloc[-1]}",
            'num_strategies': len(results),
            'profitable_count': len(profitable),
            'results': results
        }

        with open('massive_backtest_results.json', 'w') as f:
            json.dump(output, f, indent=2)

        print("\n💾 Résultats: massive_backtest_results.json")
    else:
        print("\n⚠️  AUCUNE STRATÉGIE N'A GÉNÉRÉ DE TRADES!")

    print("\n" + "=" * 100)
    print("✅ MASSIVE BACKTEST TERMINÉ")
    print("=" * 100 + "\n")


if __name__ == '__main__':
    main()
