Exemple #1
0
def test_merge_informative_pair_lower():
    data = generate_test_data('1h', 40)
    informative = generate_test_data('15m', 40)

    with pytest.raises(ValueError,
                       match=r"Tried to merge a faster timeframe .*"):
        merge_informative_pair(data, informative, '1h', '15m', ffill=True)
Exemple #2
0
def test_merge_informative_pair():
    data = generate_test_data('15m', 40)
    informative = generate_test_data('1h', 40)

    result = merge_informative_pair(data, informative, '15m', '1h', ffill=True)
    assert isinstance(result, pd.DataFrame)
    assert len(result) == len(data)
    assert 'date' in result.columns
    assert result['date'].equals(data['date'])
    assert 'date_1h' in result.columns

    assert 'open' in result.columns
    assert 'open_1h' in result.columns
    assert result['open'].equals(data['open'])

    assert 'close' in result.columns
    assert 'close_1h' in result.columns
    assert result['close'].equals(data['close'])

    assert 'volume' in result.columns
    assert 'volume_1h' in result.columns
    assert result['volume'].equals(data['volume'])

    # First 3 rows are empty
    assert result.iloc[0]['date_1h'] is pd.NaT
    assert result.iloc[1]['date_1h'] is pd.NaT
    assert result.iloc[2]['date_1h'] is pd.NaT
    # Next 4 rows contain the starting date (0:00)
    assert result.iloc[3]['date_1h'] == result.iloc[0]['date']
    assert result.iloc[4]['date_1h'] == result.iloc[0]['date']
    assert result.iloc[5]['date_1h'] == result.iloc[0]['date']
    assert result.iloc[6]['date_1h'] == result.iloc[0]['date']
    # Next 4 rows contain the next Hourly date original date row 4
    assert result.iloc[7]['date_1h'] == result.iloc[4]['date']
    assert result.iloc[8]['date_1h'] == result.iloc[4]['date']

    informative = generate_test_data('1h', 40)
    result = merge_informative_pair(data, informative, '15m', '1h', ffill=False)
    # First 3 rows are empty
    assert result.iloc[0]['date_1h'] is pd.NaT
    assert result.iloc[1]['date_1h'] is pd.NaT
    assert result.iloc[2]['date_1h'] is pd.NaT
    # Next 4 rows contain the starting date (0:00)
    assert result.iloc[3]['date_1h'] == result.iloc[0]['date']
    assert result.iloc[4]['date_1h'] is pd.NaT
    assert result.iloc[5]['date_1h'] is pd.NaT
    assert result.iloc[6]['date_1h'] is pd.NaT
    # Next 4 rows contain the next Hourly date original date row 4
    assert result.iloc[7]['date_1h'] == result.iloc[4]['date']
    assert result.iloc[8]['date_1h'] is pd.NaT
Exemple #3
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:

        assert (timeframe_to_minutes(
            self.timeframe) == 5), "Run this strategy at 5m."

        if self.timeframe == self.informative_timeframe:
            dataframe = self.slow_tf_indicators(dataframe, metadata)
        else:
            assert self.dp, "DataProvider is required for multiple timeframes."

            informative = self.dp.get_pair_dataframe(
                pair=metadata['pair'], timeframe=self.informative_timeframe)
            informative = self.slow_tf_indicators(informative.copy(), metadata)

            dataframe = merge_informative_pair(dataframe,
                                               informative,
                                               self.timeframe,
                                               self.informative_timeframe,
                                               ffill=True)
            # don't overwrite the base dataframe's OHLCV information
            skip_columns = [
                (s + "_" + self.informative_timeframe)
                for s in ['date', 'open', 'high', 'low', 'close', 'volume']
            ]
            dataframe.rename(columns=lambda s: s.replace(
                "_{}".format(self.informative_timeframe), "")
                             if (not s in skip_columns) else s,
                             inplace=True)

        dataframe = self.fast_tf_indicators(dataframe, metadata)

        return dataframe
Exemple #4
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        # Set Up Bollinger Bands
        mid, lower = bollinger_bands(dataframe['close'],
                                     window_size=40,
                                     num_of_std=2)
        dataframe['lower'] = lower
        dataframe['bbdelta'] = (mid - dataframe['lower']).abs()
        dataframe['closedelta'] = (dataframe['close'] -
                                   dataframe['close'].shift()).abs()
        dataframe['tail'] = (dataframe['close'] - dataframe['low']).abs()
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe),
                                            window=20,
                                            stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']

        dataframe['ema_slow'] = ta.EMA(dataframe, timeperiod=50)
        dataframe['volume_mean_slow'] = dataframe['volume'].rolling(
            window=30).mean()
        dataframe['rocr'] = ta.ROCR(dataframe, timeperiod=28)

        inf_tf = '1h'

        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=inf_tf)
        informative['rocr'] = ta.ROCR(informative, timeperiod=168)
        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           inf_tf,
                                           ffill=True)

        return dataframe
Exemple #5
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        """
        Adds several different TA indicators to the given DataFrame

        Performance Note: For the best performance be frugal on the number of indicators
        you are using. Let uncomment only the indicator you are using in your strategies
        or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
        """

        dataframe['ema20'] = ta.EMA(dataframe, timeperiod=20)
        dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
        dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
        if self.dp:
            # Get ohlcv data for informative pair at 15m interval.
            inf_tf = '15m'
            informative = self.dp.get_pair_dataframe(pair=f"BTC/USDT",
                                                     timeframe=inf_tf)

            # calculate SMA20 on informative pair
            informative['sma20'] = informative['close'].rolling(20).mean()

            # Combine the 2 dataframe
            # This will result in a column named 'closeETH' or 'closeBTC' - depending on stake_currency.
            dataframe = merge_informative_pair(dataframe,
                                               informative,
                                               self.timeframe,
                                               inf_tf,
                                               ffill=True)

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

        if self.config['runmode'].value in ('backtest', 'hyperopt'):
            assert (timeframe_to_minutes(self.timeframe) <=
                    5), "Backtest this strategy in 5m or 1m timeframe."

        if self.timeframe == self.informative_timeframe:
            dataframe = self.do_indicators(dataframe, metadata)
        else:
            if not self.dp:
                return dataframe

            informative = self.dp.get_pair_dataframe(
                pair=metadata['pair'], timeframe=self.informative_timeframe)

            informative = self.do_indicators(informative.copy(), metadata)

            dataframe = merge_informative_pair(dataframe,
                                               informative,
                                               self.timeframe,
                                               self.informative_timeframe,
                                               ffill=True)
            # don't overwrite the base dataframe's OHLCV information
            skip_columns = [
                (s + "_" + self.informative_timeframe)
                for s in ['date', 'open', 'high', 'low', 'close', 'volume']
            ]
            dataframe.rename(columns=lambda s: s.replace(
                "_{}".format(self.informative_timeframe), "")
                             if (not s in skip_columns) else s,
                             inplace=True)

        return dataframe
