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

        dataframe.loc[
            qtpylib.
            crossed_below(dataframe['tenkan_sen'], dataframe['kijun_sen'])
            | qtpylib.crossed_below(dataframe['close'], dataframe['kijun_sen']
                                    ), 'sell'] = 1

        return dataframe
    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            (
                    (dataframe['rsi'].rolling(8).max() > 93) &
                    (dataframe['macd'] > 0) &
                    (qtpylib.crossed_below(dataframe['macd'], dataframe['macdsignal']))
            ),
            'sell'] = 1

        return dataframe
Exemplo n.º 3
0
 def populate_sell_trend(dataframe: DataFrame,
                         metadata: dict) -> DataFrame:
     EMA = "EMA" + str(params['length'])
     pmax = "pm_" + str(params['length']) + "_" + str(
         params['multiplier']) + "_" + str(
             params['length']) + "_" + str(params['MAtype'])
     dataframe.loc[((
         qtpylib.crossed_below(dataframe[EMA], dataframe[pmax]))),
                   'sell'] = 1
     return dataframe
Exemplo n.º 4
0
    def populate_sell_trend(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:

        dataframe.loc[(
            # fast ema crosses below slow ema
            (qtpylib.crossed_below(dataframe['ema9'], dataframe['ema21'])) |
            (dataframe['low'] < dataframe['ema200']
             )  # OR price is below trend ema
        ), 'sell'] = 1
        return dataframe
Exemplo n.º 5
0
    def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
        """
        Based on TA indicators, populates the sell signal for the given dataframe
        :param dataframe: DataFrame
        :return: DataFrame with buy column
        """
        dataframe.loc[(
            qtpylib.crossed_below(dataframe['macd'], dataframe['macdsignal']) &
            (dataframe['cci'] >= 100.0)), 'sell'] = 1

        return dataframe
Exemplo n.º 6
0
 def populate_sell_trend(self, dataframe: DataFrame,
                         metadata: dict) -> DataFrame:
     """
     Based on TA indicators. Should be a copy of same method from strategy.
     Must align to populate_indicators in this file.
     Only used when --spaces does not include sell space.
     """
     dataframe.loc[((
         qtpylib.crossed_below(dataframe['close'], dataframe['middle']))),
                   'sell'] = 1
     return dataframe
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:

        bollinger = qtpylib.bollinger_bands(dataframe['close'],
                                            window=20,
                                            stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        dataframe['bb_width'] = (
            (dataframe['bb_upperband'] - dataframe['bb_lowerband']) /
            dataframe['bb_middleband'])
        dataframe['bb_bottom_cross'] = qtpylib.crossed_below(
            dataframe['close'], dataframe['bb_lowerband']).astype('int')

        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=10)

        dataframe['plus_di'] = ta.PLUS_DI(dataframe)
        dataframe['minus_di'] = ta.MINUS_DI(dataframe)

        dataframe['cci'] = ta.CCI(dataframe, 30)

        dataframe['mfi'] = ta.MFI(dataframe, timeperiod=14)

        dataframe['cmf'] = chaikin_mf(dataframe)

        dataframe['rmi'] = RMI(dataframe, length=8, mom=4)

        stoch = ta.STOCHRSI(dataframe, 15, 20, 2, 2)
        dataframe['srsi_fk'] = stoch['fastk']
        dataframe['srsi_fd'] = stoch['fastd']

        dataframe['fastEMA'] = ta.EMA(dataframe['volume'], timeperiod=12)
        dataframe['slowEMA'] = ta.EMA(dataframe['volume'], timeperiod=26)
        dataframe['pvo'] = ((dataframe['fastEMA'] - dataframe['slowEMA']) /
                            dataframe['slowEMA']) * 100

        dataframe['is_dip'] = ((dataframe['rmi'] < 20)
                               & (dataframe['cci'] <= -150)
                               & (dataframe['srsi_fk'] < 20)
                               # Maybe comment mfi and cmf to make more trades
                               & (dataframe['mfi'] < 25)
                               & (dataframe['cmf'] <= -0.1)).astype('int')

        dataframe['is_break'] = (
            (dataframe['bb_width'] > 0.025)
            & (dataframe['bb_bottom_cross'].rolling(10).sum() > 1)
            & (dataframe['close'] < 0.99 * dataframe['bb_lowerband'])
        ).astype('int')

        dataframe['buy_signal'] = ((dataframe['is_dip'] > 0)
                                   & (dataframe['is_break'] > 0)).astype('int')

        return dataframe
Exemplo n.º 8
0
    def populate_sell_trend(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        dataframe.loc[
            # (dataframe['Ichimoku_Score']<0)|
            (qtpylib.crossed_below(
                ta.SMA(dataframe['Ichimoku_Score'], self.sell_fast_timeperiod.
                       value),
                ta.SMA(dataframe['Ichimoku_Score'], self.sell_slow_timeperiod.
                       value))), 'sell'] = 1

        return dataframe
Exemplo n.º 9
0
 def populate_sell_trend(self, dataframe: DataFrame,
                         metadata: dict) -> DataFrame:
     """
     Based on TA indicators, populates the sell signal for the given dataframe
     :param dataframe: DataFrame
     :param metadata: Additional information, like the currently traded pair
     :return: DataFrame with buy column
     """
     dataframe.loc[(
         (qtpylib.crossed_below(dataframe['ema5'], dataframe['ema50'])) &
         (dataframe["close"] < (dataframe["high"] * 0.99))), 'sell'] = 1
     return dataframe
Exemplo n.º 10
0
 def populate_sell_trend(self, dataframe: DataFrame,
                         metadata: dict) -> DataFrame:
     conditions = []
     conditions.append(
         qtpylib.crossed_below(
             dataframe[self.sell_fast_key.value].shift(
                 self.sell_horizontal_push.value),
             dataframe[self.sell_slow_key.value] *
             self.sell_vertical_push.value))
     if conditions:
         dataframe.loc[reduce(lambda x, y: x & y, conditions), 'sell'] = 1
     return dataframe
Exemplo n.º 11
0
 def populate_sell_trend(self, dataframe: DataFrame,
                         metadata: dict) -> DataFrame:
     # print(dataframe['slowk']/dataframe['wt1'])
     dataframe.loc[(
         (qtpylib.crossed_below(dataframe['wt1'], dataframe['wt2']))
         & (dataframe['wt1'].between(self.sell_min0.value, self.sell_max0.
                                     value))
         & (dataframe['slowk'].between(self.sell_min1.value, self.sell_max1.
                                       value))
         &
         (dataframe['def'].between(self.sell_min.value, self.sell_max.value)
          )), 'sell'] = 1
     return dataframe
Exemplo n.º 12
0
    def populate_sell_trend(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        conditions = []

        # RSI Sell Hyperopt
        if self.rsi_sell_enabled.value:
            conditions.append(
                qtpylib.crossed_below(dataframe['rsi'], self.rsi_sell.value))
        dataframe.loc[((qtpylib.crossed_above(dataframe['rsi'], 70))
                       & (dataframe['tema'] > dataframe['bb_middleband'])
                       & (dataframe['tema'] < dataframe['tema'].shift(1))
                       & (dataframe['volume'] > 0)), 'sell'] = 1
        return dataframe
Exemplo n.º 13
0
    def populate_entry_trend(self, dataframe: DataFrame,
                             metadata: dict) -> DataFrame:

        dataframe.loc[((dataframe['rsi'] < self.buy_rsi.value) &
                       (dataframe['fastd'] < 35) & (dataframe['adx'] > 30) &
                       (dataframe['plus_di'] > self.buy_plusdi.value)) |
                      ((dataframe['adx'] > 65) &
                       (dataframe['plus_di'] > self.buy_plusdi.value)),
                      'enter_long'] = 1
        dataframe.loc[(
            qtpylib.crossed_below(dataframe['rsi'], self.sell_rsi.value)),
                      'enter_short'] = 1

        return dataframe
Exemplo n.º 14
0
    def populate_sell_trend(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        params = self.sell_params
        trade_data = self.custom_trade_info[metadata['pair']]
        conditions = []

        if trade_data['active_trade']:
            loss_cutoff = self.linear_growth(-0.03, 0, 0, 300,
                                             trade_data['open_minutes'])

            conditions.append((trade_data['current_profit'] < loss_cutoff)
                              & (trade_data['current_profit'] > self.stoploss)
                              & (dataframe['rmi-dn-trend'] == 1)
                              & (dataframe['volume'].gt(0)))
            if trade_data['peak_profit'] > 0:
                conditions.append(
                    qtpylib.crossed_below(dataframe['rmi-slow'], 50))
            else:
                conditions.append(
                    qtpylib.crossed_below(dataframe['rmi-slow'], 10))

            if trade_data['other_trades']:
                if trade_data['free_slots'] > 0:
                    hold_pct = (trade_data['free_slots'] / 100) * -1
                    conditions.append(
                        trade_data['avg_other_profit'] >= hold_pct)
                else:
                    conditions.append(trade_data['biggest_loser'] == True)

        else:
            conditions.append(dataframe['volume'].lt(0))

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

        return dataframe
Exemplo n.º 15
0
    def populate_buy_trend(self, dataframe: DataFrame,
                           metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the buy signal for the given dataframe
        :param dataframe: DataFrame
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with buy column
        """
        dataframe.loc[((
            qtpylib.crossed_below(dataframe['close'], dataframe['lower']))
                       # &
                       # (dataframe["close"].iloc[-1] < dataframe['lower'])
                       ), 'buy'] = 1

        return dataframe
        def populate_sell_trend(dataframe: DataFrame,
                                metadata: dict) -> DataFrame:
            conditions = []

            rmi_drop = dataframe['rmi-max'] - (dataframe['rmi-max'] *
                                               params['sell-rmi-drop'])
            conditions.append((dataframe['rmi-dn-trend'] == 1) & (
                qtpylib.crossed_below(dataframe['rmi-slow'], rmi_drop))
                              & (dataframe['volume'].gt(0)))

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

            # dataframe['sell'] = 0
            return dataframe
        def populate_sell_trend(dataframe: DataFrame,
                                metadata: dict) -> DataFrame:
            """
            Sell strategy Hyperopt will build and use.
            """
            conditions = []

            # GUARDS AND TRENDS
            for i in range(DNA_SIZE):

                OPR = params[f'sell-oper-{i}']
                IND = params[f'sell-indicator-{i}']
                CRS = params[f'sell-cross-{i}']
                INT = params[f'sell-int-{i}']
                REAL = params[f'sell-real-{i}']
                DFIND = dataframe[IND]
                DFCRS = dataframe[CRS]

                if OPR == ">":
                    conditions.append(DFIND > DFCRS)
                elif OPR == "=":
                    conditions.append(np.isclose(DFIND, DFCRS))
                elif OPR == "<":
                    conditions.append(DFIND < DFCRS)
                elif OPR == "CA":
                    conditions.append(qtpylib.crossed_above(DFIND, DFCRS))
                elif OPR == "CB":
                    conditions.append(qtpylib.crossed_below(DFIND, DFCRS))
                elif OPR == ">I":
                    conditions.append(DFIND > INT)
                elif OPR == "=I":
                    conditions.append(DFIND == INT)
                elif OPR == "<I":
                    conditions.append(DFIND < INT)
                elif OPR == ">R":
                    conditions.append(DFIND > REAL)
                elif OPR == "=R":
                    conditions.append(np.isclose(DFIND, REAL))
                elif OPR == "<R":
                    conditions.append(DFIND < REAL)

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

            return dataframe
Exemplo n.º 18
0
        def populate_sell_trend(dataframe: DataFrame,
                                metadata: dict) -> DataFrame:
            """
            Sell strategy Hyperopt will build and use.
            """
            conditions = []

            # TRIGGERS
            if 'sell-trigger' in params:
                if params['sell-trigger'] == 'sell-middle':
                    conditions.append(
                        qtpylib.crossed_below(dataframe['close'],
                                              dataframe['middle']))

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

            return dataframe
Exemplo n.º 19
0
    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        conditions = list()
        # /5: Cuz We have 5 Group of variables inside buy_param
        for i in range(int(len(self.buy_params)/5)):

            OPR = self.buy_params[f'buy-oper-{i}']
            IND = self.buy_params[f'buy-indicator-{i}']
            CRS = self.buy_params[f'buy-cross-{i}']
            INT = self.buy_params[f'buy-int-{i}']
            REAL = self.buy_params[f'buy-real-{i}']
            DFIND = dataframe[IND]
            DFCRS = dataframe[CRS]

            if OPR == ">":
                conditions.append(DFIND > DFCRS)
            elif OPR == "=":
                conditions.append(np.isclose(DFIND, DFCRS))
            elif OPR == "<":
                conditions.append(DFIND < DFCRS)
            elif OPR == "CA":
                conditions.append(qtpylib.crossed_above(DFIND, DFCRS))
            elif OPR == "CB":
                conditions.append(qtpylib.crossed_below(DFIND, DFCRS))
            elif OPR == ">I":
                conditions.append(DFIND > INT)
            elif OPR == "=I":
                conditions.append(DFIND == INT)
            elif OPR == "<I":
                conditions.append(DFIND < INT)
            elif OPR == ">R":
                conditions.append(DFIND > REAL)
            elif OPR == "=R":
                conditions.append(np.isclose(DFIND, REAL))
            elif OPR == "<R":
                conditions.append(DFIND < REAL)

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

        return dataframe
Exemplo n.º 20
0
    def populate_buy_trend(self, dataframe: DataFrame,
                           metadata: dict) -> DataFrame:
        conditions = list()
        for i in range(self.Buy_DNA_Size):

            OPR = self.buy_params[f'buy-oper-{i}']
            IND = self.buy_params[f'buy-indicator-{i}']
            CRS = self.buy_params[f'buy-cross-{i}']
            INT = self.buy_params[f'buy-int-{i}']
            REAL = self.buy_params[f'buy-real-{i}']
            DFIND = dataframe[IND]
            DFCRS = dataframe[CRS]

            if OPR == ">":
                conditions.append(DFIND > DFCRS)
            elif OPR == "=":
                conditions.append(np.isclose(DFIND, DFCRS))
            elif OPR == "<":
                conditions.append(DFIND < DFCRS)
            elif OPR == "CA":
                conditions.append(qtpylib.crossed_above(DFIND, DFCRS))
            elif OPR == "CB":
                conditions.append(qtpylib.crossed_below(DFIND, DFCRS))
            elif OPR == ">I":
                conditions.append(DFIND > INT)
            elif OPR == "=I":
                conditions.append(DFIND == INT)
            elif OPR == "<I":
                conditions.append(DFIND < INT)
            elif OPR == ">R":
                conditions.append(DFIND > REAL)
            elif OPR == "=R":
                conditions.append(np.isclose(DFIND, REAL))
            elif OPR == "<R":
                conditions.append(DFIND < REAL)

        if self.Buy_DNA_Size > 0:
            dataframe.loc[reduce(lambda x, y: x & y, conditions), 'buy'] = 1

        return dataframe
Exemplo n.º 21
0
    def populate_sell_trend(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        params = self.get_pair_params(metadata['pair'], 'sell')
        trade_data = self.custom_trade_info[metadata['pair']]
        conditions = []

        # If we are in an active trade (which is the only way a sell can occur...)
        # This is needed to block backtest/hyperopt from hitting the profit stuff and erroring out.
        if trade_data['active_trade']:
            # Decay a loss cutoff point where we allow a sell to occur idea is this allows
            # a trade to go into the negative a little bit before we react to sell.
            loss_cutoff = cta.linear_growth(-0.03, 0, 0, 240,
                                            trade_data['open_minutes'])

            conditions.append((trade_data['current_profit'] < loss_cutoff))

            # Examine the state of our other trades and free_slots to inform the decision
            if trade_data['other_trades']:
                if trade_data['free_slots'] > 0:
                    # If the average of all our other trades is below a certain threshold based
                    # on free slots available, hold and wait for market recovery.
                    hold_pct = (1 / trade_data['free_slots']) * -0.04
                    conditions.append(
                        trade_data['avg_other_profit'] >= hold_pct)
                else:
                    # If we are out of free slots disregard the above and allow the biggest loser to sell.
                    conditions.append(trade_data['biggest_loser'] == True)

        # Primary sell trigger
        rmi_drop = dataframe['rmi-max'] - (dataframe['rmi-max'] *
                                           params['sell-rmi-drop'])
        conditions.append((dataframe['rmi-dn-trend'] == 1) & (
            qtpylib.crossed_below(dataframe['rmi-slow'], rmi_drop))
                          & (dataframe['volume'].gt(0)))

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

        return dataframe
Exemplo n.º 22
0
        def populate_sell_trend(dataframe: DataFrame,
                                metadata: dict) -> DataFrame:

            conditions = []
            # Guards
            if params.get('sell-rsi-enabled'):
                conditions.append(
                    (qtpylib.crossed_below(dataframe['rsi'],
                                           params['sell-rsi-limit'])
                     | qtpylib.crossed_below(dataframe['rsi'].shift(1),
                                             params['sell-rsi-limit'])
                     | qtpylib.crossed_below(dataframe['rsi'].shift(2),
                                             params['sell-rsi-limit']))
                    & (dataframe['rsi'].lt(params['sell-rsi-limit'])))
            if params.get('sell-cci-enabled'):
                conditions.append(
                    (qtpylib.crossed_below(dataframe['cci'],
                                           params['sell-cci-limit'])
                     | qtpylib.crossed_below(dataframe['cci'].shift(1),
                                             params['sell-cci-limit'])
                     | qtpylib.crossed_below(dataframe['cci'].shift(2),
                                             params['sell-cci-limit']))
                    & (dataframe['cci'].lt(params['sell-cci-limit'])))

            # Triggers
            if params.get('sell-kama-trigger') == 'cross':
                conditions.append(
                    qtpylib.crossed_below(dataframe['kama-short'],
                                          dataframe['kama-long']))
            if params.get('sell-kama-trigger') == 'slope':
                conditions.append(
                    dataframe['kama-long'] < dataframe['kama-long'].shift(1))

            # Check that the candle had volume
            conditions.append(dataframe['volume'] > 0)

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

            return dataframe
Exemplo n.º 23
0
    def populate_sell_trend(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        params = self.sell_params
        trade_data = self.custom_trade_info[metadata['pair']]
        conditions = []

        # In this strategy all sells for profit happen according to ROI
        # This sell signal is designed as a "dynamic stoploss"

        # if we are in an active trade for this pair
        if trade_data['active_trade']:
            # if we are at a loss, consider what the trend looks and preempt the stoploss
            conditions.append(
                (trade_data['current_profit'] < 0)
                & (trade_data['current_profit'] > self.stoploss)
                & (dataframe['rmi-dn-trend'] == 1)
                & (qtpylib.crossed_below(dataframe['rmi-fast'], 50))
                & (dataframe['volume'].gt(0)))

            # if there are other open trades in addition to this one, consider the average profit
            # across them all (not including this one), don't sell if entire market is down big and wait for recovery
            if trade_data['other_trades']:
                if trade_data['free_slots'] == 0:
                    conditions.append(trade_data['avg_other_profit'] >= -0.03)
                else:
                    conditions.append(trade_data['avg_other_profit'] >= -0.01)

        # the bot comes through this loop even when there isn't an open trade to sell
        # so we pass an impossible condiiton here because we don't want a sell signal
        # clogging up the charts and not having one leads the bot to crash
        else:
            conditions.append(dataframe['volume'].lt(0))

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

        return dataframe
Exemplo n.º 24
0
        def populate_sell_trend(dataframe: DataFrame,
                                metadata: dict) -> DataFrame:
            # Detect if current trend going Downwards / Sideways / Upwards, strategy will respond accordingly
            dataframe.loc[(dataframe['adx'] > 20) &
                          (dataframe['plus_di'] < dataframe['minus_di']),
                          'trend'] = 'downwards'
            dataframe.loc[dataframe['adx'] < 20, 'trend'] = 'sideways'
            dataframe.loc[(dataframe['adx'] > 20) &
                          (dataframe['plus_di'] > dataframe['minus_di']),
                          'trend'] = 'upwards'

            # If a Weighted Sell Signal goes off => Bearish Indication, Set to true (=1) and multiply by weight
            # percentage

            # Weighted Sell Signal: ADX above 25 & +DI below -DI (The trend has strength while moving down)
            dataframe.loc[(dataframe['trend'] == 'downwards') &
                          (dataframe['adx'] > 25),
                          'total_sell_signal_strength'] += 1 * params[
                              'downwards_trend_adx_strong_down_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways') &
                          (dataframe['adx'] > 25),
                          'total_sell_signal_strength'] += 1 * params[
                              'sideways_trend_adx_strong_down_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards') &
                          (dataframe['adx'] > 25),
                          'total_sell_signal_strength'] += 1 * params[
                              'upwards_trend_adx_strong_down_sell_weight']

            # Weighted Sell Signal: RSI crosses below 70 (Over-bought / high-price and dropping indication)
            dataframe.loc[(dataframe['trend'] == 'downwards')
                          & qtpylib.crossed_below(dataframe['rsi'], 70),
                          'total_sell_signal_strength'] += 1 * params[
                              'downwards_trend_rsi_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways')
                          & qtpylib.crossed_below(dataframe['rsi'], 70),
                          'total_sell_signal_strength'] += 1 * params[
                              'sideways_trend_rsi_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards')
                          & qtpylib.crossed_below(dataframe['rsi'], 70),
                          'total_sell_signal_strength'] += 1 * params[
                              'upwards_trend_rsi_sell_weight']

            # Weighted Sell Signal: MACD below Signal
            dataframe.loc[(dataframe['trend'] == 'downwards') &
                          (dataframe['macd'] < dataframe['macdsignal']),
                          'total_sell_signal_strength'] += 1 * params[
                              'downwards_trend_macd_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways') &
                          (dataframe['macd'] < dataframe['macdsignal']),
                          'total_sell_signal_strength'] += 1 * params[
                              'sideways_trend_macd_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards') &
                          (dataframe['macd'] < dataframe['macdsignal']),
                          'total_sell_signal_strength'] += 1 * params[
                              'upwards_trend_macd_sell_weight']

            # Weighted Sell Signal: SMA short term Death Cross (Short term SMA crosses below Medium term SMA)
            dataframe.loc[(dataframe['trend'] == 'downwards') & qtpylib.crossed_below(dataframe['sma9'], dataframe[
                'sma50']), 'total_sell_signal_strength'] += \
                1 * params['downwards_trend_sma_short_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways') & qtpylib.crossed_below(dataframe['sma9'], dataframe[
                'sma50']), 'total_sell_signal_strength'] += \
                1 * params['sideways_trend_sma_short_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards') & qtpylib.crossed_below(dataframe['sma9'], dataframe[
                'sma50']), 'total_sell_signal_strength'] += \
                1 * params['upwards_trend_sma_short_death_cross_sell_weight']

            # Weighted Sell Signal: EMA short term Death Cross (Short term EMA crosses below Medium term EMA)
            dataframe.loc[(dataframe['trend'] == 'downwards') & qtpylib.crossed_below(dataframe['ema9'], dataframe[
                'ema50']), 'total_sell_signal_strength'] += \
                1 * params['downwards_trend_ema_short_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways') & qtpylib.crossed_below(dataframe['ema9'], dataframe[
                'ema50']), 'total_sell_signal_strength'] += \
                1 * params['sideways_trend_ema_short_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards') & qtpylib.crossed_below(dataframe['ema9'], dataframe[
                'ema50']), 'total_sell_signal_strength'] += \
                1 * params['upwards_trend_ema_short_death_cross_sell_weight']

            # Weighted Sell Signal: SMA long term Death Cross (Medium term SMA crosses below Long term SMA)
            dataframe.loc[(dataframe['trend'] == 'downwards') & qtpylib.crossed_below(dataframe['sma50'], dataframe[
                'sma200']), 'total_sell_signal_strength'] += \
                1 * params['downwards_trend_sma_long_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways') & qtpylib.crossed_below(dataframe['sma50'], dataframe[
                'sma200']), 'total_sell_signal_strength'] += \
                1 * params['sideways_trend_sma_long_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards') & qtpylib.crossed_below(dataframe['sma50'], dataframe[
                'sma200']), 'total_sell_signal_strength'] += \
                1 * params['upwards_trend_sma_long_death_cross_sell_weight']

            # Weighted Sell Signal: EMA long term Death Cross (Medium term EMA crosses below Long term EMA)
            dataframe.loc[(dataframe['trend'] == 'downwards') & qtpylib.crossed_below(dataframe['ema50'], dataframe[
                'ema200']), 'total_sell_signal_strength'] += \
                1 * params['downwards_trend_ema_long_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways') & qtpylib.crossed_below(dataframe['ema50'], dataframe[
                'ema200']), 'total_sell_signal_strength'] += \
                1 * params['sideways_trend_ema_long_death_cross_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards') & qtpylib.crossed_below(dataframe['ema50'], dataframe[
                'ema200']), 'total_sell_signal_strength'] += \
                1 * params['upwards_trend_ema_long_death_cross_sell_weight']

            # Weighted Sell Signal: Re-Entering Upper Bollinger Band after upward breakout
            # (Candle closes below Upper Bollinger Band)
            dataframe.loc[(dataframe['trend'] == 'downwards') & qtpylib.crossed_below(dataframe['close'], dataframe[
                'bb_upperband']), 'total_sell_signal_strength'] += \
                1 * params['downwards_trend_bollinger_bands_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'sideways') & qtpylib.crossed_below(dataframe['close'], dataframe[
                'bb_upperband']), 'total_sell_signal_strength'] += \
                1 * params['sideways_trend_bollinger_bands_sell_weight']
            dataframe.loc[(dataframe['trend'] == 'upwards') & qtpylib.crossed_below(dataframe['close'], dataframe[
                'bb_upperband']), 'total_sell_signal_strength'] += \
                1 * params['upwards_trend_bollinger_bands_sell_weight']

            # Weighted Sell Signal: VWAP crosses below current price
            dataframe.loc[
                (dataframe['trend'] == 'downwards')
                & qtpylib.crossed_below(dataframe['vwap'], dataframe['close']),
                'total_sell_signal_strength'] += 1 * params[
                    'downwards_trend_vwap_cross_sell_weight']
            dataframe.loc[
                (dataframe['trend'] == 'sideways')
                & qtpylib.crossed_below(dataframe['vwap'], dataframe['close']),
                'total_sell_signal_strength'] += 1 * params[
                    'sideways_trend_vwap_cross_sell_weight']
            dataframe.loc[
                (dataframe['trend'] == 'upwards')
                & qtpylib.crossed_below(dataframe['vwap'], dataframe['close']),
                'total_sell_signal_strength'] += 1 * params[
                    'upwards_trend_vwap_cross_sell_weight']

            # Check if sell signal should be sent depending on the current trend
            dataframe.loc[(dataframe['trend'] == 'downwards') & (
                dataframe['total_sell_signal_strength'] >=
                params['_downwards_trend_total_sell_signal_needed']),
                          'sell'] = 1
            dataframe.loc[(dataframe['trend'] == 'sideways') &
                          (dataframe['total_sell_signal_strength'] >=
                           params['_sideways_trend_total_sell_signal_needed']),
                          'sell'] = 1
            dataframe.loc[(dataframe['trend'] == 'upwards') &
                          (dataframe['total_sell_signal_strength'] >=
                           params['_upwards_trend_total_sell_signal_needed']),
                          'sell'] = 1

            # Override Sell Signal: When configured sell signals can be completely turned off for each kind of trend
            if not params['.trade_sells_when_downwards']:
                dataframe.loc[dataframe['trend'] == 'downwards', 'sell'] = 0
            if not params['.trade_sells_when_sideways']:
                dataframe.loc[dataframe['trend'] == 'sideways', 'sell'] = 0
            if not params['.trade_sells_when_upwards']:
                dataframe.loc[dataframe['trend'] == 'upwards', 'sell'] = 0

            return dataframe
Exemplo n.º 25
0
 def populate_sell_trend(self, dataframe: DataFrame,
                         metadata: dict) -> DataFrame:
     dataframe.loc[((
         qtpylib.crossed_below(dataframe['ema20'], dataframe['ema60']))),
                   'sell'] = 1
     return dataframe
    'sma_short_golden_cross':
    lambda df: (qtpylib.crossed_above(df['sma9'], df['sma50'])),
    # Weighted Buy Signal: TEMA
    'tema':
    lambda df:
    (df['tema'] <= df['bb_middleband']) & (df['tema'] > df['tema'].shift(1))
}

# Define the Weighted Sell Signals to be used by MGM
sell_signals = {
    # Weighted Sell Signal: MACD below Signal
    'macd':
    lambda df: (df['macd'] < df['macdsignal']),
    # Weighted Sell Signal: MFI crosses below 80 (Over-bought / high-price and dropping indication)
    'mfi':
    lambda df: (qtpylib.crossed_below(df['mfi'], 80)),
    # Weighted Sell Signal: Rolling VWAP crosses below current price
    'rolling_vwap_cross':
    lambda df: (qtpylib.crossed_below(df['rolling_vwap'], df['close'])),
    # Weighted Sell Signal: Price crosses below Parabolic SAR
    'sar_cross':
    lambda df: (qtpylib.crossed_below(df['sar'], df['close'])),
    # Weighted Sell Signal: Stochastic Slow above 80 (Over-bought, indication of starting to move down)
    'stoch':
    lambda df: (df['slowk'] > 80),
    # Weighted Sell Signal: SMA long term Death Cross (Medium term SMA crosses below Long term SMA)
    'sma_long_death_cross':
    lambda df: (qtpylib.crossed_below(df['sma50'], df['sma200'])),
    # Weighted Sell Signal: SMA short term Death Cross (Short term SMA crosses below Medium term SMA)
    'sma_short_death_cross':
    lambda df: (qtpylib.crossed_below(df['sma9'], df['sma50'])),
Exemplo n.º 27
0
    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        params = self.get_pair_params(metadata['pair'], 'sell')
        trade_data = self.custom_trade_info[metadata['pair']]
        conditions = []
        
        """
        Previous Schism sell implementation has been *partially* replaced by custom_stoploss.
        Doing it there makes it able to be backtested more realistically but some of the functionality
        such as the ability to use other trades or the # of slots in our decision need to remain here.

        The current sell is meant to be a pre-stoploss bailout but most sells at a loss
        should happen due to the stoploss in live/dry.

        ** Only part of this signal functions in backtest/hyperopt. Can only be optimized in live/dry.
        ** Results in backtest/hyperopts will sell far more readily than in live due to the profit guards.
        """

        # If we are in an active trade (which is the only way a sell can occur...)
        # This is needed to block backtest/hyperopt from hitting the profit stuff and erroring out.
        if trade_data['active_trade']:  
            # Decay a loss cutoff point where we allow a sell to occur idea is this allows
            # a trade to go into the negative a little bit before we react to sell.
            loss_cutoff = self.linear_growth(-0.03, 0, 0, 240, trade_data['open_minutes'])
            conditions.append((trade_data['current_profit'] < loss_cutoff))

            # Primary sell trigger
            # TODO: Experiment with replacing or augmenting this with PMAX 
            rmi_drop = dataframe['rmi-max'] - (dataframe['rmi-max'] * 0.50)
            conditions.append(
                (dataframe['rmi-dn-trend'] == 1) &
                (qtpylib.crossed_below(dataframe['rmi-slow'], rmi_drop)) &
                (dataframe['volume'].gt(0))
            )
            
            # Examine the state of our other trades and free_slots to inform the decision
            if trade_data['other_trades']:
                if trade_data['free_slots'] > 0:
                    # If the average of all our other trades is below a certain threshold based
                    # on free slots available, hold and wait for market recovery.
                    max_market_down = -0.04 
                    hold_pct = (1/trade_data['free_slots']) * max_market_down
                    conditions.append(trade_data['avg_other_profit'] >= hold_pct)
                else:
                    # If we are out of free slots disregard the above and allow the biggest loser to sell.
                    conditions.append(trade_data['biggest_loser'] == True)
        else:
            # This is an impossible condition but needs to be here for some reason?
            conditions.append(dataframe['volume'].lt(0))

        """
        rmi_drop = dataframe['rmi-max'] - (dataframe['rmi-max'] * params['sell-rmi-drop'])

        conditions.append(
            (dataframe['rmi-dn-trend'] == 1) &
            (qtpylib.crossed_below(dataframe['rmi-slow'], rmi_drop)) &
            (dataframe['volume'].gt(0))
        )
        """
                           
        if conditions:
            dataframe.loc[
                reduce(lambda x, y: x & y, conditions),
                'sell'] = 1

        return dataframe
Exemplo n.º 28
0
def condition_generator(dataframe, operator, indicator, crossed_indicator,
                        real_num):

    condition = (dataframe['volume'] > 10)

    # TODO : it ill callculated in populate indicators.

    dataframe[indicator] = gene_calculator(dataframe, indicator)
    dataframe[crossed_indicator] = gene_calculator(dataframe,
                                                   crossed_indicator)

    indicator_trend_sma = f"{indicator}-SMA-{TREND_CHECK_CANDLES}"
    if operator in ["UT", "DT", "OT", "CUT", "CDT", "COT"]:
        dataframe[indicator_trend_sma] = gene_calculator(
            dataframe, indicator_trend_sma)

    if operator == ">":
        condition = (dataframe[indicator] > dataframe[crossed_indicator])
    elif operator == "=":
        condition = (np.isclose(dataframe[indicator],
                                dataframe[crossed_indicator]))
    elif operator == "<":
        condition = (dataframe[indicator] < dataframe[crossed_indicator])
    elif operator == "C":
        condition = ((qtpylib.crossed_below(dataframe[indicator],
                                            dataframe[crossed_indicator])) |
                     (qtpylib.crossed_above(dataframe[indicator],
                                            dataframe[crossed_indicator])))
    elif operator == "CA":
        condition = (qtpylib.crossed_above(dataframe[indicator],
                                           dataframe[crossed_indicator]))
    elif operator == "CB":
        condition = (qtpylib.crossed_below(dataframe[indicator],
                                           dataframe[crossed_indicator]))
    elif operator == ">R":
        condition = (dataframe[indicator] > real_num)
    elif operator == "=R":
        condition = (np.isclose(dataframe[indicator], real_num))
    elif operator == "<R":
        condition = (dataframe[indicator] < real_num)
    elif operator == "/>R":
        condition = (dataframe[indicator].div(dataframe[crossed_indicator]) >
                     real_num)
    elif operator == "/=R":
        condition = (np.isclose(
            dataframe[indicator].div(dataframe[crossed_indicator]), real_num))
    elif operator == "/<R":
        condition = (dataframe[indicator].div(dataframe[crossed_indicator]) <
                     real_num)
    elif operator == "UT":
        condition = (dataframe[indicator] > dataframe[indicator_trend_sma])
    elif operator == "DT":
        condition = (dataframe[indicator] < dataframe[indicator_trend_sma])
    elif operator == "OT":
        condition = (np.isclose(dataframe[indicator],
                                dataframe[indicator_trend_sma]))
    elif operator == "CUT":
        condition = ((qtpylib.crossed_above(dataframe[indicator],
                                            dataframe[indicator_trend_sma])) &
                     (dataframe[indicator] > dataframe[indicator_trend_sma]))
    elif operator == "CDT":
        condition = ((qtpylib.crossed_below(dataframe[indicator],
                                            dataframe[indicator_trend_sma])) &
                     (dataframe[indicator] < dataframe[indicator_trend_sma]))
    elif operator == "COT":
        condition = (
            ((qtpylib.crossed_below(dataframe[indicator],
                                    dataframe[indicator_trend_sma])) |
             (qtpylib.crossed_above(dataframe[indicator],
                                    dataframe[indicator_trend_sma]))) &
            (np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])))

    return condition, dataframe