DISCLAIMER
The codes in this post is just for educational purpose, and not to be used on live trading
Sometimes, there are times when a trade almost reach your roi level, but then it stop rise up and start to go down and ends up triggering stoploss. That’s where trailing stoploss (I’m gonna refer to it as tsl
throughout this article) helps you. You can see minimal roi as the preferred profit target, and tsl as a minimum profit target. For example, let’s see this code
minimal_roi = { "0": 0.05 } trailing_stop = True trailing_stop_positive = 0.01 trailing_stop_positive_offset = 0.03 trailing_only_offset_is_reached = True
5% is the preferred profit target. But you set the minimum profit target at (around) 3-1 = 2%
profit target. Of course the profit have to at least reached 3% before the trailing activated and the 2% profit locked in.
The issue with the code above is it introduced backtest trap. You can read it more here. So personally, I prefer using custom_stoploss
function, which look like the code below
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
The code above will make sure the tsl is backtest-able. The tsl will only start to be checked once the trade duration past the open candle (in this case 15 mins), and current_profit
is tied to last candle’s close value. The full code will look like this (don’t forget to copy the import lines, because there are new import lines)
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 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 populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: dataframe['ema_9'] = ta.EMA(dataframe, 9) dataframe['ema_20'] = ta.EMA(dataframe, 20) 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 – Basic Template of a Strategy Next – Trailing stoploss […]
[…] Previous – Trailing stoploss Next […]
[…] Trailing stoploss […]