Exemple #7
0
    def slow_tf_indicators(self, dataframe: DataFrame,
                           metadata: dict) -> DataFrame:

        dataframe5m = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe="5m")

        create_ichimoku(dataframe5m,
                        conversion_line_period=355,
                        displacement=880,
                        base_line_periods=175,
                        laggin_span=175)

        dataframe5m['hma888'] = ftt.hull_moving_average(dataframe5m, 888)
        dataframe = merge_informative_pair(dataframe,
                                           dataframe5m,
                                           self.timeframe,
                                           "5m",
                                           ffill=True)
        dataframe['hma100'] = ftt.hull_moving_average(dataframe, 100)
        dataframe['ema550'] = ta.EMA(dataframe, timeperiod=550)
        dataframe['ema633'] = ta.EMA(dataframe, timeperiod=633)

        create_ichimoku(dataframe,
                        conversion_line_period=20,
                        displacement=88,
                        base_line_periods=88,
                        laggin_span=88)
        create_ichimoku(dataframe,
                        conversion_line_period=9,
                        displacement=26,
                        base_line_periods=26,
                        laggin_span=52)
        create_ichimoku(dataframe,
                        conversion_line_period=444,
                        displacement=444,
                        base_line_periods=444,
                        laggin_span=444)
        create_ichimoku(dataframe,
                        conversion_line_period=355,
                        displacement=888,
                        base_line_periods=175,
                        laggin_span=175)

        dataframe['ichimoku_ok'] = (
            (dataframe['kijun_sen_355_5m'] >= dataframe['tenkan_sen_355_5m']) &
            (dataframe['kijun_sen_20'] > dataframe['tenkan_sen_444']) &
            (dataframe['senkou_a_9'] > dataframe['senkou_a_20']) &
            (dataframe['tenkan_sen_20'] >= dataframe['kijun_sen_20']) &
            (dataframe['tenkan_sen_9'] >= dataframe['tenkan_sen_20']) &
            (dataframe['tenkan_sen_9'] >= dataframe['kijun_sen_9'])
        ).astype('int') * 4

        dataframe['trending_over'] = ((dataframe['senkou_b_355_5m'] >
                                       dataframe['close'])).astype('int') * 1

        dataframe.loc[(dataframe['ichimoku_ok'] > 0), 'trending'] = 3
        dataframe.loc[(dataframe['trending_over'] > 0), 'trending'] = 0
        dataframe['trending'].fillna(method='ffill', inplace=True)

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

        # Obelisk_Ichimoku_Slow does not use trailing stop or roi and should be safe to backtest at 5m
        # if self.config['runmode'].value in ('backtest', 'hyperopt'):
        #     assert (timeframe_to_minutes(self.timeframe) <= 5), "Backtest this strategy in 5m or 1m timeframe."

        if self.timeframe == self.informative_timeframe:
            dataframe = self.slow_tf_indicators(dataframe, metadata)
        else:
            assert self.dp, "DataProvider is required for multiple timeframes."

            informative = self.dp.get_pair_dataframe(
                pair=metadata['pair'], timeframe=self.informative_timeframe)
            informative = self.slow_tf_indicators(informative.copy(), metadata)

            dataframe = merge_informative_pair(dataframe,
                                               informative,
                                               self.timeframe,
                                               self.informative_timeframe,
                                               ffill=True)
            # don't overwrite the base dataframe's OHLCV information
            skip_columns = [
                (s + "_" + self.informative_timeframe)
                for s in ['date', 'open', 'high', 'low', 'close', 'volume']
            ]
            dataframe.rename(columns=lambda s: s.replace(
                "_{}".format(self.informative_timeframe), "")
                             if (not s in skip_columns) else s,
                             inplace=True)

        dataframe = self.fast_tf_indicators(dataframe, metadata)

        return dataframe
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        # Populate/update the trade data if there is any, set trades to false if not live/dry
        self.custom_trade_info[metadata['pair']] = self.populate_trades(
            metadata['pair'])

        if self.config['runmode'].value in ('backtest', 'hyperopt'):
            assert (timeframe_to_minutes(self.timeframe) <=
                    30), "Backtest this strategy in 5m or 1m timeframe."

        if self.timeframe == self.informative_timeframe:
            dataframe = self.do_indicators(dataframe, metadata)
        else:
            if not self.dp:
                return dataframe

            informative = self.dp.get_pair_dataframe(
                pair=metadata['pair'], timeframe=self.informative_timeframe)

            informative = self.do_indicators(informative.copy(), metadata)

            dataframe = merge_informative_pair(dataframe,
                                               informative,
                                               self.timeframe,
                                               self.informative_timeframe,
                                               ffill=True)

            skip_columns = [(s + "_" + self.informative_timeframe) for s in [
                'date', 'open', 'high', 'low', 'close', 'volume', 'emac',
                'emao'
            ]]
            dataframe.rename(columns=lambda s: s.replace(
                "_{}".format(self.informative_timeframe), "")
                             if (not s in skip_columns) else s,
                             inplace=True)

        # Slam some indicators into the trade_info dict so we can dynamic roi and custom stoploss in backtest
        if self.dp.runmode.value in ('backtest', 'hyperopt'):
            self.custom_trade_info[metadata['pair']]['roc'] = dataframe[[
                'date', 'roc'
            ]].copy().set_index('date')
            self.custom_trade_info[metadata['pair']]['atr'] = dataframe[[
                'date', 'atr'
            ]].copy().set_index('date')
            self.custom_trade_info[metadata['pair']]['sroc'] = dataframe[[
                'date', 'sroc'
            ]].copy().set_index('date')
            self.custom_trade_info[metadata['pair']]['ssl-dir'] = dataframe[[
                'date', 'ssl-dir'
            ]].copy().set_index('date')
            self.custom_trade_info[
                metadata['pair']]['rmi-up-trend'] = dataframe[[
                    'date', 'rmi-up-trend'
                ]].copy().set_index('date')
            self.custom_trade_info[
                metadata['pair']]['candle-up-trend'] = dataframe[[
                    'date', 'candle-up-trend'
                ]].copy().set_index('date')

        return dataframe
