import datetime from datetime import datetime from functools import reduce import freqtrade.vendor.qtpylib.indicators as qtpylib import talib.abstract as ta from freqtrade.persistence import Trade from freqtrade.strategy import DecimalParameter, IntParameter from freqtrade.strategy.interface import IStrategy from pandas import DataFrame buy_params = { "base_nb_candles_buy": 8, "ewo_high": 4.179, "ewo_low": -16.917, "ewo_high_2": -2.609, # value loaded from strategy "low_offset": 0.986, # value loaded from strategy "low_offset_2": 0.944, # value loaded from strategy "rsi_buy": 58, # value loaded from strategy } sell_params = { "base_nb_candles_sell": 16, "high_offset": 1.054, "high_offset_2": 1.018, # value loaded from strategy } def EWO(dataframe, ema_length=5, ema2_length=35): df = dataframe.copy() ema1 = ta.EMA(df, timeperiod=ema_length) ema2 = ta.EMA(df, timeperiod=ema2_length) emadif = (ema1 - ema2) / df["low"] * 100 return emadif class NotAnotherSMAOffsetStrategyHOv3_b_interface_v3(IStrategy): INTERFACE_VERSION = 3 minimal_roi = { "0": 10 } stoploss = -0.3 base_nb_candles_buy = IntParameter( 2, 20, default=buy_params["base_nb_candles_buy"], space="buy", optimize=False ) base_nb_candles_sell = IntParameter( 10, 40, default=sell_params["base_nb_candles_sell"], space="sell", optimize=False, ) low_offset = DecimalParameter( 0.9, 0.99, default=buy_params["low_offset"], space="buy", optimize=False ) low_offset_2 = DecimalParameter( 0.9, 0.99, default=buy_params["low_offset_2"], space="buy", optimize=False ) high_offset = DecimalParameter( 0.95, 1.1, default=sell_params["high_offset"], space="sell", optimize=False ) high_offset_2 = DecimalParameter( 0.99, 1.5, default=sell_params["high_offset_2"], space="sell", optimize=False ) fast_ewo = 50 slow_ewo = 200 ewo_low = DecimalParameter( -20.0, -8.0, default=buy_params["ewo_low"], space="buy", optimize=False ) ewo_high = DecimalParameter( 2.0, 12.0, default=buy_params["ewo_high"], space="buy", optimize=False ) ewo_high_2 = DecimalParameter( -6.0, 12.0, default=buy_params["ewo_high_2"], space="buy", optimize=False ) rsi_buy = IntParameter( 30, 70, default=buy_params["rsi_buy"], space="buy", optimize=True ) trailing_stop = True trailing_stop_positive = 0.005 trailing_stop_positive_offset = 0.025 trailing_only_offset_is_reached = True use_exit_signal = True exit_profit_only = False exit_profit_offset = 0.01 ignore_roi_if_entry_signal = False order_time_in_force = {"entry": "gtc", "exit": "ioc"} timeframe = "5m" inf_1h = "1h" process_only_new_candles = True startup_candle_count = 200 use_custom_stoploss = False plot_config = { "main_plot": { "ma_buy": {"color": "orange"}, "ma_sell": {"color": "orange"}, }, } slippage_protection = {"retries": 3, "max_slippage": -0.02} buy_signals = {} def confirm_trade_exit( self, pair: str, trade: Trade, order_type: str, amount: float, rate: float, time_in_force: str, exit_reason: str, current_time: datetime, **kwargs, ) -> bool: dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1] if last_candle is not None: if exit_reason in ["exit_signal"]: if ( last_candle["hma_50"] * 1.149 > last_candle["ema_100"] and last_candle["close"] < last_candle["ema_100"] * 0.951 ): # *1.2 return False try: state = self.slippage_protection["__pair_retries"] except KeyError: state = self.slippage_protection["__pair_retries"] = {} candle = dataframe.iloc[-1].squeeze() slippage = rate / candle["close"] - 1 if slippage < self.slippage_protection["max_slippage"]: pair_retries = state.get(pair, 0) if pair_retries < self.slippage_protection["retries"]: state[pair] = pair_retries + 1 return False state[pair] = 0 return True def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: for val in self.base_nb_candles_buy.range: dataframe[f"ma_buy_{val}"] = ta.EMA(dataframe, timeperiod=val) for val in self.base_nb_candles_sell.range: dataframe[f"ma_sell_{val}"] = ta.EMA(dataframe, timeperiod=val) dataframe["hma_50"] = qtpylib.hull_moving_average(dataframe["close"], window=50) dataframe["ema_100"] = ta.EMA(dataframe, timeperiod=100) dataframe["sma_9"] = ta.SMA(dataframe, timeperiod=9) dataframe["EWO"] = EWO(dataframe, self.fast_ewo, self.slow_ewo) dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) dataframe["rsi_fast"] = ta.RSI(dataframe, timeperiod=4) dataframe["rsi_slow"] = ta.RSI(dataframe, timeperiod=20) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ (dataframe["rsi_fast"] < 35) & ( dataframe["close"] < dataframe[f"ma_buy_{self.base_nb_candles_buy.value}"] * self.low_offset.value ) & (dataframe["EWO"] > self.ewo_high.value) & (dataframe["rsi"] < self.rsi_buy.value) & (dataframe["volume"] > 0) & ( dataframe["close"] < dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] * self.high_offset.value ), ["enter_long", "enter_tag"], ] = (1, "ewo1") dataframe.loc[ (dataframe["rsi_fast"] < 35) & ( dataframe["close"] < dataframe[f"ma_buy_{self.base_nb_candles_buy.value}"] * self.low_offset_2.value ) & (dataframe["EWO"] > self.ewo_high_2.value) & (dataframe["rsi"] < self.rsi_buy.value) & (dataframe["volume"] > 0) & ( dataframe["close"] < dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] * self.high_offset.value ) & (dataframe["rsi"] < 25), ["enter_long", "enter_tag"], ] = (1, "ewo2") dataframe.loc[ (dataframe["rsi_fast"] < 35) & ( dataframe["close"] < dataframe[f"ma_buy_{self.base_nb_candles_buy.value}"] * self.low_offset.value ) & (dataframe["EWO"] < self.ewo_low.value) & (dataframe["volume"] > 0) & ( dataframe["close"] < dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] * self.high_offset.value ), ["enter_long", "enter_tag"], ] = (1, "ewolow") return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: conditions = [] conditions.append( (dataframe["close"] > dataframe["sma_9"]) & ( dataframe["close"] > dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] * self.high_offset_2.value ) & (dataframe["rsi"] > 50) & (dataframe["volume"] > 0) & (dataframe["rsi_fast"] > dataframe["rsi_slow"]) | (dataframe["close"] < dataframe["hma_50"]) & ( dataframe["close"] > dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] * self.high_offset.value ) & (dataframe["volume"] > 0) & (dataframe["rsi_fast"] > dataframe["rsi_slow"]) ) if conditions: dataframe.loc[reduce(lambda x, y: x | y, conditions), "exit_long"] = 1 return dataframe