diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index 678899cc6..302ffd5fd 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -91,7 +91,8 @@ For example you could implement a 1:2 risk-reward ROI with `custom_exit()`. Using custom_exit() signals in place of stoploss though *is not recommended*. It is a inferior method to using `custom_stoploss()` in this regard - which also allows you to keep the stoploss on exchange. !!! Note - Returning a (none-empty) `string` or `True` from this method is equal to setting exit signal on a candle at specified time. This method is not called when exit signal is set already, or if exit signals are disabled (`use_exit_signal=False` or `exit_profit_only=True` while profit is below `exit_profit_offset`). `string` max length is 64 characters. Exceeding this limit will cause the message to be truncated to 64 characters. + Returning a (none-empty) `string` or `True` from this method is equal to setting exit signal on a candle at specified time. This method is not called when exit signal is set already, or if exit signals are disabled (`use_exit_signal=False`). `string` max length is 64 characters. Exceeding this limit will cause the message to be truncated to 64 characters. + `custom_exit()` will ignore `exit_profit_only`, and will always be called unless `use_exit_signal=False` or if there is an enter signal. An example of how we can use different indicators depending on the current profit and also exit trades that were open longer than one day: diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index eb1729ba7..1fe1f0953 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -145,6 +145,9 @@ Please refer to the [Strategy documentation](strategy-customization.md#exit-sign ### `custom_sell` +`custom_sell` has been renamed to `custom_exit`. +It's now also being called for every iteration, independent of current profit and `exit_profit_only` settings. + ``` python hl_lines="2" class AwesomeStrategy(IStrategy): def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index b0ed6e72d..1c53b2e3e 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -881,10 +881,7 @@ class IStrategy(ABC, HyperStrategyMixin): current_rate = rate current_profit = trade.calc_profit_ratio(current_rate) - if (self.exit_profit_only and current_profit <= self.exit_profit_offset): - # exit_profit_only and profit doesn't reach the offset - ignore sell signal - pass - elif self.use_exit_signal and not enter: + if self.use_exit_signal and not enter: if exit_: exit_signal = ExitType.EXIT_SIGNAL else: @@ -902,7 +899,11 @@ class IStrategy(ABC, HyperStrategyMixin): custom_reason = custom_reason[:CUSTOM_EXIT_MAX_LENGTH] else: custom_reason = None - if exit_signal in (ExitType.CUSTOM_EXIT, ExitType.EXIT_SIGNAL): + if ( + exit_signal == ExitType.CUSTOM_EXIT + or (exit_signal == ExitType.EXIT_SIGNAL + and (not self.exit_profit_only or current_profit > self.exit_profit_offset)) + ): logger.debug(f"{trade.pair} - Sell signal received. " f"exit_type=ExitType.{exit_signal.name}" + (f", custom_reason={custom_reason}" if custom_reason else ""))