Exemple #10
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:

        # Base Thiccness
        dataframe['color'] = np.where(dataframe['close'] > dataframe['open'],
                                      'green', 'red')

        dataframe['how-thicc'] = (dataframe['close'] - dataframe['open']).abs()
        dataframe['avg-thicc'] = dataframe['how-thicc'].abs().rolling(
            36).mean()
        dataframe['not-thicc'] = dataframe['how-thicc'] < (
            dataframe['avg-thicc'])
        dataframe['rly-thicc'] = dataframe['how-thicc'] > (
            dataframe['avg-thicc'])
        dataframe['xtra-thicc'] = np.where(
            dataframe['rly-thicc'].rolling(8).sum() >= 5, 1, 0)

        dataframe['roc'] = ta.ROC(dataframe, timeperiod=6)

        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=self.inf_timeframe)
        informative['3d-low'] = informative['close'].rolling(72).min()
        informative['3d-high'] = informative['close'].rolling(72).max()

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.inf_timeframe,
                                           ffill=True)

        return dataframe
Exemple #11
0
def test_merge_informative_pair_same():
    data = generate_test_data('15m', 40)
    informative = generate_test_data('15m', 40)

    result = merge_informative_pair(data, informative, '15m', '15m', ffill=True)
    assert isinstance(result, pd.DataFrame)
    assert len(result) == len(data)
    assert 'date' in result.columns
    assert result['date'].equals(data['date'])
    assert 'date_15m' in result.columns

    assert 'open' in result.columns
    assert 'open_15m' in result.columns
    assert result['open'].equals(data['open'])

    assert 'close' in result.columns
    assert 'close_15m' in result.columns
    assert result['close'].equals(data['close'])

    assert 'volume' in result.columns
    assert 'volume_15m' in result.columns
    assert result['volume'].equals(data['volume'])

    # Dates match 1:1
    assert result['date_15m'].equals(result['date'])
Exemple #12
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        self.custom_trade_info[metadata['pair']] = self.populate_trades(
            metadata['pair'])

        dataframe['rmi-slow'] = RMI(dataframe, length=21, mom=5)
        dataframe['rmi-fast'] = RMI(dataframe, length=8, mom=4)
        dataframe['roc'] = ta.ROC(dataframe, timeperiod=6)
        dataframe['mp'] = ta.RSI(dataframe['roc'], timeperiod=6)

        dataframe['rmi-up'] = np.where(
            dataframe['rmi-slow'] >= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-dn'] = np.where(
            dataframe['rmi-slow'] <= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-up-trend'] = np.where(
            dataframe['rmi-up'].rolling(3, min_periods=1).sum() >= 2, 1, 0)
        dataframe['rmi-dn-trend'] = np.where(
            dataframe['rmi-dn'].rolling(3, min_periods=1).sum() >= 2, 1, 0)

        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=self.inf_timeframe)
        informative['rsi'] = ta.RSI(informative, timeperiod=14)
        informative['1d_high'] = informative['close'].rolling(24).max()
        informative['3d_low'] = informative['close'].rolling(72).min()
        informative['adr'] = informative['1d_high'] - informative['3d_low']

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.inf_timeframe,
                                           ffill=True)

        return dataframe
Exemple #13
0
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        # Misc. calculations regarding existing open positions (reset on every loop iteration)
        self.custom_trade_info[metadata['pair']] = trade_data = {}
        trade_data['active_trade'] = trade_data['other_trades'] = False

        if self.config['runmode'].value in ('live', 'dry_run'):
            
            active_trade = Trade.get_trades([Trade.pair == metadata['pair'], Trade.is_open.is_(True),]).all()
            other_trades = Trade.get_trades([Trade.pair != metadata['pair'], Trade.is_open.is_(True),]).all()

            if active_trade:
                current_rate = self.get_current_price(metadata['pair'])
                active_trade[0].adjust_min_max_rates(current_rate)
                trade_data['active_trade']   = True
                trade_data['current_profit'] = active_trade[0].calc_profit_ratio(current_rate)
                trade_data['peak_profit']    = active_trade[0].calc_profit_ratio(active_trade[0].max_rate)

            if other_trades:
                trade_data['other_trades'] = True
                total_other_profit = tuple(trade.calc_profit_ratio(self.get_current_price(trade.pair)) for trade in other_trades)
                trade_data['avg_other_profit'] = mean(total_other_profit) 

        self.custom_trade_info[metadata['pair']] = trade_data

        # Set up other indicators
        dataframe['volume_mean_slow'] = dataframe['volume'].rolling(window=24).mean()
        dataframe['rmi-slow'] = RMI(dataframe, length=20, mom=5)
        dataframe['rmi-fast'] = RMI(dataframe, length=9, mom=3)
        dataframe['sar'] = ta.SAR(dataframe)

        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']

        # Trend calculations
        dataframe['max'] = dataframe['high'].rolling(12).max()      
        dataframe['min'] = dataframe['low'].rolling(12).min()       
        dataframe['upper'] = np.where(dataframe['max'] > dataframe['max'].shift(),1,0)      
        dataframe['lower'] = np.where(dataframe['min'] < dataframe['min'].shift(),1,0)      
        dataframe['up_trend'] = np.where(dataframe['upper'].rolling(3, min_periods=1).sum() != 0,1,0)      
        dataframe['dn_trend'] = np.where(dataframe['lower'].rolling(3, min_periods=1).sum() != 0,1,0)

        # Informative Pair Indicators
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_timeframe)

        informative['ema3']   = ta.EMA(informative, timeperiod=3)
        informative['ema12']  = ta.EMA(informative, timeperiod=12)

        inf_macd = ta.MACD(informative)
        informative['macd'] = inf_macd['macd']
        informative['macdsignal'] = inf_macd['macdsignal']
        informative['macdhist'] = inf_macd['macdhist']

        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_timeframe, ffill=True)

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

        dataframe5m = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe="5m")

        create_ichimoku(dataframe5m,
                        conversion_line_period=355,
                        displacement=880,
                        base_line_periods=175,
                        laggin_span=175)
        dataframe = merge_informative_pair(dataframe,
                                           dataframe5m,
                                           self.timeframe,
                                           "5m",
                                           ffill=True)

        create_ichimoku(dataframe,
                        conversion_line_period=20,
                        displacement=88,
                        base_line_periods=88,
                        laggin_span=88)
        create_ichimoku(dataframe,
                        conversion_line_period=9,
                        displacement=26,
                        base_line_periods=26,
                        laggin_span=52)
        create_ichimoku(dataframe,
                        conversion_line_period=444,
                        displacement=444,
                        base_line_periods=444,
                        laggin_span=444)
        create_ichimoku(dataframe,
                        conversion_line_period=100,
                        displacement=88,
                        base_line_periods=440,
                        laggin_span=440)
        create_ichimoku(dataframe,
                        conversion_line_period=40,
                        displacement=88,
                        base_line_periods=176,
                        laggin_span=176)

        dataframe['ichimoku_ok'] = (
            (dataframe['kijun_sen_355_5m'] >= dataframe['tenkan_sen_355_5m']) &
            (dataframe['senkou_a_100'] > dataframe['senkou_b_100']) &
            (dataframe['senkou_a_20'] > dataframe['senkou_b_20']) &
            (dataframe['kijun_sen_20'] > dataframe['tenkan_sen_444']) &
            (dataframe['senkou_a_9'] > dataframe['senkou_a_20']) &
            (dataframe['tenkan_sen_20'] >= dataframe['kijun_sen_20']) &
            (dataframe['tenkan_sen_9'] >= dataframe['tenkan_sen_20']) &
            (dataframe['tenkan_sen_9'] >= dataframe['kijun_sen_9'])
        ).astype('int') * 4

        dataframe['trending_over'] = (
            (dataframe['senkou_b_444'] > dataframe['close'])).astype('int') * 1

        return dataframe
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        self.custom_trade_info[metadata['pair']] = self.populate_trades(
            metadata['pair'])

        # Relative Momentum Index
        dataframe['rmi-slow'] = RMI(dataframe, length=21, mom=5)
        dataframe['rmi-fast'] = RMI(dataframe, length=8, mom=4)

        # Momentum Pinball
        dataframe['roc'] = ta.ROC(dataframe, timeperiod=6)
        dataframe['mp'] = ta.RSI(dataframe['roc'], timeperiod=6)

        # Trend Calculations
        dataframe['rmi-up'] = np.where(
            dataframe['rmi-slow'] >= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-dn'] = np.where(
            dataframe['rmi-slow'] <= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-up-trend'] = np.where(
            dataframe['rmi-up'].rolling(3, min_periods=1).sum() >= 2, 1, 0)
        dataframe['rmi-dn-trend'] = np.where(
            dataframe['rmi-dn'].rolling(3, min_periods=1).sum() >= 2, 1, 0)

        # Informative for STAKE/FIAT and COIN/FIAT on default timeframe, only relevant if stake currency is BTC or ETH
        if self.config['stake_currency'] in ('BTC', 'ETH'):
            coin, stake = metadata['pair'].split('/')
            fiat = self.custom_fiat
            coin_fiat = f"{coin}/{fiat}"
            stake_fiat = f"{stake}/{fiat}"

            # COIN/FIAT (e.g. XLM/USD) - timeframe
            coin_fiat_tf = self.dp.get_pair_dataframe(pair=coin_fiat,
                                                      timeframe=self.timeframe)
            dataframe[f"{fiat}_rsi"] = ta.RSI(coin_fiat_tf, timeperiod=14)

            # STAKE/FIAT (e.g. BTC/USD) - inf_timeframe
            stake_fiat_tf = self.dp.get_pair_dataframe(
                pair=stake_fiat, timeframe=self.timeframe)
            stake_fiat_inf_tf = self.dp.get_pair_dataframe(
                pair=stake_fiat, timeframe=self.inf_timeframe)

            dataframe[f"{stake}_rsi"] = ta.RSI(stake_fiat_tf, timeperiod=14)
            dataframe[f"{stake}_rmi_{self.inf_timeframe}"] = RMI(
                stake_fiat_inf_tf, length=21, mom=5)

        # Informative indicators for current pair on inf_timeframe
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=self.inf_timeframe)
        informative['rsi'] = ta.RSI(informative, timeperiod=14)

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.inf_timeframe,
                                           ffill=True)

        return dataframe
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # The indicators for the 1h informative timeframe
        informative_1h = self.informative_1h_indicators(dataframe, metadata)
        dataframe = merge_informative_pair(dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True)

        # The indicators for the normal (5m) timeframe
        dataframe = self.normal_tf_indicators(dataframe, metadata)

        return dataframe
