DISCLAIMER
The codes in this post is just for educational purpose, and not to be used on live trading
Let’s say you want to exit a trade when the rsi enter overbought area, because you aren’t sure that the price will keep going up, then you can use custom_exit
to do it. First, you need to calculate rsi in populate_indicators
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['ema_9'] = ta.EMA(dataframe, 9) dataframe['ema_20'] = ta.EMA(dataframe, 20) dataframe['rsi'] = ta.RSI(dataframe, 14) return dataframe
Then you need to write custom_exit
lines. For this example, we tell the bot to exit on overbought rsi only when the profit above or equal 0. But similar to tsl example, since we want to make the code backtest-able, we tied the profit to last candle’s close.
def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> Optional[Union[str, bool]]: if ((current_time - timedelta(minutes=15)) >= trade.open_date_utc): dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) current_candle = dataframe.iloc[-1].squeeze() current_profit = trade.calc_profit_ratio(current_candle['close']) if (current_profit >= 0): if (current_candle['rsi'] >= 70): return "rsi_overbought"
The full code will look like below. Don’t forget to copy the import lines, since there are new imports.
from freqtrade.strategy import IStrategy from pandas import DataFrame import freqtrade.vendor.qtpylib.indicators as qtpylib import talib.abstract as ta from freqtrade.persistence import Trade from datetime import datetime, timedelta from typing import Optional, Union class strat_template (IStrategy): def version(self) -> str: return "template-v1" INTERFACE_VERSION = 3 minimal_roi = { "0": 0.05 } stoploss = -0.05 timeframe = '15m' process_only_new_candles = True startup_candle_count = 999 use_custom_stoploss = True def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> float: sl_new = 1 if (current_time - timedelta(minutes=15) >= trade.open_date_utc): dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) current_candle = dataframe.iloc[-1].squeeze() current_profit = trade.calc_profit_ratio(current_candle['close']) if (current_profit >= 0.03): sl_new = 0.01 return sl_new def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float, current_profit: float, **kwargs) -> Optional[Union[str, bool]]: if ((current_time - timedelta(minutes=15)) >= trade.open_date_utc): dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) current_candle = dataframe.iloc[-1].squeeze() current_profit = trade.calc_profit_ratio(current_candle['close']) if (current_profit >= 0): if (current_candle['rsi'] >= 70): return "rsi_overbought" def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['ema_9'] = ta.EMA(dataframe, 9) dataframe['ema_20'] = ta.EMA(dataframe, 20) dataframe['rsi'] = ta.RSI(dataframe, 14) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ qtpylib.crossed_above(dataframe['ema_9'], dataframe['ema_20']) & (dataframe['volume'] > 0) , ['enter_long', 'enter_tag'] ] = (1, 'golden cross') return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe.loc[ qtpylib.crossed_below(dataframe['ema_9'], dataframe['ema_20']) & (dataframe['volume'] > 0) , ['exit_long', 'exit_tag'] ] = (1, 'death cross') return dataframe
[…] Previous – Create moving average cross strategy Next – Custom exit […]
[…] Previous – Custom exit Next […]
[…] Custom exit […]