"""
RECHERCHE ULTIME de la MEILLEURE stratégie
Tests multiples: MA variations, RSI, combinaisons
"""
import pandas as pd
import numpy as np
from apollo_client import ApolloDegenClient

print('\n' + '='*100)
print('🔬 RECHERCHE ULTIME - TESTS MULTIPLES')
print('='*100)

client = ApolloDegenClient()
df = client.get_klines('BTCUSDT', '1m', limit=1500)

# Add indicators
for period in [5, 10, 20, 30, 50]:
    df[f'ma_{period}'] = df['close'].rolling(period).mean()

# RSI
def calculate_rsi(data, period=14):
    delta = data.diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
    rs = gain / loss
    return 100 - (100 / (1 + rs))

df['rsi'] = calculate_rsi(df['close'])

def backtest_strategy(df, strategy_name, signal_func, sl_pct, tp_ratio, lev):
    """Backtest générique"""
    capital = 1000
    trades = []

    for i in range(100, len(df)-10, 5):
        if pd.isna(signal_func(df.iloc[:i+1], i)):
            continue

        side = signal_func(df.iloc[:i+1], i)
        if side is None:
            continue

        close = df.iloc[i]['close']

        if side == 'LONG':
            sl = close * (1 - sl_pct)
            tp = close * (1 + sl_pct * tp_ratio)
        else:
            sl = close * (1 + sl_pct)
            tp = close * (1 - sl_pct * tp_ratio)

        # Check exit
        for j in range(i+1, min(i+15, len(df))):
            candle = df.iloc[j]
            exit_price = None

            if side == 'LONG':
                if candle['low'] <= sl:
                    exit_price = sl
                elif candle['high'] >= tp:
                    exit_price = tp
            else:
                if candle['high'] >= sl:
                    exit_price = sl
                elif candle['low'] <= tp:
                    exit_price = tp

            if exit_price:
                pnl_pct = ((exit_price - close) / close) if side == 'LONG' else ((close - exit_price) / close)
                pnl_usd = capital * 0.05 * lev * pnl_pct
                capital += pnl_usd
                trades.append(pnl_usd)
                break

    if len(trades) >= 50:
        total_return = ((capital - 1000) / 1000) * 100
        wins = len([t for t in trades if t > 0])
        wr = wins / len(trades) * 100
        return {
            'name': strategy_name,
            'return': total_return,
            'wr': wr,
            'trades': len(trades),
            'capital': capital
        }
    return None

# Define strategies
strategies = []

# 1. MA Crossovers (différentes périodes)
for ma_period in [5, 10, 20, 30, 50]:
    strategies.append({
        'name': f'MA{ma_period} Cross',
        'func': lambda df_window, idx, p=ma_period: 'LONG' if df_window.iloc[-1]['close'] > df_window.iloc[-1][f'ma_{p}'] else 'SHORT' if df_window.iloc[-1]['close'] < df_window.iloc[-1][f'ma_{p}'] else None
    })

# 2. RSI strategies
strategies.append({
    'name': 'RSI Extreme',
    'func': lambda df_window, idx: 'LONG' if df_window.iloc[-1]['rsi'] < 30 else 'SHORT' if df_window.iloc[-1]['rsi'] > 70 else None
})

strategies.append({
    'name': 'RSI Mid Cross',
    'func': lambda df_window, idx: 'LONG' if df_window.iloc[-1]['rsi'] > 50 else 'SHORT' if df_window.iloc[-1]['rsi'] < 50 else None
})

# 3. MA + RSI combinations
strategies.append({
    'name': 'MA20 + RSI>50',
    'func': lambda df_window, idx: 'LONG' if df_window.iloc[-1]['close'] > df_window.iloc[-1]['ma_20'] and df_window.iloc[-1]['rsi'] > 50 else 'SHORT' if df_window.iloc[-1]['close'] < df_window.iloc[-1]['ma_20'] and df_window.iloc[-1]['rsi'] < 50 else None
})

# Test configs
test_params = [
    # Ultra tight (notre gagnant actuel)
    {'sl': 0.0003, 'tp_ratio': 5, 'lev': 250},

    # Variations autour
    {'sl': 0.00025, 'tp_ratio': 6, 'lev': 250},
    {'sl': 0.00035, 'tp_ratio': 4, 'lev': 250},
    {'sl': 0.0003, 'tp_ratio': 7, 'lev': 250},
    {'sl': 0.0003, 'tp_ratio': 10, 'lev': 250},

    # Tight mais moins agressif
    {'sl': 0.0004, 'tp_ratio': 5, 'lev': 225},
    {'sl': 0.0005, 'tp_ratio': 4, 'lev': 200},
]

print('\n🧪 Test de {} stratégies × {} configs = {} tests'.format(
    len(strategies), len(test_params), len(strategies) * len(test_params)
))
print('\n{:<25} | {:<8} | {:<8} | {:<6} | {:<10} | {:<7} | {:<8}'.format(
    'Strategy', 'SL%', 'TP%', 'Lev', 'Return%', 'WR%', 'Trades'
))
print('-'*100)

all_results = []

for strat in strategies:
    for params in test_params:
        result = backtest_strategy(
            df,
            strat['name'],
            strat['func'],
            params['sl'],
            params['tp_ratio'],
            params['lev']
        )

        if result:
            result['sl'] = params['sl']
            result['tp'] = params['sl'] * params['tp_ratio']
            result['tp_ratio'] = params['tp_ratio']
            result['lev'] = params['lev']
            all_results.append(result)

# Sort and display top 20
all_results.sort(key=lambda x: x['return'], reverse=True)

for r in all_results[:20]:
    print('{:<25} | {:<8.3f} | {:<8.3f} | {:<6} | {:<10.2f} | {:<7.1f} | {:<8}'.format(
        r['name'], r['sl']*100, r['tp']*100, r['lev'], r['return'], r['wr'], r['trades']
    ))

if all_results:
    best = all_results[0]

    print('\n' + '='*100)
    print('🏆 CHAMPION ABSOLU')
    print('='*100)
    print('Strategy:  {}'.format(best['name']))
    print('SL:        {:.4f}%'.format(best['sl']*100))
    print('TP:        {:.3f}% (ratio {:.1f}:1)'.format(best['tp']*100, best['tp_ratio']))
    print('Leverage:  {}x'.format(best['lev']))
    print('')
    print('Return:    {:+.2f}%'.format(best['return']))
    print('Win Rate:  {:.1f}%'.format(best['wr']))
    print('Trades:    {}'.format(best['trades']))
    print('Capital:   ${:.2f}'.format(best['capital']))
    print('')

    if best['return'] > 9.07:
        print('🎉 NOUVEAU RECORD ! Bat le précédent de {:+.2f}%'.format(best['return'] - 9.07))
    else:
        print('⚠️  Pas mieux que MA20 (9.07%). Différence: {:+.2f}%'.format(best['return'] - 9.07))

    print('='*100)