Exemple #17
0
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        # Misc calculations regarding existing open positions
        self.custom_trade_info[metadata['pair']] = trade_data = {}
        trade_data['active_trade'] = trade_data['other_trades'] = False

        if self.config['runmode'].value in ('live', 'dry_run'):
            
            active_trade = Trade.get_trades([Trade.pair == metadata['pair'], Trade.is_open.is_(True),]).all()
            other_trades = Trade.get_trades([Trade.pair != metadata['pair'], Trade.is_open.is_(True),]).all()

            if active_trade:
                trade_data['active_trade'] = True
                trade_data['current_profit'] = active_trade[0].calc_profit_ratio(rate=self.get_current_price(metadata['pair']))
                trade_data['peak_profit']    = active_trade[0].calc_profit_ratio(rate=active_trade[0].max_rate)
                trade_data['current_peak_ratio'] = (trade_data['current_profit'] / trade_data['peak_profit'])

            if other_trades:
                trade_data['other_trades'] = True
                total_other_profit = sum(trade.calc_profit_ratio(rate=self.get_current_price(trade.pair)) for trade in other_trades)
                trade_data['avg_other_profit'] = total_other_profit / len(other_trades)

        self.custom_trade_info[metadata['pair']] = trade_data

        # Set up other indicators
        dataframe['volume_mean_slow'] = dataframe['volume'].rolling(window=24).mean()
        dataframe['rmi-slow'] = RMI(dataframe, length=20, mom=5)
        dataframe['rmi-fast'] = RMI(dataframe, length=9, mom=3)
        dataframe['sar'] = ta.SAR(dataframe)

        # Trend calculations
        dataframe['max'] = dataframe['high'].rolling(12).max()      
        dataframe['min'] = dataframe['low'].rolling(12).min()       
        dataframe['upper'] = np.where(dataframe['max'] > dataframe['max'].shift(),1,0)      
        dataframe['lower'] = np.where(dataframe['min'] < dataframe['min'].shift(),1,0)      
        dataframe['up_trend'] = np.where(dataframe['upper'].rolling(3, min_periods=1).sum() != 0,1,0)      
        dataframe['dn_trend'] = np.where(dataframe['lower'].rolling(3, min_periods=1).sum() != 0,1,0)

        # Consensus dashboard based on default timeframe and informative pair
        # Example: https://www.tradingview.com/symbols/BTCUSD/technicals/
        # Code: https://github.com/freqtrade/technical/blob/master/technical/tradingview/__init__.py

        consensus = tv.SummaryConsensus(dataframe).score()
        dataframe['tv-consensus-sell'] = consensus['sell_agreement']
        dataframe['tv-consensus-buy']  = consensus['buy_agreement']

        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_timeframe)
        consensus_inf = tv.SummaryConsensus(informative).score()
        informative['tv-consensus-sell'] = consensus_inf['sell_agreement']
        informative['tv-consensus-buy']  = consensus_inf['buy_agreement']

        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_timeframe, ffill=True)

        # dataframe.to_csv('user_data/foo.csv')

        return dataframe
