#!/usr/bin/env python3
"""
OPTIMISATION V10 AVEC TRAILING STOP

Compare TP fixe vs différents trailing stop %
pour trouver la meilleure combinaison
"""
import pandas as pd
import numpy as np
import json
import logging
from datetime import datetime
from v10_range_strategy import V10RangeStrategy
from backtest_adaptive import AdaptiveBacktest
from backtest_v10_range import V10StrategyAdapter, Signal

logging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)


class V10TrailingOptimizer:
    """Optimise V10 avec trailing stop"""

    def __init__(self, df: pd.DataFrame, initial_capital: float = 500.0):
        self.df = df
        self.initial_capital = initial_capital
        self.results = []

        # MEILLEUR PARAM FIXE (baseline)
        self.best_fixed_params = {
            'rsi_oversold': 30,
            'rsi_overbought': 70,
            'min_confidence': 75,
            'range_atr_threshold': 0.30,
            'sl_atr_mult': 1.0,  # Meilleur de la grille précédente
            'tp_atr_mult': 4.0,  # Meilleur de la grille précédente
            'leverage': 150,
        }

    def test_config(self, params, use_trailing: bool = False, trailing_pct: float = 0.15):
        """Teste une config avec ou sans trailing stop"""
        try:
            # Créer stratégie
            strategy = V10RangeStrategy(leverage=params['leverage'])

            # Appliquer params
            strategy.params['rsi_oversold'] = params['rsi_oversold']
            strategy.params['rsi_overbought'] = params['rsi_overbought']
            strategy.params['range_atr_threshold'] = params['range_atr_threshold']
            strategy.params['min_confidence'] = params['min_confidence']
            strategy.params['sl_atr_multiplier'] = params['sl_atr_mult']
            strategy.params['tp_atr_multiplier'] = params['tp_atr_mult']

            # Adapter
            class CustomAdapter:
                def __init__(self, strat):
                    self.strategy = strat
                    self.leverage = strat.leverage
                    self.params = {
                        'ranging': {
                            'sl_atr_multiplier': strat.params['sl_atr_multiplier'],
                            'tp_atr_multiplier': strat.params['tp_atr_multiplier'],
                            'min_confidence': strat.params['min_confidence'],
                        }
                    }

                def analyze(self, symbol, df):
                    signal_dict = self.strategy.analyze(symbol, df)
                    if not signal_dict:
                        return None
                    return Signal(
                        symbol=signal_dict['symbol'],
                        side=signal_dict['side'],
                        entry_price=signal_dict['entry_price'],
                        stop_loss=signal_dict['stop_loss'],
                        take_profit=signal_dict['take_profit'],
                        leverage=signal_dict['leverage'],
                        risk_pct=signal_dict['risk_pct'],
                        score=signal_dict['confidence'],
                        confluences=signal_dict['confluences'],
                        strategy_used='v10_range_reversal',
                        confidence=signal_dict['confidence']
                    )

            adapter = CustomAdapter(strategy)

            # Backtest avec ou sans trailing
            backtest = AdaptiveBacktest(
                adapter,
                initial_capital=self.initial_capital,
                use_trailing_stop=use_trailing,
                trailing_pct=trailing_pct if use_trailing else 0.15
            )

            results = backtest.run(self.df, 'BTCUSDT')

            if not results or results['total_trades'] == 0:
                return None

            return {
                'params': params.copy(),
                'trailing': use_trailing,
                'trailing_pct': trailing_pct if use_trailing else None,
                'results': {
                    'total_trades': results['total_trades'],
                    'win_rate': results['win_rate'],
                    'total_pnl_pct': results['total_pnl_pct'],
                    'final_capital': results['final_capital'],
                    'profit_factor': results['profit_factor'],
                    'avg_win': results['avg_win'],
                    'avg_loss': results['avg_loss']
                },
                'timestamp': datetime.now().isoformat()
            }

        except Exception as e:
            logger.error(f"Erreur test config: {e}")
            return None

    def optimize(self):
        """Lance l'optimisation"""

        print("="*80)
        print("🚀 OPTIMISATION V10 - TP FIXE vs TRAILING STOP")
        print("="*80)
        print(f"Capital: ${self.initial_capital}")
        print(f"Données: {len(self.df)} bougies")
        print(f"Période: {self.df['timestamp'].iloc[0]} → {self.df['timestamp'].iloc[-1]}")
        print(f"{'='*80}\n")

        # 1. BASELINE: TP/SL fixe avec meilleurs params
        print("📊 Test 1/11: TP Fixe (baseline)...")
        result = self.test_config(self.best_fixed_params, use_trailing=False)
        if result:
            result['is_baseline'] = True
            self.results.append(result)
            print(f"   ✅ PnL: {result['results']['total_pnl_pct']:+.2f}% | "
                  f"PF: {result['results']['profit_factor']:.2f} | "
                  f"Trades: {result['results']['total_trades']}")

        # 2. TRAILING STOPS: différents %
        trailing_pcts = [0.05, 0.10, 0.12, 0.15, 0.18, 0.20, 0.22, 0.25, 0.30, 0.35]

        for i, trail_pct in enumerate(trailing_pcts, 2):
            print(f"📊 Test {i}/11: Trailing Stop {int(trail_pct*100)}%...")
            result = self.test_config(self.best_fixed_params, use_trailing=True, trailing_pct=trail_pct)
            if result:
                self.results.append(result)
                print(f"   ✅ PnL: {result['results']['total_pnl_pct']:+.2f}% | "
                      f"PF: {result['results']['profit_factor']:.2f} | "
                      f"Trades: {result['results']['total_trades']}")

                # Sauvegarder
                with open('v10_trailing_results.json', 'w') as f:
                    json.dump(self.results, f, indent=2)

        self.print_summary()

    def print_summary(self):
        """Affiche résumé"""
        if not self.results:
            print("\n❌ Aucun résultat")
            return

        print(f"\n\n{'='*80}")
        print(f"📊 RÉSUMÉ: TP FIXE vs TRAILING STOP")
        print(f"{'='*80}\n")

        # Filtrer profitables
        profitable = [r for r in self.results if r['results']['total_pnl_pct'] > 0 and r['results']['profit_factor'] > 1.0]

        print(f"Tests effectués: {len(self.results)}")
        print(f"Profitables: {len(profitable)} ({len(profitable)/len(self.results)*100:.1f}%)\n")

        if not profitable:
            print("❌ Aucune config profitable!")
            return

        # Baseline
        baseline = [r for r in profitable if r.get('is_baseline')]
        if baseline:
            b = baseline[0]
            print(f"⭐ BASELINE (TP Fixe - SL/TP: {b['params']['sl_atr_mult']}/{b['params']['tp_atr_mult']}):")
            print(f"   PnL: {b['results']['total_pnl_pct']:+.2f}%")
            print(f"   PF: {b['results']['profit_factor']:.2f}")
            print(f"   Trades: {b['results']['total_trades']}\n")

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

        print(f"🏆 TOP 10 CONFIGS (tous systèmes):\n")
        print(f"{'#':<4} {'Type':<20} {'PnL':<12} {'PF':<8} {'Trades':<8} {'Params'}")
        print("-" * 90)

        for i, r in enumerate(profitable[:10], 1):
            res = r['results']

            if r.get('trailing'):
                type_str = f"Trailing {int(r['trailing_pct']*100)}%"
            else:
                type_str = "TP Fixe"

            baseline_mark = "⭐" if r.get('is_baseline') else "  "

            print(f"{baseline_mark}{i:<2} {type_str:<20} {res['total_pnl_pct']:>+9.2f}%  "
                  f"{res['profit_factor']:>5.2f}   "
                  f"{res['total_trades']:>5}")

        # Comparaison
        best = profitable[0]
        if baseline:
            improvement = best['results']['total_pnl_pct'] - baseline[0]['results']['total_pnl_pct']

            print("\n" + "="*80)
            print(f"🎯 MEILLEUR SYSTÈME:")
            if best.get('trailing'):
                print(f"   Type: Trailing Stop {int(best['trailing_pct']*100)}%")
            else:
                print(f"   Type: TP Fixe")
            print(f"   PnL: {best['results']['total_pnl_pct']:+.2f}%")
            print(f"   PF: {best['results']['profit_factor']:.2f}")
            print(f"   Trades: {best['results']['total_trades']}")

            if improvement > 0:
                print(f"\n💰 AMÉLIORATION vs TP Fixe: {improvement:+.2f}%")
                print(f"   Gain supplémentaire: ${self.initial_capital * improvement / 100:.2f}")
            elif improvement < 0:
                print(f"\n⚠️  TP Fixe reste meilleur de {abs(improvement):.2f}%")
            else:
                print(f"\n➡️  Performance identique")

            print("="*80)

        # Sauvegarder
        with open('v10_trailing_results.json', 'w') as f:
            json.dump(self.results, f, indent=2)

        print(f"\n💾 Résultats sauvegardés: v10_trailing_results.json")


if __name__ == '__main__':
    # Charger données
    df = pd.read_csv('historical_data/BTCUSDT_5m_9000candles.csv')
    df['timestamp'] = pd.to_datetime(df['timestamp'])

    print("📊 Chargement données...")
    print(f"   Période: {df['timestamp'].iloc[0]} → {df['timestamp'].iloc[-1]}")
    print(f"   Bougies: {len(df):,}\n")

    optimizer = V10TrailingOptimizer(df, initial_capital=500.0)
    optimizer.optimize()
