# --- Do not remove these libs ---
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np
import talib.abstract as ta
import pandas_ta as pta

from freqtrade.persistence import Trade
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame, Series, DatetimeIndex, merge
from datetime import datetime, timedelta
from freqtrade.strategy import merge_informative_pair, CategoricalParameter, DecimalParameter, IntParameter, \
    stoploss_from_open
from functools import reduce
from technical.indicators import RMI, zema


def EWO_low(dataframe, ema_length=5, ema2_length=35):
    df = dataframe.copy()
    ema1 = ta.EMA(df, timeperiod=ema_length)
    ema2 = ta.EMA(df, timeperiod=ema2_length)
    emadif = (ema2 - ema1) / df['high'] * 100
    return emadif


def EWO_high(dataframe, ema_length=5, ema2_length=35):
    df = dataframe.copy()
    ema1 = ta.EMA(df, timeperiod=ema_length)
    ema2 = ta.EMA(df, timeperiod=ema2_length)
    emadif = (ema1 - ema2) / df['low'] * 100
    return emadif


# Williams %R
def williams_r(dataframe: DataFrame, period: int = 14) -> Series:
    """Williams %R, or just %R, is a technical analysis oscillator showing the current closing price in relation to the high and low
        of the past N days (for a given N). It was developed by a publisher and promoter of trading materials, Larry Williams.
        Its purpose is to tell whether a stock or commodity market is trading near the high or the low, or somewhere in between,
        of its recent trading range.
        The oscillator is on a negative scale, from −100 (lowest) up to 0 (highest).
    """

    highest_high = dataframe["high"].rolling(center=False, window=period).max()
    lowest_low = dataframe["low"].rolling(center=False, window=period).min()

    WR = Series(
        (highest_high - dataframe["close"]) / (highest_high - lowest_low),
        name=f"{period} Williams %R",
    )

    return WR * -100


