# source: https://raw.githubusercontent.com/hassanbht/TradingBot/dd2e35941f439e7a527ffbb31f04e870719a021f/user_data/strategies/Gemieni/AegisBayesAdaptive.py
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
from functools import reduce
import pandas as pd
import talib.abstract as ta
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
from pandas import DataFrame

class Github_hassanbht_TradingBot__AegisBayesAdaptive__20260601_204013(IStrategy):
    """
    Github_hassanbht_TradingBot__AegisBayesAdaptive__20260601_204013 - Bayesian Optimization Strategy
    رویکرد: استفاده از فضاهای جستجوی وسیع برای کشف بهترین پارامترها توسط الگوریتم بیزین
    تکنیک: Adaptive EMA + Dynamic RSI + Hyperoptable ATR Stop
    """
    INTERFACE_VERSION = 3
    timeframe = '1h'
    startup_candle_count: int = 100

    # ─── فضاهای جستجوی بیزین (Bayesian Search Spaces) ───
    # الگوریتم مقادیر بهینه را در این بازه‌ها پیدا خواهد کرد
    buy_rsi = IntParameter(20, 45, default=30, space="buy")
    buy_ema_short = IntParameter(5, 20, default=12, space="buy")
    buy_ema_long = IntParameter(21, 50, default=26, space="buy")
    
    sell_rsi = IntParameter(55, 85, default=70, space="sell")
    
    # ضریب داینامیک خروج
    atr_sl_mult = DecimalParameter(1.0, 4.0, default=2.0, space="sell")

    # اجازه می‌دهیم هایپراپت حد ضرر و ROI را هم بهینه‌سازی کند
    stoploss = -0.15 
    trailing_stop = False
    roi = {"0": 0.10}

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # به جای محاسبه یک EMA ثابت، طیفی از EMA ها را محاسبه می‌کنیم تا هایپراپت بتواند انتخاب کند
        for val in self.buy_ema_short.range:
            dataframe[f'ema_short_{val}'] = ta.EMA(dataframe, timeperiod=val)
            
        for val in self.buy_ema_long.range:
            dataframe[f'ema_long_{val}'] = ta.EMA(dataframe, timeperiod=val)

        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
        
        # بالاترین قیمت اخیر برای خروج پویا
        dataframe['highest_high'] = dataframe['high'].rolling(window=20).max()

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = []

        # استفاده از پارامترهای داینامیک که توسط هایپراپت تنظیم می‌شوند
        conditions.append(
            (dataframe[f'ema_short_{self.buy_ema_short.value}'] > dataframe[f'ema_long_{self.buy_ema_long.value}']) &
            (dataframe['rsi'] < self.buy_rsi.value) &
            (dataframe['volume'] > 0)
        )

        if conditions:
            dataframe.loc[reduce(lambda x, y: x & y, conditions), 'enter_long'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = []

        conditions.append(
            (dataframe['rsi'] > self.sell_rsi.value)
        )

        if conditions:
            dataframe.loc[reduce(lambda x, y: x & y, conditions), 'exit_long'] = 1

        return dataframe

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: 'datetime',
                        current_rate: float, current_profit: float, **kwargs) -> float:
        """حد ضرر متحرک بر اساس ضریب ATR که توسط هوش مصنوعی پیدا شده است"""
        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()

        # محاسبه استاپ لاس داینامیک با ضریب یافت شده
        dynamic_sl_price = last_candle['highest_high'] - (last_candle['atr'] * self.atr_sl_mult.value)
        
        if dynamic_sl_price > 0 and current_rate > dynamic_sl_price:
            return (current_rate - dynamic_sl_price) / current_rate
            
        return self.stoploss