# source: https://raw.githubusercontent.com/cycle-luca/reqtrade-strategies/82c460c3d1c318524702dc18b8f6cd9c07e752a0/macd.py
from freqtrade.strategy import IStrategy, merge_informative_pair
from freqtrade.strategy.indicators import (
    macd,
    atr
)

class github_cycle_luca_reqtrade_strategies__macd__20230330_132513(IStrategy):

    EMA_SHORT_TERM = 21
    EMA_MEDIUM_TERM = 55
    EMA_LONG_TERM = 120

    minimal_roi = {
        "0": 3
    }

    # Use only the informative pairs for the indicators
    informative_timeframe = '1h'
    informative = [("ETH/BTC", "1h")]

    def populate_indicators(self, dataframe: dict, metadata: dict) -> dict:
        dataframe['ema_short'] = dataframe['close'].ewm(span=self.EMA_SHORT_TERM).mean()
        dataframe['ema_medium'] = dataframe['close'].ewm(span=self.EMA_MEDIUM_TERM).mean()
        dataframe['ema_long'] = dataframe['close'].ewm(span=self.EMA_LONG_TERM).mean()

        # Compute MACD
        macd_values = macd(dataframe, self.EMA_SHORT_TERM, self.EMA_MEDIUM_TERM, self.EMA_LONG_TERM)
        dataframe['macd'] = macd_values['macd']
        dataframe['macd_signal'] = macd_values['signal']
        dataframe['macd_hist'] = macd_values['histogram']

        # Compute ATR
        dataframe['atr'] = atr(dataframe, timeperiod=14)

        return dataframe

    def populate_buy_trend(self, dataframe: dict, metadata: dict) -> dict:
        if self.condition(dataframe, "buy"):
            dataframe.loc[
                (
                    dataframe['close'] <= dataframe['ema_short'] * 1.02 # Buy when price falls below EMA short-term + 2%
                ),
                'buy'
            ] = 1

        return dataframe

    def populate_sell_trend(self, dataframe: dict, metadata: dict) -> dict:
        if self.condition(dataframe, "sell"):
            dataframe.loc[
                (
                    dataframe['close'] >= dataframe['ema_short'] * 0.98 # Sell when price rises above EMA short-term - 2%
                ),
                'sell'
            ] = 1

        return dataframe

    def condition(self, dataframe: dict, action: str) -> bool:
        # Check MACD trend
        if action == "buy":
            if dataframe['macd'].iloc[-1] > 0 and dataframe['macd'].iloc[-2] < 0:
                return True
        elif action == "sell":
            if dataframe['macd'].iloc[-1] < 0 and dataframe['macd'].iloc[-2] > 0:
                return True

        # Check ATR stop-loss
        atr_value = dataframe['atr'].iloc[-1]
        if action == "buy":
            stop_loss = dataframe['close'].iloc[-1] - 2 * atr_value
            if stop_loss < dataframe['low'].iloc[-1]:
                return False
        elif action == "sell":
            stop_loss = dataframe['close'].iloc[-1] + 2 * atr_value
            if stop_loss > dataframe['high'].iloc[-1]:
                return False

        return True

