#!/usr/bin/env python3
"""
OPTIMISATION V10 RANGE STRATEGY
Trouve le bon compromis entre sélectivité et fréquence
"""

import pandas as pd
import numpy as np
import random
import json
import logging
from datetime import datetime
from v10_range_strategy import V10RangeStrategy
from backtest_adaptive import AdaptiveBacktest

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


class V10RangeOptimizer:
    """Optimiseur pour stratégie V10 Range"""

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

    def generate_random_params(self):
        """Génère des paramètres aléatoires pour V10"""
        return {
            'leverage': random.choice([100, 110, 120, 125, 130, 140, 150]),
            'rsi_oversold': random.randint(25, 40),
            'rsi_overbought': random.randint(60, 75),
            'range_atr_threshold': random.uniform(0.25, 0.45),
            'min_confidence': random.randint(60, 80),
            'sl_atr_mult': random.uniform(0.8, 2.0),
            'tp_atr_mult': random.uniform(2.0, 5.0),
            'bb_std': random.uniform(1.5, 2.5),
        }

    def test_params(self, params):
        """Teste une combinaison de paramètres"""
        try:
            # Créer stratégie avec params custom
            strategy = V10RangeStrategy(leverage=params['leverage'])

            # Appliquer les 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']
            strategy.params['bb_std'] = params['bb_std']

            # Créer adapteur
            from backtest_v10_range import V10StrategyAdapter, Signal

            class CustomV10Adapter:
                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'],
                        confidence=signal_dict['confidence'],
                        strategy_used=signal_dict['strategy_used'],
                        confluences=signal_dict['confluences'],
                        leverage=self.leverage,
                        timeframe='5m',
                        timestamp=pd.Timestamp.now()
                    )

            adapter = CustomV10Adapter(strategy)

            # Backtest
            backtest = AdaptiveBacktest(adapter, initial_capital=self.initial_capital)
            results = backtest.run(self.df, "BTCUSD_DEGEN")

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

            return {
                'params': params,
                '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"Error testing params: {e}")
            return None

    def optimize(self, n_iterations: int = 50):
        """Lance l'optimisation"""
        print(f"\n{'='*80}")
        print(f"🔬 OPTIMISATION V10 RANGE")
        print(f"{'='*80}")
        print(f"Itérations: {n_iterations}")
        print(f"Capital: ${self.initial_capital}")
        print(f"Données: {len(self.df)} bougies")
        print(f"{'='*80}\n")

        for i in range(n_iterations):
            # Générer params
            params = self.generate_random_params()

            # S'assurer TP > SL * 2
            if params['tp_atr_mult'] < params['sl_atr_mult'] * 2.0:
                params['tp_atr_mult'] = params['sl_atr_mult'] * random.uniform(2.5, 3.5)

            # Tester
            result = self.test_params(params)

            if result:
                self.results.append(result)

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

                pnl = result['results']['total_pnl_pct']
                pf = result['results']['profit_factor']
                trades = result['results']['total_trades']
                lev = result['params']['leverage']

                if pnl > 0 and pf > 1.0:
                    print(f"✅ Test {i+1}/{n_iterations} | "
                          f"PnL: {pnl:+.2f}% | PF: {pf:.2f} | "
                          f"Trades: {trades} | Lev: {lev}x")
                else:
                    print(f"❌ Test {i+1}/{n_iterations} | "
                          f"PnL: {pnl:+.2f}% | PF: {pf:.2f} | "
                          f"Trades: {trades}")
            else:
                print(f"⚠️  Test {i+1}/{n_iterations} | Aucun trade")

        # Résumé
        self.print_summary()

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

        print(f"\n\n{'='*80}")
        print(f"📊 RÉSUMÉ OPTIMISATION V10")
        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 totaux: {len(self.results)}")
        print(f"Profitables: {len(profitable)} ({len(profitable)/len(self.results)*100:.1f}%)\n")

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

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

        print(f"🏆 TOP 10 CONFIGS:\n")
        print(f"{'#':<4} {'PnL':<10} {'PF':<8} {'WR':<8} {'Trades':<8} {'Lev':<6} {'Params'}")
        print("-" * 80)

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

            param_str = (f"RSI:{p['rsi_oversold']}/{p['rsi_overbought']} "
                        f"ATR:{p['range_atr_threshold']:.2f} "
                        f"Conf:{p['min_confidence']} "
                        f"SL/TP:{p['sl_atr_mult']:.1f}/{p['tp_atr_mult']:.1f}")

            print(f"{i:<4} {res['total_pnl_pct']:>+7.2f}%  "
                  f"{res['profit_factor']:>5.2f}   "
                  f"{res['win_rate']:>5.1f}%   "
                  f"{res['total_trades']:>5}    "
                  f"{p['leverage']:>4}x  "
                  f"{param_str}")

        print("\n" + "="*80)

        # Meilleur compromis (bon PnL + trades suffisants)
        good_volume = [r for r in profitable if r['results']['total_trades'] >= 5]

        if good_volume:
            print(f"\n💎 MEILLEUR COMPROMIS (5+ trades):\n")
            best = good_volume[0]
            res = best['results']
            p = best['params']

            print(f"  PnL: {res['total_pnl_pct']:+.2f}% (${res['final_capital'] - self.initial_capital:+.2f})")
            print(f"  Profit Factor: {res['profit_factor']:.3f}")
            print(f"  Win Rate: {res['win_rate']:.1f}%")
            print(f"  Trades: {res['total_trades']}")
            print(f"  Leverage: {p['leverage']}x")
            print(f"\n  Paramètres:")
            print(f"    RSI oversold: {p['rsi_oversold']}")
            print(f"    RSI overbought: {p['rsi_overbought']}")
            print(f"    ATR threshold: {p['range_atr_threshold']:.3f}")
            print(f"    Min confidence: {p['min_confidence']}%")
            print(f"    SL ATR mult: {p['sl_atr_mult']:.2f}")
            print(f"    TP ATR mult: {p['tp_atr_mult']:.2f}")
            print(f"    BB std: {p['bb_std']:.2f}")

        print("\n" + "="*80 + "\n")


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

    # Optimiser
    optimizer = V10RangeOptimizer(df, initial_capital=500.0)
    optimizer.optimize(n_iterations=100)