Exemple #18
0
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        self.custom_trade_info[metadata['pair']] = self.populate_trades(metadata['pair'])
    
        # Base timeframe indicators
        dataframe['rmi-slow'] = RMI(dataframe, length=21, mom=5)
        dataframe['rmi-fast'] = RMI(dataframe, length=8, mom=4)

        # Momentum Pinball: 
        dataframe['roc'] = ta.ROC(dataframe, timeperiod=6)
        dataframe['mp']  = ta.RSI(dataframe['roc'], timeperiod=6)
  
        # RMI Trends and Peaks
        dataframe['rmi-up'] = np.where(dataframe['rmi-slow'] >= dataframe['rmi-slow'].shift(),1,0)      
        dataframe['rmi-dn'] = np.where(dataframe['rmi-slow'] <= dataframe['rmi-slow'].shift(),1,0)      
        dataframe['rmi-up-trend'] = np.where(dataframe['rmi-up'].rolling(3, min_periods=1).sum() >= 2,1,0)      
        dataframe['rmi-dn-trend'] = np.where(dataframe['rmi-dn'].rolling(3, min_periods=1).sum() >= 2,1,0)
        dataframe['rmi-max'] = dataframe['rmi-slow'].rolling(10, min_periods=1).max()

        # See: https://github.com/freqtrade/technical/blob/master/technical/indicators/indicators.py#L1059
        # matype = vidya, src = hl2
        dataframe = PMAX(dataframe, period=10, multiplier=3, length=10, MAtype=5, src=2)

        # Other stake specific informative indicators
        # TODO: Re-evaluate the value of these informative indicators
        if self.config['stake_currency'] in ('BTC', 'ETH'):
            coin, stake = metadata['pair'].split('/')
            fiat = self.custom_fiat
            coin_fiat = f"{coin}/{fiat}"
            stake_fiat = f"{stake}/{fiat}"

            coin_fiat_tf = self.dp.get_pair_dataframe(pair=coin_fiat, timeframe=self.timeframe)
            dataframe[f"{fiat}_rsi"] = ta.RSI(coin_fiat_tf, timeperiod=14)

            stake_fiat_tf = self.dp.get_pair_dataframe(pair=stake_fiat, timeframe=self.timeframe)
            stake_fiat_inf_tf = self.dp.get_pair_dataframe(pair=stake_fiat, timeframe=self.inf_timeframe)

            dataframe[f"{stake}_rsi"] = ta.RSI(stake_fiat_tf, timeperiod=14)
            dataframe[f"{stake}_rmi_{self.inf_timeframe}"] = RMI(stake_fiat_inf_tf, length=21, mom=5)

        # Base pair informative timeframe indicators
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_timeframe)
        informative['rsi'] = ta.RSI(informative, timeperiod=14)
        
        # Get the "average day range" between the 1d high and 3d low to set up guards
        informative['1d_high'] = informative['close'].rolling(24).max()
        informative['3d_low'] = informative['close'].rolling(72).min()
        informative['adr'] = informative['1d_high'] - informative['3d_low']

        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_timeframe, ffill=True)

        dataframe.to_csv('user_data/foo.csv')

        return dataframe
Exemple #19
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        # Populate/update the trade data if there is any, set trades to false if not live/dry
        self.custom_trade_info[metadata['pair']] = self.populate_trades(
            metadata['pair'])

        # Set up primary indicators
        dataframe['rmi-slow'] = ti.RMI(dataframe, length=21, mom=5)
        dataframe['rmi-fast'] = ti.RMI(dataframe, length=8, mom=4)

        # MA Streak
        dataframe['mac'] = self.mac(dataframe, 20, 50)
        dataframe['streak'] = self.ma_streak(dataframe, period=4)

        streak = abs(int(dataframe['streak'].iloc[-1]))
        streak_back_close = dataframe['close'].shift(streak + 1)

        dataframe['streak-roc'] = 100 * (dataframe['close'] -
                                         streak_back_close) / streak_back_close

        # Percent Change Channel
        pcc = self.pcc(dataframe, period=20, mult=2)
        dataframe['pcc-lowerband'] = pcc.lowerband

        # Momentum Pinball
        dataframe['roc'] = ta.ROC(dataframe, timeperiod=1)
        dataframe['mp'] = ta.RSI(dataframe['roc'], timeperiod=3)

        # Trend Calculations
        dataframe['rmi-up'] = np.where(
            dataframe['rmi-slow'] >= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-dn'] = np.where(
            dataframe['rmi-slow'] <= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-up-trend'] = np.where(
            dataframe['rmi-up'].rolling(3, min_periods=1).sum() >= 2, 1, 0)
        dataframe['rmi-dn-trend'] = np.where(
            dataframe['rmi-dn'].rolling(3, min_periods=1).sum() >= 2, 1, 0)

        # Informative indicators for current pair on inf_timeframe
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=self.inf_timeframe)
        informative['1d_high'] = informative['close'].rolling(24).max()
        informative['3d_low'] = informative['close'].rolling(72).min()
        informative['adr'] = informative['1d_high'] - informative['3d_low']

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.inf_timeframe,
                                           ffill=True)

        return dataframe
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        # # Heikin Ashi Candles
        heikinashi = qtpylib.heikinashi(dataframe)
        dataframe['ha_open'] = heikinashi['open']
        dataframe['ha_close'] = heikinashi['close']
        dataframe['ha_high'] = heikinashi['high']
        dataframe['ha_low'] = heikinashi['low']

        # Set Up Bollinger Bands
        mid, lower = bollinger_bands(ha_typical_price(dataframe),
                                     window_size=40,
                                     num_of_std=2)
        dataframe['lower'] = lower
        dataframe['mid'] = mid

        dataframe['bbdelta'] = (mid - dataframe['lower']).abs()
        dataframe['closedelta'] = (dataframe['ha_close'] -
                                   dataframe['ha_close'].shift()).abs()
        dataframe['tail'] = (dataframe['ha_close'] - dataframe['ha_low']).abs()

        dataframe['bb_lowerband'] = dataframe['lower']
        dataframe['bb_middleband'] = dataframe['mid']

        dataframe['ema_fast'] = ta.EMA(dataframe['ha_close'], timeperiod=3)
        dataframe['ema_slow'] = ta.EMA(dataframe['ha_close'], timeperiod=50)
        dataframe['volume_mean_slow'] = dataframe['volume'].rolling(
            window=30).mean()
        dataframe['rocr'] = ta.ROCR(dataframe['ha_close'], timeperiod=28)

        rsi = ta.RSI(dataframe)
        dataframe["rsi"] = rsi
        rsi = 0.1 * (rsi - 50)
        dataframe["fisher"] = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1)

        inf_tf = '1h'

        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=inf_tf)

        inf_heikinashi = qtpylib.heikinashi(informative)

        informative['ha_close'] = inf_heikinashi['close']
        informative['rocr'] = ta.ROCR(informative['ha_close'], timeperiod=168)

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           inf_tf,
                                           ffill=True)

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

        dataframe4h = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe="4h")

        dataframe4h['hma105'] = ftt.hull_moving_average(dataframe4h, 105)
        dataframe = merge_informative_pair(dataframe,
                                           dataframe4h,
                                           self.timeframe,
                                           "4h",
                                           ffill=True)
        dataframe['hma88'] = ftt.hull_moving_average(dataframe, 88)
        dataframe['ema550'] = ta.EMA(dataframe, timeperiod=550)
        dataframe['ema633'] = ta.EMA(dataframe, timeperiod=633)

        create_ichimoku(dataframe,
                        conversion_line_period=20,
                        displacement=88,
                        base_line_periods=88,
                        laggin_span=88)
        create_ichimoku(dataframe,
                        conversion_line_period=9,
                        displacement=26,
                        base_line_periods=26,
                        laggin_span=52)
        create_ichimoku(dataframe,
                        conversion_line_period=1776,
                        displacement=880,
                        base_line_periods=880,
                        laggin_span=880)
        dataframe['ichimoku_ok'] = (
            (dataframe['kijun_sen_1776'] > dataframe['tenkan_sen_1776']) &
            (dataframe['senkou_a_20'] > dataframe['senkou_b_20']) &
            (dataframe['senkou_a_9'] > dataframe['senkou_a_20']) &
            (dataframe['tenkan_sen_20'] >= dataframe['kijun_sen_20']) &
            (dataframe['tenkan_sen_9'] >= dataframe['tenkan_sen_20']) &
            (dataframe['tenkan_sen_9'] >= dataframe['kijun_sen_9']) &
            (dataframe['hma105_4h'] < dataframe['kijun_sen_20']) &
            (dataframe['hma88'] > dataframe['hma105_4h']) &
            (dataframe['hma88'] < dataframe['tenkan_sen_9']) &
            (dataframe['close'] > dataframe['open'].shift(1))
        ).astype('int') * 4

        dataframe['trending_over'] = (
            (dataframe['hma105_4h'] > dataframe['close'])).astype('int') * 1

        dataframe.loc[(dataframe['ichimoku_ok'] > 0), 'trending'] = 3
        dataframe.loc[(dataframe['trending_over'] > 0), 'trending'] = 0
        dataframe['trending'].fillna(method='ffill', inplace=True)

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

        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=self.inf_timeframe)
        informative['30d-low'] = informative['close'].rolling(30).min()
        informative['30d-high'] = informative['close'].rolling(30).max()

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.inf_timeframe,
                                           ffill=True)

        return dataframe
