#!/usr/bin/env python3
"""
Adaptation dynamique des paramètres selon la volatilité (ATR)

Principe: La volatilité change tout.
- Haute volatilité: Trailing large, RSI extrême, SL large
- Basse volatilité: Trailing serré, RSI resserré, SL serré
"""
import pandas as pd
import numpy as np
from typing import Dict


class DynamicParameterAdapter:
    """Adapte les paramètres de trading selon la volatilité du marché"""

    def __init__(self, base_params: Dict[str, float]):
        """
        Args:
            base_params: Paramètres de base à adapter
                - trailing_pct: % de trailing stop de base
                - rsi_oversold: RSI oversold de base
                - rsi_overbought: RSI overbought de base
                - sl_atr_mult: Multiplicateur SL de base
        """
        self.base_params = base_params.copy()

    def calculate_atr_pct(self, df: pd.DataFrame, period: int = 14) -> float:
        """
        Calcule l'ATR en % du prix

        Args:
            df: DataFrame avec colonnes high, low, close
            period: Période ATR (défaut 14)

        Returns:
            ATR en % du prix actuel
        """
        if len(df) < period + 1:
            return 1.0  # Valeur par défaut si pas assez de données

        high = df['high'].values
        low = df['low'].values
        close = df['close'].values

        # True Range
        tr1 = high - low
        tr2 = np.abs(high - np.roll(close, 1))
        tr3 = np.abs(low - np.roll(close, 1))

        tr = np.maximum(tr1, np.maximum(tr2, tr3))

        # ATR = moyenne mobile du TR
        atr = pd.Series(tr).rolling(period).mean().iloc[-1]

        # ATR en % du prix actuel
        current_price = close[-1]
        atr_pct = (atr / current_price) * 100

        return atr_pct

    def adapt_params(self, df: pd.DataFrame) -> Dict[str, float]:
        """
        Adapte les paramètres selon l'ATR actuel

        Args:
            df: DataFrame avec données de marché

        Returns:
            Dict avec paramètres adaptés
        """
        # Calculer ATR actuel
        atr_pct = self.calculate_atr_pct(df)

        # Paramètres de base
        base_trailing = self.base_params['trailing_pct']
        base_rsi_os = self.base_params['rsi_oversold']
        base_rsi_ob = self.base_params['rsi_overbought']
        base_sl_mult = self.base_params['sl_atr_mult']

        # ADAPTATION SELON ATR
        # ATR < 0.5% = Très basse volatilité
        # ATR 0.5-1.5% = Volatilité normale
        # ATR 1.5-3.0% = Haute volatilité
        # ATR > 3.0% = Extrême volatilité

        if atr_pct < 0.5:
            # TRÈS BASSE VOLATILITÉ
            # Serrer tout: prendre profits vite, RSI resserré
            trailing_mult = 0.5  # Trailing 2x plus serré
            rsi_adjustment = 5   # RSI plus proche du centre (35/65 au lieu de 30/70)
            sl_mult = 0.8        # SL plus serré

        elif atr_pct < 1.5:
            # VOLATILITÉ NORMALE
            # Paramètres standard
            trailing_mult = 1.0
            rsi_adjustment = 0
            sl_mult = 1.0

        elif atr_pct < 3.0:
            # HAUTE VOLATILITÉ
            # Laisser respirer: trailing large, RSI extrême
            trailing_mult = 1.5  # Trailing 50% plus large
            rsi_adjustment = -5  # RSI plus extrême (25/75 au lieu de 30/70)
            sl_mult = 1.3        # SL plus large

        else:
            # EXTRÊME VOLATILITÉ
            # Très large, pour ne pas se faire sortir par le bruit
            trailing_mult = 2.0  # Trailing 2x plus large
            rsi_adjustment = -10 # RSI très extrême (20/80)
            sl_mult = 1.5        # SL très large

        # Appliquer les ajustements
        adapted_params = {
            'trailing_pct': min(0.35, max(0.05, base_trailing * trailing_mult)),
            'rsi_oversold': max(20, min(35, base_rsi_os + rsi_adjustment)),
            'rsi_overbought': max(65, min(80, base_rsi_ob - rsi_adjustment)),
            'sl_atr_mult': max(0.5, min(2.5, base_sl_mult * sl_mult)),
            'atr_pct': atr_pct,  # Pour info/debug
            'volatility_regime': self._get_regime_label(atr_pct)
        }

        return adapted_params

    def _get_regime_label(self, atr_pct: float) -> str:
        """Retourne le label du régime de volatilité"""
        if atr_pct < 0.5:
            return "VERY_LOW_VOL"
        elif atr_pct < 1.5:
            return "NORMAL_VOL"
        elif atr_pct < 3.0:
            return "HIGH_VOL"
        else:
            return "EXTREME_VOL"


def test_adapter():
    """Test de l'adaptateur"""
    # Simuler des données
    dates = pd.date_range('2024-01-01', periods=100, freq='5T')

    # Scénario 1: Basse volatilité
    print("=" * 80)
    print("TEST 1: BASSE VOLATILITÉ")
    print("=" * 80)

    df_low = pd.DataFrame({
        'timestamp': dates,
        'high': 100 + np.random.randn(100) * 0.2,  # Variation ±0.2$
        'low': 100 + np.random.randn(100) * 0.2,
        'close': 100 + np.random.randn(100) * 0.2
    })

    base_params = {
        'trailing_pct': 0.15,
        'rsi_oversold': 30,
        'rsi_overbought': 70,
        'sl_atr_mult': 1.0
    }

    adapter = DynamicParameterAdapter(base_params)
    adapted = adapter.adapt_params(df_low)

    print(f"ATR: {adapted['atr_pct']:.2f}%")
    print(f"Regime: {adapted['volatility_regime']}")
    print(f"Trailing: {adapted['trailing_pct']:.2%} (base: {base_params['trailing_pct']:.2%})")
    print(f"RSI: {adapted['rsi_oversold']:.0f}/{adapted['rsi_overbought']:.0f} (base: {base_params['rsi_oversold']}/{base_params['rsi_overbought']})")
    print(f"SL mult: {adapted['sl_atr_mult']:.2f} (base: {base_params['sl_atr_mult']:.2f})")

    # Scénario 2: Haute volatilité
    print("\n" + "=" * 80)
    print("TEST 2: HAUTE VOLATILITÉ")
    print("=" * 80)

    df_high = pd.DataFrame({
        'timestamp': dates,
        'high': 100 + np.random.randn(100) * 2.0,  # Variation ±2$
        'low': 100 + np.random.randn(100) * 2.0,
        'close': 100 + np.random.randn(100) * 2.0
    })

    adapter = DynamicParameterAdapter(base_params)
    adapted = adapter.adapt_params(df_high)

    print(f"ATR: {adapted['atr_pct']:.2f}%")
    print(f"Regime: {adapted['volatility_regime']}")
    print(f"Trailing: {adapted['trailing_pct']:.2%} (base: {base_params['trailing_pct']:.2%})")
    print(f"RSI: {adapted['rsi_oversold']:.0f}/{adapted['rsi_overbought']:.0f} (base: {base_params['rsi_oversold']}/{base_params['rsi_overbought']})")
    print(f"SL mult: {adapted['sl_atr_mult']:.2f} (base: {base_params['sl_atr_mult']:.2f})")

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


if __name__ == '__main__':
    test_adapter()
