# --- Do not remove these libs --- import freqtrade.vendor.qtpylib.indicators as qtpylib import numpy as np # -------------------------------- import talib.abstract as ta from freqtrade.strategy import IStrategy, merge_informative_pair from pandas import DataFrame # The main idea is to entry only when overall uptrend in higher informative # but in local dip cause BinCluc some king of pullback strategy. def bollinger_bands(stock_price, window_size, num_of_std): rolling_mean = stock_price.rolling(window=window_size).mean() rolling_std = stock_price.rolling(window=window_size).std() lower_band = rolling_mean - rolling_std * num_of_std return (np.nan_to_num(rolling_mean), np.nan_to_num(lower_band)) def SSLChannels(dataframe, length=7): df = dataframe.copy() df['ATR'] = ta.ATR(df, timeperiod=14) df['smaHigh'] = df['high'].rolling(length).mean() + df['ATR'] df['smaLow'] = df['low'].rolling(length).mean() - df['ATR'] df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN)) df['hlv'] = df['hlv'].ffill() df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow']) df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh']) return (df['sslDown'], df['sslUp']) class CombinedBinHAndClucV2(IStrategy): INTERFACE_VERSION = 3 minimal_roi = {'120': 0.01, '60': 0.02, '30': 0.05, '0': 0.1} informative_timeframe = '1h' timeframe = '5m' stoploss = -0.05 use_exit_signal = True exit_profit_only = False ignore_roi_if_entry_signal = True protections = [{'method': 'StoplossGuard', 'lookback_period_candles': 24, 'trade_limit': 2, 'stop_duration_candles': 12, 'only_per_pair': True}] startup_candle_count = 200 def informative_pairs(self): pairs = self.dp.current_whitelist() informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] return informative_pairs @staticmethod def get_informative_indicators(dataframe: DataFrame, metadata: dict): ssl_down, ssl_up = SSLChannels(dataframe, 25) dataframe['ssl_down'] = ssl_down dataframe['ssl_up'] = ssl_up dataframe['ssl_high'] = (ssl_up > ssl_down).astype('int') * 3 dataframe['mfi'] = ta.MFI(dataframe, timeperiod=30) stoch = ta.STOCHRSI(dataframe, 30, 35, 2, 2) dataframe['srsi_fk'] = stoch['fastk'] dataframe['srsi_fd'] = stoch['fastd'] # dataframe['rsi'] = ta.RSI(dataframe, timeperiod=3) dataframe['go_long'] = ((dataframe['ssl_high'] > 0) & (dataframe['mfi'].shift().rolling(3).mean() > dataframe['mfi']) & (dataframe['srsi_fk'].shift().rolling(3).mean() > dataframe['srsi_fk'])).astype('int') * 4 return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: if not self.dp: return dataframe informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe) informative = self.get_informative_indicators(informative.copy(), metadata) 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) typical_price = qtpylib.typical_price(dataframe) # strategy BinHV45 bollinger_b = qtpylib.bollinger_bands(typical_price, window=40, stds=2) mid = bollinger_b['mid'] lower = bollinger_b['lower'] dataframe['lower'] = lower dataframe['bbdelta'] = (mid - dataframe['lower']).abs() dataframe['closedelta'] = (dataframe['close'] - dataframe['close'].shift()).abs() dataframe['tail'] = (dataframe['close'] - dataframe['low']).abs() # strategy ClucMay72018 bollinger_c = qtpylib.bollinger_bands(typical_price, window=20, stds=2) dataframe['bb_lowerband'] = bollinger_c['lower'] dataframe['bb_middleband'] = bollinger_c['mid'] dataframe['bb_upperband'] = bollinger_c['upper'] dataframe['ema_slow'] = ta.EMA(dataframe, timeperiod=50) dataframe['volume_mean_slow'] = dataframe['volume'].rolling(window=30).mean() return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # strategy BinHV45 # strategy ClucMay72018 dataframe.loc[(dataframe['go_long'] > 0) & (dataframe['lower'].shift().gt(0) & dataframe['bbdelta'].gt(dataframe['close'] * 0.008) & dataframe['closedelta'].gt(dataframe['close'] * 0.0175) & dataframe['tail'].lt(dataframe['bbdelta'] * 0.25) & dataframe['close'].lt(dataframe['lower'].shift()) & dataframe['close'].le(dataframe['close'].shift()) | (dataframe['close'] < dataframe['ema_slow']) & (dataframe['close'] < 0.985 * dataframe['bb_lowerband']) & (dataframe['volume'] < dataframe['volume_mean_slow'].shift(1) * 20)), 'enter_long'] = 1 return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ """ dataframe.loc[qtpylib.crossed_below(dataframe['close'], dataframe['bb_upperband']), 'exit_long'] = 1 return dataframe