from datetime import datetime from freqtrade.strategy import DecimalParameter, stoploss_from_open from freqtrade.strategy.interface import IStrategy from pandas import DataFrame import freqtrade.vendor.qtpylib.indicators as qtpylib import pandas_ta as pta import talib.abstract as ta TMP_HOLD = [] def VWAPB(dataframe, window_size=20, num_of_std=1): df = dataframe.copy() df['vwap'] = qtpylib.rolling_vwap(df,window=window_size) rolling_std = df['vwap'].rolling(window=window_size).std() df['vwap_low'] = df['vwap'] - (rolling_std * num_of_std) df['vwap_high'] = df['vwap'] + (rolling_std * num_of_std) return df['vwap_low'], df['vwap'], df['vwap_high'] def top_percent_change(dataframe: DataFrame, length: int) -> float: """ Percentage change of the current close from the range maximum Open price :param dataframe: DataFrame The original OHLC dataframe :param length: int The length to look back """ if length == 0: return (dataframe['open'] - dataframe['close']) / dataframe['close'] else: return (dataframe['open'].rolling(length).max() - dataframe['close']) / dataframe['close'] class VWAP_1(IStrategy): """ modified from https://github.com/jilv220/freqtrade-stuff/blob/main/VWAP.py @author jilv220 """ sell_params = { "pHSL": -0.15, "pPF_1": 0.02, "pPF_2": 0.05, "pSL_1": 0.02, "pSL_2": 0.04 } minimal_roi = { "0": 100 } stoploss = -0.99 timeframe = '5m' use_custom_stoploss = True process_only_new_candles = False startup_candle_count = 120 order_types = { 'buy': 'limit', 'sell': 'limit', 'emergencysell': 'limit', 'forcebuy': "limit", 'forcesell': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': False, 'stoploss_on_exchange_interval': 60, 'stoploss_on_exchange_limit_ratio': 0.99 } pHSL = DecimalParameter(-0.200, -0.040, default=-0.08, decimals=3, space='sell', load=True) pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', load=True) pSL_1 = DecimalParameter(0.008, 0.020, default=0.011, decimals=3, space='sell', load=True) pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', load=True) pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', load=True) def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: HSL = self.pHSL.value PF_1 = self.pPF_1.value SL_1 = self.pSL_1.value PF_2 = self.pPF_2.value SL_2 = self.pSL_2.value if current_profit > PF_2: sl_profit = SL_2 + (current_profit - PF_2) elif current_profit > PF_1: sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1)) else: sl_profit = HSL if sl_profit >= current_profit: return -0.99 return stoploss_from_open(sl_profit, current_profit) def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, current_profit: float, **kwargs): dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1].squeeze() previous_candle_1 = dataframe.iloc[-2].squeeze() if current_profit >= 0.02: return None if current_profit < 0.02: if ( (last_candle['close'] > last_candle['bb_middleband']) ): if trade.id not in TMP_HOLD: TMP_HOLD.append(trade.id) return None for i in TMP_HOLD: if trade.id == i and (last_candle["close"] < last_candle["bb_middleband"]): if previous_candle_1["close"] < previous_candle_1["bb_middleband"]: TMP_HOLD.remove(i) return "sell_drop_bb_mid" if trade.id == i: if ( (current_profit < 0.02) and (last_candle['rsi'] > 65) and (last_candle['close'] < previous_candle_1['close']) ): TMP_HOLD.remove(i) return "rsi_sell" def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: vwap_low, vwap, vwap_high = VWAPB(dataframe, 20, 1) dataframe['vwap_low'] = vwap_low dataframe['tcp_percent_4'] = top_percent_change(dataframe, 4) dataframe['cti'] = pta.cti(dataframe["close"], length=20) dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) dataframe['rsi_84'] = ta.RSI(dataframe, timeperiod=84) dataframe['rsi_112'] = ta.RSI(dataframe, timeperiod=112) bollinger = qtpylib.bollinger_bands(dataframe['close'], window=20, stds=2) dataframe['bb_lowerband'] = bollinger['lower'] dataframe['bb_upperband'] = bollinger['upper'] dataframe['bb_middleband'] = bollinger['mid'] return dataframe def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[:, 'buy_tag'] = 'vwap' dataframe.loc[ ( (dataframe['close'] < dataframe['vwap_low']) & (dataframe['tcp_percent_4'] > 0.04) & (dataframe['cti'] < -0.8) & (dataframe['rsi'] < 35) & (dataframe['rsi_84'] < 60) & (dataframe['rsi_112'] < 60) & (dataframe['volume'] > 0) ), 'buy'] = 1 return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[(), 'sell'] = 1 return dataframe