#!/usr/bin/env python3
"""
VRAIE MARTINGALE - Doubler dans le MÊME SENS jusqu'à gagner

Principe:
- Prend un signal initial (LONG ou SHORT)
- Si perd → DOUBLE la position dans le MÊME sens
- Continue jusqu'à gagner OU max level
- Reset après un gain

Paramètres clés:
- Position initiale TRÈS PETITE pour avoir marge de doubler
- Leverage adapté selon le niveau
- Pas de limite de casino ici, on a 1000x leverage!
"""

from martingale_strategy import MartingaleStrategy, MartingaleSignal
import pandas as pd
from typing import Optional

class TrueMartingaleStrategy(MartingaleStrategy):
    """Vraie martingale: garde le même côté et double jusqu'à gagner"""

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.current_side = None  # Le côté actuel de la martingale
        self.locked_in_martingale = False  # True si on est en série de pertes

    def generate_signal(self, df: pd.DataFrame) -> Optional[MartingaleSignal]:
        """
        Génère signal martingale en GARDANT le même côté après une perte
        """
        df = self.calculate_indicators(df)

        # Si on est en série de pertes (martingale active)
        if self.locked_in_martingale and self.current_side:
            # On GARDE le même côté, on ne regarde PAS les indicateurs
            side = self.current_side
            score = 1.0  # Confiance maximale - on est en martingale

        else:
            # Premier trade OU on a gagné le dernier
            # Générer un NOUVEAU signal
            base_signal = self.generate_base_signal(df)

            if not base_signal:
                return None

            side, score = base_signal

            # Vérifier score minimum
            if score < self.min_signal_score:
                return None

            # Mémoriser ce côté pour la série
            self.current_side = side

        # Prix d'entrée
        entry_price = df.iloc[-1]['close']

        # Leverage adapté au niveau
        leverage = self.get_leverage_for_level()

        # SL/TP adaptés au leverage
        max_sl_pct = 1.0 / leverage * 0.5  # 50% de marge de liquidation
        sl_pct = min(self.stop_loss_pct, max_sl_pct)

        if side == 'LONG':
            stop_loss = entry_price * (1 - sl_pct)
            take_profit = entry_price * (1 + sl_pct * self.take_profit_ratio)
        else:  # SHORT
            stop_loss = entry_price * (1 + sl_pct)
            take_profit = entry_price * (1 - sl_pct * self.take_profit_ratio)

        # Position size AVEC MARTINGALE (doubler)
        multiplier = self.get_martingale_multiplier()
        position_size = self.base_position_size * multiplier

        # Sécurité: ne pas dépasser 80% du capital
        # (on veut garder de la marge pour le prochain doublement)
        max_position_size = 800.0  # Sur 1000$ capital
        position_size = min(position_size, max_position_size)

        signal = MartingaleSignal(
            timestamp=df.iloc[-1]['timestamp'],
            side=side,
            entry_price=entry_price,
            stop_loss=stop_loss,
            take_profit=take_profit,
            leverage=leverage,
            position_size_usd=position_size,
            martingale_level=self.current_level,
            signal_score=score,
            strategy='true_martingale'
        )

        return signal

    def update_after_trade(self, won: bool):
        """
        Met à jour l'état après un trade

        Args:
            won: True si trade gagné
        """
        if won:
            # VICTOIRE! Reset complet
            self.consecutive_losses = 0
            self.current_level = 0
            self.current_side = None
            self.locked_in_martingale = False

        else:
            # PERTE: activer la martingale
            self.consecutive_losses += 1
            self.current_level = min(self.current_level + 1, self.max_martingale_level)
            self.locked_in_martingale = True
            # On GARDE le même côté (self.current_side)


