diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index c77b59788..d4db1c737 100644 --- a/docs/strategy-customization.md +++ b/docs/strategy-customization.md @@ -927,13 +927,14 @@ In some situations it may be confusing to deal with stops relative to current ra ??? Example "Returning a stoploss using absolute price from the custom stoploss function" - If we want to trail a stop price at 2xATR below current price we can call `stoploss_from_absolute(current_rate - (candle['atr'] * 2), current_rate, is_short=trade.is_short)`. + If we want to trail a stop price at 2xATR below current price we can call `stoploss_from_absolute(current_rate + (side * candle['atr'] * 2), current_rate, is_short=trade.is_short, leverage=trade.leverage)`. + For futures, we need to adjust the direction (up or down), as well as adjust for leverage, since the [`custom_stoploss`](strategy-callbacks.md#custom-stoploss) callback returns the ["risk for this trade"](stoploss.md#stoploss-and-leverage) - not the relative price movement. ``` python from datetime import datetime from freqtrade.persistence import Trade - from freqtrade.strategy import IStrategy, stoploss_from_absolute + from freqtrade.strategy import IStrategy, stoploss_from_absolute, timeframe_to_prev_date class AwesomeStrategy(IStrategy): @@ -947,8 +948,12 @@ In some situations it may be confusing to deal with stops relative to current ra current_rate: float, current_profit: float, after_fill: bool, **kwargs) -> Optional[float]: dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) + trade_date = timeframe_to_prev_date(self.timeframe, trade.open_date_utc) candle = dataframe.iloc[-1].squeeze() - return stoploss_from_absolute(current_rate - (candle['atr'] * 2), current_rate, is_short=trade.is_short) + sign = 1 if trade.is_short else -1 + return stoploss_from_absolute(current_rate + (side * candle['atr'] * 2), + current_rate, is_short=trade.is_short, + leverage=trade.leverage) ``` diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index 0af901bb3..d4d5f0068 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -317,7 +317,7 @@ After: if current_profit > 0.10: return stoploss_from_open(0.07, current_profit, is_short=trade.is_short) - return stoploss_from_absolute(current_rate - (candle['atr'] * 2), current_rate, is_short=trade.is_short) + return stoploss_from_absolute(current_rate - (candle['atr'] * 2), current_rate, is_short=trade.is_short, leverage=trade.leverage) ``` diff --git a/freqtrade/strategy/strategy_helper.py b/freqtrade/strategy/strategy_helper.py index 27ebe7e69..f47e1db45 100644 --- a/freqtrade/strategy/strategy_helper.py +++ b/freqtrade/strategy/strategy_helper.py @@ -123,7 +123,8 @@ def stoploss_from_open( return max(stoploss * leverage, 0.0) -def stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool = False) -> float: +def stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool = False, + leverage: float = 1.0) -> float: """ Given current price and desired stop price, return a stop loss value that is relative to current price. @@ -136,6 +137,7 @@ def stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool :param stop_rate: Stop loss price. :param current_rate: Current asset price. :param is_short: When true, perform the calculation for short instead of long + :param leverage: Leverage to use for the calculation :return: Positive stop loss value relative to current price """ @@ -150,4 +152,4 @@ def stoploss_from_absolute(stop_rate: float, current_rate: float, is_short: bool # negative stoploss values indicate the requested stop price is higher/lower # (long/short) than the current price # shorts can yield stoploss values higher than 1, so limit that as well - return max(min(stoploss, 1.0), 0.0) + return max(min(stoploss, 1.0), 0.0) * leverage diff --git a/tests/strategy/test_strategy_helpers.py b/tests/strategy/test_strategy_helpers.py index a55580780..d6aebd982 100644 --- a/tests/strategy/test_strategy_helpers.py +++ b/tests/strategy/test_strategy_helpers.py @@ -211,15 +211,18 @@ def test_stoploss_from_absolute(): assert pytest.approx(stoploss_from_absolute(110, 100)) == 0 assert pytest.approx(stoploss_from_absolute(100, 0)) == 1 assert pytest.approx(stoploss_from_absolute(0, 100)) == 1 + assert pytest.approx(stoploss_from_absolute(0, 100, False, leverage=5)) == 5 assert pytest.approx(stoploss_from_absolute(90, 100, True)) == 0 assert pytest.approx(stoploss_from_absolute(100, 100, True)) == 0 assert pytest.approx(stoploss_from_absolute(110, 100, True)) == -(1 - (110 / 100)) assert pytest.approx(stoploss_from_absolute(110, 100, True)) == 0.1 assert pytest.approx(stoploss_from_absolute(105, 100, True)) == 0.05 + assert pytest.approx(stoploss_from_absolute(105, 100, True, 5)) == 0.05 * 5 assert pytest.approx(stoploss_from_absolute(100, 0, True)) == 1 assert pytest.approx(stoploss_from_absolute(0, 100, True)) == 0 - assert pytest.approx(stoploss_from_absolute(100, 1, True)) == 1 + assert pytest.approx(stoploss_from_absolute(100, 1, is_short=True)) == 1 + assert pytest.approx(stoploss_from_absolute(100, 1, is_short=True, leverage=5)) == 5 @pytest.mark.parametrize('trading_mode', ['futures', 'spot'])