Exemple #23
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        # Strategy timeframe indicators for current pair.
        dataframe['rsi'] = 14
        # Informative pairs are available in this method.
        dataframe['rsi_less'] = dataframe['rsi'] < dataframe['rsi_1h']

        # Mixing manual informative pairs with decorators.
        informative = self.dp.get_pair_dataframe('NEO/USDT', '5m')
        informative['rsi'] = 14
        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           '5m',
                                           ffill=True)

        return dataframe
Exemple #24
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:

        if self.config['runmode'].value in ('backtest', 'hyperopt'):
            assert (timeframe_to_minutes(self.timeframe) <=
                    5), "Backtest this strategy in a timeframe of 5m or less."

        assert self.dp, "DataProvider is required for multiple timeframes."

        informative = self.get_informative_indicators(dataframe, metadata)
        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.informative_timeframe,
                                           ffill=True)
        dataframe = self.get_main_indicators(dataframe, metadata)

        return dataframe
Exemple #25
0
    def merge_informative(self, informative: DataFrame,
                          dataframe: DataFrame) -> DataFrame:

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.informative_timeframe,
                                           ffill=True)

        # don't overwrite the base dataframe's HLCV information
        skip_columns = [
            (s + "_" + self.informative_timeframe)
            for s in ['date', 'open', 'high', 'low', 'close', 'volume']
        ]
        dataframe.rename(columns=lambda s: s.replace(
            "_{}".format(self.informative_timeframe), "")
                         if (not s in skip_columns) else s,
                         inplace=True)

        return dataframe
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        self.custom_trade_info[metadata['pair']] = self.populate_trades(metadata['pair'])
    
        dataframe['rmi-slow'] = RMI(dataframe, length=21, mom=5)
        dataframe['rmi-fast'] = RMI(dataframe, length=8, mom=4)
        
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
   
        dataframe['rmi-up'] = np.where(dataframe['rmi-slow'] >= dataframe['rmi-slow'].shift(),1,0)      
        dataframe['rmi-dn'] = np.where(dataframe['rmi-slow'] <= dataframe['rmi-slow'].shift(),1,0)      
        dataframe['rmi-up-trend'] = np.where(dataframe['rmi-up'].rolling(3, min_periods=1).sum() >= 2,1,0)      
        dataframe['rmi-dn-trend'] = np.where(dataframe['rmi-dn'].rolling(3, min_periods=1).sum() >= 2,1,0)

        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_timeframe)
        informative['rsi'] = ta.RSI(informative, timeperiod=14)

        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_timeframe, ffill=True)

        dataframe['bull'] = dataframe[f"rsi_{self.inf_timeframe}"].gt(60).astype('int') * 20

        return dataframe
Exemple #27
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        if not metadata['pair'] in self.custom_trade_info:
            self.custom_trade_info[metadata['pair']] = {}

        if self.timeframe == self.informative_timeframe:
            dataframe = self.coock_indicators(dataframe, metadata)
        else:
            assert self.dp, "DataProvider is required for multiple timeframes."

            informative = self.dp.get_pair_dataframe(
                pair=metadata['pair'], timeframe=self.informative_timeframe)
            informative = self.coock_indicators(informative.copy(), metadata)

            dataframe = merge_informative_pair(dataframe,
                                               informative,
                                               self.timeframe,
                                               self.informative_timeframe,
                                               ffill=True)
            # don't overwrite the base dataframe's OHLCV information
            skip_columns = [
                (s + "_" + self.informative_timeframe)
                for s in ['date', 'open', 'high', 'low', 'close', 'volume']
            ]
            dataframe.rename(columns=lambda s: s.replace(
                "_{}".format(self.informative_timeframe), "")
                             if (not s in skip_columns) else s,
                             inplace=True)

            informative_btc = self.dp.get_pair_dataframe(
                pair='BTC/USDT', timeframe=self.informative_timeframe)
            informative_btc['EWO_BTC'] = EWO(informative_btc, 10, 40)
            informative_btc['ema32_btc'] = fta.EMA(informative_btc, period=32)
            informative_btc['btc_open'] = informative_btc['open']

            dataframe = merge_informative_pair(dataframe,
                                               informative_btc,
                                               self.timeframe,
                                               self.informative_timeframe,
                                               ffill=True)
            # don't overwrite the base dataframe's OHLCV information
            skip_columns = [
                (s + "_" + self.informative_timeframe)
                for s in ['date', 'open', 'high', 'low', 'close', 'volume']
            ]
            dataframe.rename(columns=lambda s: s.replace(
                "_{}".format(self.informative_timeframe), "")
                             if (not s in skip_columns) else s,
                             inplace=True)

        dataframe['4h_high'] = dataframe['close'].rolling(48).max()
        dataframe['8h_high'] = dataframe['close'].rolling(96).max()

        if self.dp.runmode.value in ('backtest', 'hyperopt'):
            self.custom_trade_info[metadata['pair']]['EWO_BUY'] = dataframe[[
                'date', 'EWO_BUY'
            ]].copy().set_index('date')
            self.custom_trade_info[metadata['pair']]['EWO_SELL'] = dataframe[[
                'date', 'EWO_SELL'
            ]].copy().set_index('date')

        return dataframe