if __name__ == "__main__":
    """
    Test rapide de la vraie martingale
    """
    from martingale_backtester import MartingaleBacktester

    print("=" * 80)
    print("🎲 TEST VRAIE MARTINGALE")
    print("=" * 80)

    backtester = MartingaleBacktester(
        initial_capital=1000.0,
        trading_fee_pct=0.0005,
        timeout_minutes=60
    )

    print("\n📥 Téléchargement données...")
    df = backtester.fetch_binance_data('BTCUSDT', '1m', 1000)

    if df is None:
        exit(1)

    print(f"✅ {len(df)} bougies\n")

    # Paramètres OPTIMISÉS pour vraie martingale
    # Position TRÈS PETITE pour avoir marge de doubler
    configs = [
        {
            'name': '1. Conservative (base $1)',
            'base_position_size': 1.0,  # $1 seulement!
            'max_martingale_level': 8,  # Peut doubler 8 fois = 256x
            'base_leverage': 10,
            'max_leverage': 500
        },
        {
            'name': '2. Moderate (base $2)',
            'base_position_size': 2.0,
            'max_martingale_level': 7,  # 128x max
            'base_leverage': 10,
            'max_leverage': 500
        },
        {
            'name': '3. Aggressive (base $5)',
            'base_position_size': 5.0,
            'max_martingale_level': 6,  # 64x max
            'base_leverage': 20,
            'max_leverage': 1000
        },
        {
            'name': '4. Very Aggressive (base $10)',
            'base_position_size': 10.0,
            'max_martingale_level': 5,  # 32x max
            'base_leverage': 50,
            'max_leverage': 1000
        }
    ]

    results = []

    for config in configs:
        print(f"\n{'=' * 80}")
        print(f"🧪 TEST: {config['name']}")
        print(f"{'=' * 80}")
        print(f"Position de base: ${config['base_position_size']}")
        print(f"Max doublement: {2 ** config['max_martingale_level']}x")
        print(f"Leverage: {config['base_leverage']}x → {config['max_leverage']}x")

        strategy = TrueMartingaleStrategy(
            base_position_size=config['base_position_size'],
            max_martingale_level=config['max_martingale_level'],
            base_leverage=config['base_leverage'],
            max_leverage=config['max_leverage'],
            stop_loss_pct=0.003,
            take_profit_ratio=3.0,
            min_signal_score=0.6
        )

        result = backtester.run_backtest(df, 'BTCUSDT', strategy)

        if result:
            results.append({
                'name': config['name'],
                'roi': result.total_return_pct,
                'win_rate': result.win_rate,
                'pf': result.profit_factor,
                'trades': result.total_trades,
                'dd': result.max_drawdown_pct,
                'capital': result.final_capital
            })

    # Classement
    print("\n" + "=" * 80)
    print("🏆 CLASSEMENT VRAIE MARTINGALE")
    print("=" * 80)

    results.sort(key=lambda x: x['roi'], reverse=True)

    print(f"\n{'RANG':<5} {'CONFIG':<35} {'ROI %':>10} {'WR %':>8} {'PF':>6} {'Trades':>7} {'DD %':>8}")
    print("-" * 80)

    for rank, res in enumerate(results, 1):
        emoji = "🥇" if rank == 1 else "🥈" if rank == 2 else "🥉" if rank == 3 else f"{rank:2}"
        status = "✅" if res['roi'] > 0 else "⚠️" if res['roi'] > -2 else "❌"
        print(f"{emoji:<5} {res['name']:<35} {res['roi']:>9.2f}% {res['win_rate']*100:>7.1f}% "
              f"{res['pf']:>5.2f} {res['trades']:>7} {res['dd']:>7.2f}% {status}")

    best = results[0]
    print(f"\n{'=' * 80}")
    print(f"🏆 MEILLEUR: {best['name']}")
    print(f"{'=' * 80}")
    print(f"   ROI:     {best['roi']:+.2f}% {'✅ PROFITABLE!' if best['roi'] > 0 else '❌'}")
    print(f"   Capital: ${best['capital']:.2f}")
    print(f"   WR:      {best['win_rate']*100:.1f}%")
    print(f"   Trades:  {best['trades']}")
    print(f"   DD:      {best['dd']:.2f}%")
    print(f"{'=' * 80}")

    if best['roi'] > 0:
        print(f"\n🎉 MARTINGALE GAGNANTE TROUVÉE!")
        print(f"   Gain: ${best['capital'] - 1000:.2f}")
