def pcc(self): return cta.pcc(self.candles, period=20, mult=2, sequential=False)
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: if not metadata['pair'] in self.custom_trade_info: self.custom_trade_info[metadata['pair']] = {} ## Base Timeframe / Pair dataframe['kama'] = ta.KAMA(dataframe, length=233) # RMI: https://www.tradingview.com/script/kwIt9OgQ-Relative-Momentum-Index/ dataframe['rmi'] = cta.RMI(dataframe, length=24, mom=5) # Momentum Pinball: https://www.tradingview.com/script/fBpVB1ez-Momentum-Pinball-Indicator/ dataframe['roc-mp'] = ta.ROC(dataframe, timeperiod=1) dataframe['mp'] = ta.RSI(dataframe['roc-mp'], timeperiod=3) # MA Streak: https://www.tradingview.com/script/Yq1z7cIv-MA-Streak-Can-Show-When-a-Run-Is-Getting-Long-in-the-Tooth/ dataframe['mastreak'] = cta.mastreak(dataframe, period=4) # Percent Change Channel: https://www.tradingview.com/script/6wwAWXA1-MA-Streak-Change-Channel/ upper, mid, lower = cta.pcc(dataframe, period=40, mult=3) dataframe['pcc-lowerband'] = lower dataframe['pcc-upperband'] = upper lookup_idxs = dataframe.index.values - ( abs(dataframe['mastreak'].values) + 1) valid_lookups = lookup_idxs >= 0 dataframe['sbc'] = np.nan dataframe.loc[valid_lookups, 'sbc'] = dataframe['close'].to_numpy()[ lookup_idxs[valid_lookups].astype(int)] dataframe['streak-roc'] = 100 * (dataframe['close'] - dataframe['sbc']) / dataframe['sbc'] # Trends, Peaks and Crosses dataframe['candle-up'] = np.where( dataframe['close'] >= dataframe['close'].shift(), 1, 0) dataframe['candle-up-trend'] = np.where( dataframe['candle-up'].rolling(5).sum() >= 3, 1, 0) dataframe['rmi-up'] = np.where( dataframe['rmi'] >= dataframe['rmi'].shift(), 1, 0) dataframe['rmi-up-trend'] = np.where( dataframe['rmi-up'].rolling(5).sum() >= 3, 1, 0) dataframe['rmi-dn'] = np.where( dataframe['rmi'] <= dataframe['rmi'].shift(), 1, 0) dataframe['rmi-dn-count'] = dataframe['rmi-dn'].rolling(8).sum() dataframe['streak-bo'] = np.where( dataframe['streak-roc'] < dataframe['pcc-lowerband'], 1, 0) dataframe['streak-bo-count'] = dataframe['streak-bo'].rolling(8).sum() # Indicators used only for ROI and Custom Stoploss ssldown, sslup = cta.SSLChannels_ATR(dataframe, length=21) dataframe['sroc'] = cta.SROC(dataframe, roclen=21, emalen=13, smooth=21) dataframe['ssl-dir'] = np.where(sslup > ssldown, 'up', 'down') # 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 1d low to set up guards informative['1d-high'] = informative['close'].rolling(24).max() informative['1d-low'] = informative['close'].rolling(24).min() informative['adr'] = informative['1d-high'] - informative['1d-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=55, 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=55, mom=5) # 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: self.custom_btc_inf = True # 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=55, mom=5) dataframe['BTC_close'] = btc_stake_tf['close'] dataframe['BTC_kama'] = ta.KAMA(btc_stake_tf, length=144) # 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']]['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