Exemple #28
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:
        # Populate/update the trade data if there is any, set trades to false if not live/dry
        self.custom_trade_info[metadata['pair']] = self.populate_trades(
            metadata['pair'])

        # Base timeframe indicators
        dataframe['rmi-slow'] = cta.RMI(dataframe, length=21, mom=5)
        dataframe['rmi-fast'] = cta.RMI(dataframe, length=8, mom=4)

        # Indicators for ROI and Custom Stoploss
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=24)
        dataframe['roc'] = ta.ROC(dataframe, timeperiod=9)

        # Momentum Pinball: https://www.tradingview.com/script/fBpVB1ez-Momentum-Pinball-Indicator/
        dataframe['roc-mp'] = ta.ROC(dataframe, timeperiod=6)
        dataframe['mp'] = ta.RSI(dataframe['roc-mp'], timeperiod=6)

        # Trends, Peaks and Crosses
        dataframe['rmi-up'] = np.where(
            dataframe['rmi-slow'] >= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-dn'] = np.where(
            dataframe['rmi-slow'] <= dataframe['rmi-slow'].shift(), 1, 0)
        dataframe['rmi-up-trend'] = np.where(
            dataframe['rmi-up'].rolling(3, min_periods=1).sum() >= 2, 1, 0)
        dataframe['rmi-dn-trend'] = np.where(
            dataframe['rmi-dn'].rolling(3, min_periods=1).sum() >= 2, 1, 0)

        # Base pair informative timeframe indicators
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=self.inf_timeframe)

        # Get the "average day range" between the 1d high and 3d low to set up guards
        informative['1d_high'] = informative['close'].rolling(24).max()
        informative['3d_low'] = informative['close'].rolling(72).min()
        informative['adr'] = informative['1d_high'] - informative['3d_low']

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.inf_timeframe,
                                           ffill=True)

        # Other stake specific informative indicators
        # e.g if stake is BTC and current coin is XLM (pair: XLM/BTC)
        if self.config['stake_currency'] in ('BTC', 'ETH'):
            coin, stake = metadata['pair'].split('/')
            fiat = self.custom_fiat
            coin_fiat = f"{coin}/{fiat}"
            stake_fiat = f"{stake}/{fiat}"

            # Informative COIN/FIAT e.g. XLM/USD - Base Timeframe
            coin_fiat_tf = self.dp.get_pair_dataframe(pair=coin_fiat,
                                                      timeframe=self.timeframe)
            dataframe[f"{fiat}_rmi"] = cta.RMI(coin_fiat_tf, length=21, mom=5)

            # Informative STAKE/FIAT e.g. BTC/USD - Base Timeframe
            stake_fiat_tf = self.dp.get_pair_dataframe(
                pair=stake_fiat, timeframe=self.timeframe)
            dataframe[f"{stake}_rmi"] = cta.RMI(stake_fiat_tf,
                                                length=21,
                                                mom=5)

            # Informative STAKE/FIAT e.g. BTC/USD - Informative Timeframe
            stake_fiat_inf_tf = self.dp.get_pair_dataframe(
                pair=stake_fiat, timeframe=self.inf_timeframe)
            stake_fiat_inf_tf[f"{stake}_rmi"] = cta.RMI(stake_fiat_inf_tf,
                                                        length=48,
                                                        mom=5)
            dataframe = merge_informative_pair(dataframe,
                                               stake_fiat_inf_tf,
                                               self.timeframe,
                                               self.inf_timeframe,
                                               ffill=True)

        # Informatives for BTC/STAKE if not in whitelist
        else:
            pairs = self.dp.current_whitelist()
            btc_stake = f"BTC/{self.config['stake_currency']}"
            if not btc_stake in pairs:
                # BTC/STAKE - Base Timeframe
                btc_stake_tf = self.dp.get_pair_dataframe(
                    pair=btc_stake, timeframe=self.timeframe)
                dataframe['BTC_rmi'] = cta.RMI(btc_stake_tf, length=14, mom=3)

                # BTC/STAKE - Informative Timeframe
                btc_stake_inf_tf = self.dp.get_pair_dataframe(
                    pair=btc_stake, timeframe=self.inf_timeframe)
                btc_stake_inf_tf['BTC_rmi'] = cta.RMI(btc_stake_inf_tf,
                                                      length=48,
                                                      mom=5)
                dataframe = merge_informative_pair(dataframe,
                                                   btc_stake_inf_tf,
                                                   self.timeframe,
                                                   self.inf_timeframe,
                                                   ffill=True)

        # Slam some indicators into the trade_info dict so we can dynamic roi and custom stoploss in backtest
        if self.dp.runmode.value in ('backtest', 'hyperopt'):
            self.custom_trade_info[metadata['pair']]['roc'] = dataframe[[
                'date', 'roc'
            ]].copy().set_index('date')
            self.custom_trade_info[metadata['pair']]['atr'] = dataframe[[
                'date', 'atr'
            ]].copy().set_index('date')
            self.custom_trade_info[metadata['pair']]['rmi-slow'] = dataframe[[
                'date', 'rmi-slow'
            ]].copy().set_index('date')
            self.custom_trade_info[
                metadata['pair']]['rmi-up-trend'] = dataframe[[
                    'date', 'rmi-up-trend'
                ]].copy().set_index('date')

        return dataframe
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        buy_params = self.get_pair_params(metadata['pair'], 'buy')
        sell_params = self.get_pair_params(metadata['pair'], 'sell')

        self.custom_trade_info[metadata['pair']] = self.populate_trades(metadata['pair'])
    
        # Base timeframe indicators
        dataframe['rmi-slow'] = cta.RMI(dataframe, length=21, mom=5)
        dataframe['rmi-fast'] = cta.RMI(dataframe, length=8, mom=4)

        # Momentum Pinball: https://www.tradingview.com/script/fBpVB1ez-Momentum-Pinball-Indicator/
        dataframe['roc'] = ta.ROC(dataframe, timeperiod=6)
        dataframe['mp']  = ta.RSI(dataframe['roc'], timeperiod=6)
  
        # RMI Trends and Peaks
        dataframe['rmi-up'] = np.where(dataframe['rmi-slow'] >= dataframe['rmi-slow'].shift(),1,0)      
        dataframe['rmi-dn'] = np.where(dataframe['rmi-slow'] <= dataframe['rmi-slow'].shift(),1,0)      
        dataframe['rmi-up-trend'] = np.where(dataframe['rmi-up'].rolling(3, min_periods=1).sum() >= 2,1,0)      
        dataframe['rmi-dn-trend'] = np.where(dataframe['rmi-dn'].rolling(3, min_periods=1).sum() >= 2,1,0)
        dataframe['rmi-max'] = dataframe['rmi-slow'].rolling(10, min_periods=1).max()

        # Fibonacci Retracements
        dataframe['fib-ret'] = cta.fib_ret(dataframe)

        # PMAX
        # matype = ema, src = hl2
        # pmax is really slow, only enable it if its actually being used.
        if buy_params['base-pmax-enable'] == True or sell_params['sell-pmax-enable'] == True:
            atr, ma, pmax, pm_loc = cta.PMAX(dataframe, period=10, multiplier=3, length=12, MAtype=1, src=2)
            dataframe['pmax-trend'] = pm_loc
        else: 
            dataframe['pmax-trend'] = False

        # Other stake specific informative indicators
        # e.g if stake is BTC and current coin is XLM (pair: XLM/BTC)
        # TODO: Re-evaluate the value of these informative indicators
        if self.config['stake_currency'] in ('BTC', 'ETH'):
            coin, stake = metadata['pair'].split('/')
            fiat = self.custom_fiat
            coin_fiat = f"{coin}/{fiat}"
            stake_fiat = f"{stake}/{fiat}"

            # Informative COIN/FIAT e.g. XLM/USD
            coin_fiat_tf = self.dp.get_pair_dataframe(pair=coin_fiat, timeframe=self.timeframe)
            dataframe[f"{fiat}_rsi"] = ta.RSI(coin_fiat_tf, timeperiod=14)

            # Informative STAKE/FIAT e.g. BTC/USD
            stake_fiat_tf = self.dp.get_pair_dataframe(pair=stake_fiat, timeframe=self.timeframe)
            stake_fiat_inf_tf = self.dp.get_pair_dataframe(pair=stake_fiat, timeframe=self.inf_timeframe)

            dataframe[f"{stake}_rsi"] = ta.RSI(stake_fiat_tf, timeperiod=14)
            dataframe[f"{stake}_rmi_{self.inf_timeframe}"] = cta.RMI(stake_fiat_inf_tf, length=21, mom=5)

        # Base pair informative timeframe indicators
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_timeframe)
        informative['rsi'] = ta.RSI(informative, timeperiod=14)
        
        # Get the "average day range" between the 1d high and 3d low to set up guards
        informative['1d_high'] = informative['close'].rolling(24).max()
        informative['3d_low'] = informative['close'].rolling(72).min()
        informative['adr'] = informative['1d_high'] - informative['3d_low']

        informative['fib-ret'] = cta.fib_ret(informative)

        dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_timeframe, ffill=True)

        return dataframe
