# source: https://raw.githubusercontent.com/Hans1361/MyTrade56/1f9d73651bc407cf69ebaff3a89179a5841fd54c/user_data/strategies/NostalgiaForInfinityX5_Balanced.py
from freqtrade.strategy import IStrategy, IntParameter, RealParameter
from pandas import DataFrame
import talib.abstract as ta
import pandas as pd

class Github_Hans1361_MyTrade56__NostalgiaForInfinityX5_Balanced__20250619_202852(IStrategy):
    INTERFACE_VERSION = 3
    minimal_roi = {
        "0": 0.118,
        "30": 0.059,
        "58": 0.031,
        "178": 0
    }
    stoploss = -0.05
    timeframe = '5m'
    
    # Optimized hyperopt parameters
    buy_rsi = IntParameter(10, 70, default=69, space="buy")
    sell_rsi = IntParameter(60, 95, default=62, space="sell")
    ema_short = IntParameter(3, 30, default=12, space="buy")
    ema_long = IntParameter(15, 100, default=72, space="buy")
    volume_threshold = RealParameter(0.5, 2.5, default=1.28464, space="buy")
    adx_threshold = IntParameter(10, 40, default=21, space="buy")

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        dataframe['ema_short'] = ta.EMA(dataframe, timeperiod=self.ema_short.value)
        dataframe['ema_long'] = ta.EMA(dataframe, timeperiod=self.ema_long.value)
        dataframe['volume_sma'] = ta.SMA(dataframe['volume'], timeperiod=20)
        dataframe['volume_ratio'] = dataframe['volume'] / dataframe['volume_sma']
        dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
        bollinger = ta.BBANDS(dataframe, timeperiod=20, nbdevup=2.0, nbdevdn=2.0)
        dataframe['bb_upper'] = bollinger['upperband']
        dataframe['bb_lower'] = bollinger['lowerband']
        dataframe['bb_middle'] = bollinger['middleband']
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['rsi'] < self.buy_rsi.value) &
                (dataframe['close'] > dataframe['ema_short']) &
                (dataframe['ema_short'] > dataframe['ema_long']) &
                (dataframe['volume_ratio'] > self.volume_threshold.value) &
                (dataframe['adx'] > self.adx_threshold.value) &
                (dataframe['close'] < dataframe['bb_upper'] * 0.98) &
                ((dataframe['macdhist'] > 0) | (dataframe['macdhist'] > dataframe['macdhist'].shift(1)))
            ),
            'enter_long'
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                (dataframe['rsi'] > self.sell_rsi.value) |
                (dataframe['close'] < dataframe['ema_short']) |
                (dataframe['close'] > dataframe['bb_upper'] * 0.99) |
                (dataframe['macdhist'] < 0)
            ),
            'exit_long'
        ] = 1
        return dataframe 