class BB_RPB_TSL_Hippocritical_EmptyHull(IStrategy):
    INTERFACE_VERSION = 3
    can_short = True
    '''
        BB_RPB_TSL
        @author jilv220
        Simple bollinger brand strategy inspired by this blog  ( https://hacks-for-life.blogspot.com/2020/12/freqtrade-notes.html )
        RPB, which stands for Real Pull Back, taken from ( https://github.com/GeorgeMurAlkh/freqtrade-stuff/blob/main/user_data/strategies/TheRealPullbackV2.py )
        The trailing custom stoploss taken from BigZ04_TSL from Perkmeister ( modded by ilya )
        I modified it to better suit my taste and added Hyperopt for this strategy.
        modified after that by Hippocritical (http://frequenthippo.com) to adjust it for futures and hyperopt it aswell.
    '''

    ##########################################################################
    # Sell hyperspace params:
    # really hard to use this
    minimal_roi = {
        "0": 0.10,
    }

    # Optimal timeframe for the strategy
    timeframe = '5m'
    # inf_1h = '1h'

    # Disabled
    stoploss = -0.99

    # Custom stoploss
    use_custom_stoploss = True
    use_exit_signal = True


    ############################################################################
    ## Custom Trailing stoploss ( credit to Perkmeister for this custom stoploss to help the strategy ride a green candle )
    ## edited so SL_1 and _2 are now showing the trailing amount meaning that now you can avoid running
    ## into backtest traps with a 0 size trailing amount.
    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                        current_rate: float, current_profit: float, **kwargs) -> float:

        # allows different levels for long / short.
        if trade.trade_direction == "long":
            # hard stoploss profit
            HSL = self.sell_long_pHSL.value
            PF_1 = self.sell_long_pPF_1.value
            SL_1 = self.sell_long_pPF_1.value - self.sell_long_pSL_1_relative.value
            PF_2 = self.sell_long_pPF_2.value
            SL_2 = self.sell_long_pPF_2.value - self.sell_long_pSL_2_relative.value
        else:
            # hard stoploss profit
            HSL = self.sell_short_pHSL.value
            PF_1 = self.sell_short_pPF_1.value
            SL_1 = self.sell_short_pPF_1.value - self.sell_short_pSL_1_relative.value
            PF_2 = self.sell_short_pPF_2.value
            SL_2 = self.sell_short_pPF_2.value - self.sell_short_pSL_2_relative.value
        # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated
        # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value
        # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used.

        if (current_profit > PF_2):
            sl_profit = SL_2 + (current_profit - PF_2)
        elif (current_profit > PF_1):
            sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1))
        else:
            sl_profit = HSL

        # Only for hyperopt invalid return
        if (sl_profit >= current_profit):
            return -0.99

        return stoploss_from_open(sl_profit, current_profit)
    ############################################################################

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        assert self.dp, "DataProvider is required for multiple timeframes."
        if self.is_short_activate_pumpbreak or self.is_short_activate_localpump or \
                self.is_long_activate_dipbreak or self.is_long_activate_localdip:
            # Bollinger bands (hyperopt hard to implement)
            bollinger2 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
            dataframe['bb_lowerband2'] = bollinger2['lower']
            dataframe['bb_middleband2'] = bollinger2['mid']
            dataframe['bb_upperband2'] = bollinger2['upper']

            bollinger3 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=3)
            dataframe['bb_lowerband3'] = bollinger3['lower']
            dataframe['bb_middleband3'] = bollinger3['mid']
            dataframe['bb_upperband3'] = bollinger3['upper']
            dataframe['closedelta'] = (dataframe['close'] - dataframe['close'].shift()).abs()

        ### BTC protection

        # BTC info
        inf_tf = '5m'
        informative = self.dp.get_pair_dataframe('BTC/USDT:USDT', timeframe=inf_tf)
        informative_past = informative.copy().shift(1)  # Get recent BTC info

        # BTC 5m dump protection, average price of OLHC/4
        informative_past_source = (informative_past['open'] + informative_past['close'] + informative_past['high'] +
                                   informative_past['low']) / 4  # Get BTC price

        # BTC 1d dump protection
        informative_past_1d = informative.copy().shift(288)  # get snapshot 24h ago for btc
        informative_past_source_1d = (informative_past_1d['open'] + informative_past_1d['close'] +
                                      informative_past_1d[
                                          'high'] + informative_past_1d[
                                          'low']) / 4  # average price OHLC 24h ago for btc
        dataframe['btc_5m'] = informative_past_source
        dataframe['btc_1d'] = informative_past_source_1d

        if self.is_short_activate_pumpbreak or self.is_long_activate_dipbreak:
            stoch = ta.STOCHRSI(dataframe, 15, 20, 2, 2)
            dataframe['srsi_fk'] = stoch['fastk']

            dataframe['bb_width'] = (
                    (dataframe['bb_upperband2'] - dataframe['bb_lowerband2']) / dataframe['bb_middleband2'])
            dataframe['bb_delta'] = (
                    (dataframe['bb_lowerband2'] - dataframe['bb_lowerband3']) / dataframe['bb_lowerband2'])

        if self.is_short_activate_localpump or self.is_long_activate_localdip:
            dataframe['ema_12'] = ta.EMA(dataframe, timeperiod=12)
            dataframe['ema_26'] = ta.EMA(dataframe, timeperiod=26)

        if self.is_short_activate_nfi32 or self.is_long_activate_nfi32:
            # SMA
            dataframe['sma_15'] = ta.SMA(dataframe, timeperiod=15)

        if self.is_short_activate_nfi33 or self.is_long_activate_nfi33:
            dataframe['ema_13'] = ta.EMA(dataframe, timeperiod=13)

        if self.is_short_activate_nfi32 or self.is_short_activate_nfi33 or \
                self.is_long_activate_nfi32 or self.is_long_activate_nfi33:
            dataframe['cti'] = pta.cti(dataframe["close"], length=20)

        if self.is_short_activate_ewo or self.is_short_activate_ewo2 or self.is_short_activate_cofi or \
                self.is_long_activate_ewo or self.is_long_activate_ewo2 or self.is_long_activate_cofi:
            dataframe['ema_8'] = ta.EMA(dataframe, timeperiod=8)

        if self.is_short_activate_ewo or self.is_short_activate_ewo2 or \
                self.is_long_activate_ewo or self.is_long_activate_ewo2:
            dataframe['ema_16'] = ta.EMA(dataframe, timeperiod=16)

        # for exit trend, always
        dataframe['hma_50'] = qtpylib.hull_moving_average(dataframe['close'], window=50)
        dataframe['sma_9'] = ta.SMA(dataframe, timeperiod=9)
        dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=4)
        dataframe['rsi_slow'] = ta.RSI(dataframe, timeperiod=20)
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)

        if self.is_short_activate_ewo or \
                self.is_short_activate_ewo2 or \
                self.is_short_activate_cofi or \
                self.is_short_activate_nfi33:
            # Elliot
            dataframe['EWO_low'] = EWO_low(dataframe, 50, 200)

        if self.is_long_activate_ewo or \
                self.is_long_activate_ewo2 or \
                self.is_long_activate_cofi or \
                self.is_long_activate_nfi33:
            dataframe['EWO_high'] = EWO_high(dataframe, 50, 200)

        if self.is_short_activate_cofi or self.is_long_activate_cofi:
            stoch_fast = ta.STOCHF(dataframe, 5, 3, 0, 3, 0)
            dataframe['fastd'] = stoch_fast['fastd']
            dataframe['fastk'] = stoch_fast['fastk']
            dataframe['adx'] = ta.ADX(dataframe)

        if self.is_short_activate_nfi33 or self.is_long_activate_nfi33:
            dataframe['r_14'] = williams_r(dataframe, period=14)
            dataframe['volume_mean_4'] = dataframe['volume'].rolling(4).mean().shift(1)


        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        enter_long_conditions = []
        enter_short_conditions = []
        dataframe.loc[:, 'enter_tag'] = ''

        is_short_pumpbreak = False
        is_short_localpump = False
        is_short_ewo = False
        is_short_ewo2 = False
        is_short_cofi = False
        is_short_nfi32 = False
        is_short_nfi33 = False

        is_long_dipbreak = False
        is_long_localdip = False
        is_long_ewo = False
        is_long_ewo2 = False
        is_long_cofi = False
        is_long_nfi32 = False
        is_long_nfi33 = False

        ###START SHORT-BUYCONDITIONS###
        if self.is_short_activate_pumpbreak:
            dataframe['buy_short_pumpbreak_cci_length'] = \
                ta.CCI(dataframe, timeperiod=int(self.buy_short_pumpbreak_cci_length.value))
            dataframe['buy_short_pumpbreak_rmi_length'] = \
                RMI(dataframe, length=int(self.buy_short_pumpbreak_rmi_length.value), mom=4)
            is_short_pumpbreak = \
                (
                        (dataframe['buy_short_pumpbreak_rmi_length']
                         > self.buy_short_pumpbreak_rmi.value) &
                        (dataframe['buy_short_pumpbreak_cci_length']
                         >= self.buy_short_pumpbreak_cci.value) &
                        (dataframe['srsi_fk'] > self.buy_short_pumpbreak_srsi_fk.value)
                        &
                        ((dataframe[
                              'bb_delta'] < self.buy_short_pumpbreak_bb_delta.value)
                         &
                         (dataframe['bb_width'] > self.buy_short_pumpbreak_bb_width.value)
                         )
                        &
                        (dataframe['closedelta'] < dataframe[
                            'close'] * self.buy_short_pumpbreak_closedelta.value / 1000) &
                        (dataframe['close'] > dataframe['bb_upperband3'] * self.buy_short_pumpbreak_bb_factor.value)
                )
        if self.is_short_activate_localpump:
            is_short_localpump = (  # from NFI next gen

                    (dataframe['ema_26'] < dataframe['ema_12']) &
                    (dataframe['ema_12'] - dataframe['ema_26'] > dataframe[
                        'open'] * self.buy_short_localpump_ema_diff.value) &
                    (dataframe['ema_12'].shift() - dataframe['ema_26'].shift() > dataframe['open'] / 100) &
                    (dataframe['close'] > dataframe['bb_upperband2'] * self.buy_short_localpump_bb_factor.value) &
                    (dataframe['closedelta'] > dataframe['close'] * self.buy_short_localpump_closedelta.value / 1000)
            )
        if self.is_short_activate_ewo:
            is_short_ewo = (  # from SMA offset
                    (dataframe['rsi_fast'] > self.buy_short_ewo_rsi_fast.value) &
                    (dataframe['close'] > dataframe['ema_8'] * self.buy_short_ewo_ema8Factor.value) &
                    (dataframe['EWO_low'] > self.buy_short_ewo_ewo.value) &
                    (dataframe['close'] > dataframe['ema_16'] * self.buy_short_ewo_ema16Factor.value) &
                    (dataframe['rsi'] > self.buy_short_ewo_rsi.value)
            )
        if self.is_short_activate_ewo2:
            is_short_ewo2 = (
                    (dataframe['rsi_fast'] > self.buy_short_ewo2_rsi_fast.value) &
                    (dataframe['close'] > dataframe['ema_8'] * self.buy_short_ewo2_ema_low.value) &
                    (dataframe['EWO_low'] > self.buy_short_ewo2_ewo.value) &
                    (dataframe['close'] > dataframe['ema_16'] * self.buy_short_ewo2_ema_high.value) &
                    (dataframe['rsi'] > self.buy_short_ewo2_rsi.value)
            )
        if self.is_short_activate_cofi:
            is_short_cofi = (
                    (dataframe['open'] > dataframe['ema_8'] * self.buy_short_cofi_ema.value) &
                    (qtpylib.crossed_below(dataframe['fastk'], dataframe['fastd'])) &
                    (dataframe['fastk'] > self.buy_short_cofi_fastk.value) &
                    (dataframe['fastd'] > self.buy_short_cofi_fastd.value) &
                    (dataframe['adx'] < self.buy_short_cofi_adx.value) &
                    (dataframe['EWO_low'] > self.buy_short_cofi_ewo_low.value)
            )
        if self.is_short_activate_nfi32:
            is_short_nfi32 = (
                    (dataframe['rsi_slow'] > dataframe['rsi_slow'].shift(1)) &
                    (dataframe['rsi_fast'] > self.buy_short_nfi32_rsi_fast.value) &
                    (dataframe['rsi'] < self.buy_short_nfi32_rsi.value) &
                    (dataframe['close'] > dataframe['sma_15'] * self.buy_short_nfi32_sma15.value) &
                    (dataframe['cti'] > self.buy_short_nfi32_cti.value)
            )
        if self.is_short_activate_nfi33:
            is_short_nfi33 = (
                    (dataframe['close'] > (dataframe['ema_13'] * self.buy_short_nfi33_ema_13.value)) &
                    (dataframe['EWO_low'] > self.buy_short_nfi33_ewo_low.value) &
                    (dataframe['cti'] > self.buy_short_nfi33_cti.value) &
                    (dataframe['rsi'] > self.buy_short_nfi33_rsi.value) &
                    (dataframe['r_14'] > self.buy_short_nfi33_r_14.value) &
                    (dataframe['volume'] > (dataframe['volume_mean_4'] * self.buy_short_nfi33_volume_mean.value))
            )
        ###END SHORT-CONDITIONS###
        ###START LONG-CONDITIONS###
        if self.is_long_activate_dipbreak:
            dataframe['buy_long_dipbreak_cci_length'] = \
                ta.CCI(dataframe, timeperiod=int(self.buy_long_dipbreak_cci_length.value))
            dataframe['buy_long_dipbreak_rmi_length'] =\
                RMI(dataframe, length=int(self.buy_long_dipbreak_rmi_length.value), mom=4)
            is_long_dipbreak = \
                (
                        (dataframe[
                             f'buy_long_dipbreak_rmi_length']
                         < self.buy_long_dipbreak_rmi.value) &
                        (dataframe[
                             f'buy_long_dipbreak_cci_length']
                         <= self.buy_long_dipbreak_cci.value) &
                        (dataframe['srsi_fk'] < self.buy_long_dipbreak_srsi_fk.value)
                        &
                        ((dataframe[
                              'bb_delta'] > self.buy_long_dipbreak_bb_delta.value)
                         &
                         (dataframe['bb_width'] > self.buy_long_dipbreak_bb_width.value)
                         )
                        &
                        (dataframe['closedelta'] > dataframe[
                            'close'] * self.buy_long_dipbreak_closedelta.value / 1000) &
                        (dataframe['close'] < dataframe['bb_lowerband3'] * self.buy_long_dipbreak_bb_factor.value)
                )
        if self.is_long_activate_localdip:
            is_long_localdip = (  # from NFI next gen

                    (dataframe['ema_26'] > dataframe['ema_12']) &
                    (dataframe['ema_26'] - dataframe['ema_12'] > dataframe[
                        'open'] * self.buy_long_localdip_ema_diff.value) &
                    (dataframe['ema_26'].shift() - dataframe['ema_12'].shift() > dataframe['open'] / 100) &
                    (dataframe['close'] < dataframe['bb_upperband2'] * self.buy_long_localdip_bb_factor.value) &
                    (dataframe['closedelta'] > dataframe['close'] * self.buy_long_localdip_closedelta.value / 1000)
            )
        if self.is_long_activate_ewo:
            is_long_ewo = (  # from SMA offset
                    (dataframe['rsi_fast'] < self.buy_long_ewo_rsi_fast.value) &
                    (dataframe['close'] < dataframe['ema_8'] * self.buy_long_ewo_ema8Factor.value) &
                    (dataframe['EWO_high'] > self.buy_long_ewo_ewo.value) &
                    (dataframe['close'] < dataframe['ema_16'] * self.buy_long_ewo_ema16Factor.value) &
                    (dataframe['rsi'] < self.buy_long_ewo_rsi.value)
            )
        if self.is_long_activate_ewo2:
            is_long_ewo2 = (
                    (dataframe['rsi_fast'] < self.buy_long_ewo2_rsi_fast.value) &
                    (dataframe['close'] < dataframe['ema_8'] * self.buy_long_ewo2_ema8Factor.value) &
                    (dataframe['EWO_high'] > self.buy_long_ewo2_ewo.value) &
                    (dataframe['close'] < dataframe['ema_16'] * self.buy_long_ewo2_ema16Factor.value) &
                    (dataframe['rsi'] < self.buy_long_ewo2_rsi.value)
            )
        if self.is_long_activate_cofi:
            is_long_cofi = (
                    (dataframe['open'] < dataframe['ema_8'] * self.buy_long_cofi_ema.value) &
                    (qtpylib.crossed_above(dataframe['fastk'], dataframe['fastd'])) &
                    (dataframe['fastk'] < self.buy_long_cofi_fastk.value) &
                    (dataframe['fastd'] < self.buy_long_cofi_fastd.value) &
                    (dataframe['adx'] > self.buy_long_cofi_adx.value) &
                    (dataframe['EWO_high'] > self.buy_long_cofi_ewo_high.value)
            )
        if self.is_long_activate_nfi32:
            is_long_nfi32 = (
                    (dataframe['rsi_slow'] < dataframe['rsi_slow'].shift(1)) &
                    (dataframe['rsi_fast'] < self.buy_long_nfi32_rsi_fast.value) &
                    (dataframe['rsi'] > self.buy_long_nfi32_rsi.value) &
                    (dataframe['close'] < dataframe['sma_15'] * self.buy_long_nfi32_sma15.value) &
                    (dataframe['cti'] < self.buy_long_nfi32_cti.value)
            )
        if self.is_long_activate_nfi33:
            is_long_nfi33 = (
                    (dataframe['close'] < (dataframe['ema_13'] * self.buy_long_nfi33_ema_13.value)) &
                    (dataframe['EWO_high'] > self.buy_long_nfi33_ewo_high.value) &
                    (dataframe['cti'] < self.buy_long_nfi33_cti.value) &
                    (dataframe['rsi'] < self.buy_long_nfi33_rsi.value) &
                    (dataframe['r_14'] < self.buy_long_nfi33_r_14.value) &
                    (dataframe['volume'] < (dataframe['volume_mean_4'] * self.buy_long_nfi33_volume_mean.value))
            )
        ###END LONG-CONDITIONS###
        ###START APPEND SHORT-CONDITIONS###
        if type(is_short_pumpbreak) is not bool:
            enter_short_conditions.append(is_short_pumpbreak)
            dataframe.loc[is_short_pumpbreak, 'enter_tag'] += 'pumpbreak_short '
        if type(is_short_localpump) is not bool:
            enter_short_conditions.append(is_short_localpump)
            dataframe.loc[is_short_localpump, 'enter_tag'] += 'local_downtrend_short '
        if type(is_short_ewo) is not bool:
            enter_short_conditions.append(is_short_ewo)
            dataframe.loc[is_short_ewo, 'enter_tag'] += 'ewo_short '
        if type(is_short_ewo2) is not bool:
            enter_short_conditions.append(is_short_ewo2)
            dataframe.loc[is_short_ewo2, 'enter_tag'] += 'ewo2_short '
        if type(is_short_cofi) is not bool:
            enter_short_conditions.append(is_short_cofi)
            dataframe.loc[is_short_cofi, 'enter_tag'] += 'cofi_short '
        if type(is_short_nfi32) is not bool:
            enter_short_conditions.append(is_short_nfi32)
            dataframe.loc[is_short_nfi32, 'enter_tag'] += 'nfi32_short '
        if type(is_short_nfi33) is not bool:
            enter_short_conditions.append(is_short_nfi33)
            dataframe.loc[is_short_nfi33, 'enter_tag'] += 'nfi33_short '
        ###END APPEND SHORT-CONDITIONS###
        ###START APPEND LONG-CONDITIONS###
        if type(is_long_dipbreak) is not bool:
            enter_long_conditions.append(is_long_dipbreak)
            dataframe.loc[is_long_dipbreak, 'enter_tag'] += 'dipbreak_long '
        if type(is_long_localdip) is not bool:
            enter_long_conditions.append(is_long_localdip)
            dataframe.loc[is_long_localdip, 'enter_tag'] += 'local_dip_long '
        if type(is_long_ewo) is not bool:
            enter_long_conditions.append(is_long_ewo)
            dataframe.loc[is_long_ewo, 'enter_tag'] += 'ewo_long '
        if type(is_long_ewo2) is not bool:
            enter_long_conditions.append(is_long_ewo2)
            dataframe.loc[is_long_ewo2, 'enter_tag'] += 'ewo2_long '
        if type(is_long_cofi) is not bool:
            enter_long_conditions.append(is_long_cofi)
            dataframe.loc[is_long_cofi, 'enter_tag'] += 'cofi_long '
        if type(is_long_nfi32) is not bool:
            enter_long_conditions.append(is_long_nfi32)
            dataframe.loc[is_long_nfi32, 'enter_tag'] += 'nfi32_long '
        if type(is_long_nfi33) is not bool:
            enter_long_conditions.append(is_long_nfi33)
            dataframe.loc[is_long_nfi33, 'enter_tag'] += 'nfi33_long '
        ###END APPEND LONG-CONDITIONS###

        if enter_long_conditions:
            dataframe.loc[reduce(lambda x, y: x | y, enter_long_conditions), 'enter_long'] = 1
        if enter_short_conditions:
            dataframe.loc[reduce(lambda x, y: x | y, enter_short_conditions), 'enter_short'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['sell_short_ema'] = ta.EMA(dataframe, timeperiod=int(self.sell_short_ema.value))
        dataframe['sell_long_ema'] = ta.EMA(dataframe, timeperiod=int(self.sell_long_ema.value))
        dataframe.loc[
            (
                    (dataframe['close'] < dataframe['sma_9']) &
                    (dataframe['close'] < (
                            dataframe['sell_short_ema'] * self.sell_short_mult.value)) &
                    (dataframe['rsi'] < self.sell_short_rsi.value) &
                    (dataframe['volume'] > 0) &
                    (dataframe['rsi_fast'] < dataframe['rsi_slow'])

            ),
            ['exit_short', 'exit_tag']] = (1, 'exit1_short')
        dataframe.loc[
            (
                    (dataframe['sma_9'] < (dataframe['sma_9'].shift(1) * self.sell_short_smaFactor.value)) &
                    (dataframe['close'] > dataframe['hma_50']) &
                    (dataframe['close'] < (
                            dataframe['sell_short_ema'] * self.sell_short_mult2.value)) &
                    (dataframe['volume'] > 0) &
                    (dataframe['rsi_fast'] < dataframe['rsi_slow'])
            ),
            ['exit_short', 'exit_tag']] = (1, 'exit_short2')
        dataframe.loc[
            (
                    (dataframe['close'] > dataframe['sma_9']) &
                    (dataframe['close'] > (
                            dataframe['sell_long_ema'] * self.sell_long_mult.value)) &
                    (dataframe['rsi'] > self.sell_long_rsi.value) &
                    (dataframe['volume'] > 0) &
                    (dataframe['rsi_fast'] > dataframe['rsi_slow'])

            ),
            ['exit_long', 'exit_tag']] = (1, 'exit_long1')
        dataframe.loc[
            (
                    (dataframe['sma_9'] > (dataframe['sma_9'].shift(1) * self.sell_long_smaFactor.value)) &
                    (dataframe['close'] < dataframe['hma_50']) &
                    (dataframe['close'] > (
                            dataframe['sell_long_ema'] * self.sell_long_mult2.value)) &
                    (dataframe['volume'] > 0) &
                    (dataframe['rsi_fast'] > dataframe['rsi_slow'])
            ),
            ['exit_long', 'exit_tag']] += (1, 'exit_long2')

        return dataframe