Exemple #30
0
    def populate_indicators(self, dataframe: DataFrame,
                            metadata: dict) -> DataFrame:

        # Misc. calculations regarding existing open positions (reset on every loop iteration)
        self.custom_trade_info[metadata['pair']] = trade_data = {}
        trade_data['active_trade'] = trade_data['other_trades'] = False

        if self.config['runmode'].value in ('live', 'dry_run'):

            active_trade = Trade.get_trades([
                Trade.pair == metadata['pair'],
                Trade.is_open.is_(True),
            ]).all()
            other_trades = Trade.get_trades([
                Trade.pair != metadata['pair'],
                Trade.is_open.is_(True),
            ]).all()

            if active_trade:
                current_rate = self.get_current_price(metadata['pair'])
                active_trade[0].adjust_min_max_rates(current_rate)
                trade_data['active_trade'] = True
                trade_data['current_profit'] = active_trade[
                    0].calc_profit_ratio(current_rate)
                trade_data['peak_profit'] = active_trade[0].calc_profit_ratio(
                    active_trade[0].max_rate)

            if other_trades:
                trade_data['other_trades'] = True
                total_other_profit = tuple(
                    trade.calc_profit_ratio(self.get_current_price(trade.pair))
                    for trade in other_trades)
                trade_data['avg_other_profit'] = mean(total_other_profit)

        self.custom_trade_info[metadata['pair']] = trade_data

        # Set up Bollinger Bands
        mid, lower = bollinger_bands(dataframe['close'],
                                     window_size=40,
                                     num_of_std=2)
        dataframe['lower'] = lower
        dataframe['bbdelta'] = (mid - dataframe['lower']).abs()
        dataframe['closedelta'] = (dataframe['close'] -
                                   dataframe['close'].shift()).abs()
        dataframe['tail'] = (dataframe['close'] - dataframe['low']).abs()

        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe),
                                            window=20,
                                            stds=2)
        dataframe['bb-lowerband'] = bollinger['lower']
        dataframe['bb-middleband'] = bollinger['mid']

        # Set up other indicators
        dataframe['volume-mean-slow'] = dataframe['volume'].rolling(
            window=24).mean()
        dataframe['rmi-slow'] = RMI(dataframe, length=20, mom=5)
        dataframe['rmi-fast'] = RMI(dataframe, length=9, mom=3)
        dataframe['rocr'] = ta.ROCR(dataframe, timeperiod=28)
        dataframe['ema-slow'] = ta.EMA(dataframe, timeperiod=50)

        # Trend Calculations
        dataframe['max'] = dataframe['high'].rolling(12).max()
        dataframe['min'] = dataframe['low'].rolling(12).min()
        dataframe['upper'] = np.where(
            dataframe['max'] > dataframe['max'].shift(), 1, 0)
        dataframe['lower'] = np.where(
            dataframe['min'] < dataframe['min'].shift(), 1, 0)
        dataframe['up_trend'] = np.where(
            dataframe['upper'].rolling(3, min_periods=1).sum() != 0, 1, 0)
        dataframe['dn_trend'] = np.where(
            dataframe['lower'].rolling(3, min_periods=1).sum() != 0, 1, 0)

        # Informative Pair Indicators
        informative = self.dp.get_pair_dataframe(pair=metadata['pair'],
                                                 timeframe=self.inf_timeframe)
        informative['rocr'] = ta.ROCR(informative, timeperiod=168)

        dataframe = merge_informative_pair(dataframe,
                                           informative,
                                           self.timeframe,
                                           self.inf_timeframe,
                                           ffill=True)

        return dataframe