#!/usr/bin/env python3
"""
Optimisation Random Search pour stratégie RANGING
Teste différentes combinaisons de SL/TP/trailing
"""

import pandas as pd
import numpy as np
import random
from adaptive_strategy import AdaptiveStrategy
from backtest_adaptive import AdaptiveBacktest
import logging

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


class RangingOptimizer:
    """Optimise les paramètres de la stratégie RANGING"""

    def __init__(self, df: pd.DataFrame):
        self.df = df
        self.results = []
        self.best_result = None

    def optimize(self, n_iterations: int = 200):
        """Lance l'optimisation par random search"""

        logger.warning(f"\n{'='*80}")
        logger.warning(f"🔬 OPTIMISATION RANDOM SEARCH - RANGING STRATEGY")
        logger.warning(f"{'='*80}")
        logger.warning(f"Iterations: {n_iterations}")
        logger.warning(f"Data: {len(self.df):,} bougies")
        logger.warning(f"{'='*80}\n")

        profitable_count = 0

        for i in range(1, n_iterations + 1):
            # Générer paramètres aléatoires
            params = {
                'sl_atr_mult': random.uniform(0.3, 1.5),
                'tp_atr_mult': random.uniform(1.0, 6.0),
                'min_confidence': random.randint(65, 90),
                'leverage': random.choice([150, 175, 200, 225]),
                'max_trades': random.choice([50, 100, 150, 200]),  # Limiter nombre de trades
            }

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

            # Créer stratégie avec ces paramètres
            strategy = AdaptiveStrategy(leverage=params['leverage'])

            # Modifier paramètres RANGING
            strategy.params['ranging']['sl_atr_multiplier'] = params['sl_atr_mult']
            strategy.params['ranging']['tp_atr_multiplier'] = params['tp_atr_mult']
            strategy.params['ranging']['min_confidence'] = params['min_confidence']

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

            if not results or results['total_trades'] == 0:
                continue

            # Limiter nombre de trades pour éviter over-trading
            if results['total_trades'] > params['max_trades']:
                continue

            # Enregistrer résultats
            result = {
                'params': params,
                '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'],
            }

            self.results.append(result)

            # Tracker les résultats profitables
            if result['total_pnl_pct'] > 0 and result['profit_factor'] > 1.0:
                profitable_count += 1

                if self.best_result is None or result['total_pnl_pct'] > self.best_result['total_pnl_pct']:
                    self.best_result = result
                    logger.warning(
                        f"🎯 Nouveau meilleur: PnL {result['total_pnl_pct']:+.1f}% | "
                        f"PF {result['profit_factor']:.2f} | WR {result['win_rate']:.1f}% | "
                        f"Trades {result['total_trades']} | #{i}"
                    )

            # Progression
            if i % 20 == 0:
                logger.warning(f"   [{i}/{n_iterations}] - {profitable_count} configs profitables")

        logger.warning(f"\n✅ Optimisation terminée: {len(self.results)} configurations testées")
        logger.warning(f"   Configurations profitables: {profitable_count}/{len(self.results)}\n")

    def print_best_results(self, n: int = 10):
        """Affiche les N meilleurs résultats"""

        if not self.results:
            logger.warning("❌ Aucun résultat")
            return

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

        if len(profitable) == 0:
            logger.warning("❌ Aucune configuration profitable!")
            # Afficher les meilleures quand même
            best = sorted(self.results, key=lambda x: x['total_pnl_pct'], reverse=True)[:n]
        else:
            best = sorted(profitable, key=lambda x: x['total_pnl_pct'], reverse=True)[:n]

        logger.warning("="*80)
        logger.warning("🏆 TOP CONFIGURATIONS")
        logger.warning("="*80)

        for idx, r in enumerate(best, 1):
            p = r['params']

            logger.warning(f"\n#{idx}. PnL: {r['total_pnl_pct']:+.1f}% | PF: {r['profit_factor']:.2f} | "
                          f"WR: {r['win_rate']:.1f}% | Trades: {r['total_trades']}")
            logger.warning(f"   {'─'*76}")
            logger.warning(f"   Leverage: {p['leverage']}x")
            logger.warning(f"   SL: {p['sl_atr_mult']:.2f}x ATR | TP: {p['tp_atr_mult']:.2f}x ATR | "
                          f"Ratio: {p['tp_atr_mult']/p['sl_atr_mult']:.1f}:1")
            logger.warning(f"   Min Confidence: {p['min_confidence']}%")
            logger.warning(f"   Avg Win: ${r['avg_win']:.2f} | Avg Loss: ${r['avg_loss']:.2f}")
            logger.warning(f"   Capital final: ${r['final_capital']:.2f}")

        logger.warning("\n" + "="*80)


if __name__ == '__main__':
    import sys

    # Paramètres
    timeframe = sys.argv[1] if len(sys.argv) > 1 else '5m'
    n_iter = int(sys.argv[2]) if len(sys.argv) > 2 else 200

    logger.warning(f"\n⏱️  Chargement données {timeframe}...")

    # Charger données
    if timeframe == '1m':
        df = pd.read_csv('historical_data/BTCUSDT_1m_44000candles.csv')
    elif timeframe == '5m':
        df = pd.read_csv('historical_data/BTCUSDT_5m_9000candles.csv')
    else:
        df = pd.read_csv('historical_data/BTCUSDT_15m_3000candles.csv')

    df['timestamp'] = pd.to_datetime(df['timestamp'])

    logger.warning(f"✅ {len(df):,} bougies chargées")

    # Optimiser
    optimizer = RangingOptimizer(df)
    optimizer.optimize(n_iterations=n_iter)

    # Afficher résultats
    optimizer.print_best_results(n=10)

    logger.warning(f"\n✅ Optimisation complète!")
