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)
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
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
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
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
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
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
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'])
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
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
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
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
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
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
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
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
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
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
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