Merge pull request #7619 from freqtrade/stop/usehighlow

Stop/usehighlow
This commit is contained in:
Matthias 2022-10-24 20:04:36 +02:00 committed by GitHub
commit e969479525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 10 additions and 9 deletions

View File

@ -522,13 +522,13 @@ Since backtesting lacks some detailed information about what happens within a ca
- ROI - ROI
- exits are compared to high - but the ROI value is used (e.g. ROI = 2%, high=5% - so the exit will be at 2%) - exits are compared to high - but the ROI value is used (e.g. ROI = 2%, high=5% - so the exit will be at 2%)
- exits are never "below the candle", so a ROI of 2% may result in a exit at 2.4% if low was at 2.4% profit - exits are never "below the candle", so a ROI of 2% may result in a exit at 2.4% if low was at 2.4% profit
- Forceexits caused by `<N>=-1` ROI entries use low as exit value, unless N falls on the candle open (e.g. `120: -1` for 1h candles) - Force-exits caused by `<N>=-1` ROI entries use low as exit value, unless N falls on the candle open (e.g. `120: -1` for 1h candles)
- Stoploss exits happen exactly at stoploss price, even if low was lower, but the loss will be `2 * fees` higher than the stoploss price - Stoploss exits happen exactly at stoploss price, even if low was lower, but the loss will be `2 * fees` higher than the stoploss price
- Stoploss is evaluated before ROI within one candle. So you can often see more trades with the `stoploss` exit reason comparing to the results obtained with the same strategy in the Dry Run/Live Trade modes - Stoploss is evaluated before ROI within one candle. So you can often see more trades with the `stoploss` exit reason comparing to the results obtained with the same strategy in the Dry Run/Live Trade modes
- Low happens before high for stoploss, protecting capital first - Low happens before high for stoploss, protecting capital first
- Trailing stoploss - Trailing stoploss
- Trailing Stoploss is only adjusted if it's below the candle's low (otherwise it would be triggered) - Trailing Stoploss is only adjusted if it's below the candle's low (otherwise it would be triggered)
- On trade entry candles that trigger trailing stoploss, the "minimum offset" (`stop_positive_offset`) is assumed (instead of high) - and the stop is calculated from this point - On trade entry candles that trigger trailing stoploss, the "minimum offset" (`stop_positive_offset`) is assumed (instead of high) - and the stop is calculated from this point. This rule is NOT applicable to custom-stoploss scenarios, since there's no information about the stoploss logic available.
- High happens first - adjusting stoploss - High happens first - adjusting stoploss
- Low uses the adjusted stoploss (so exits with large high-low difference are backtested correctly) - Low uses the adjusted stoploss (so exits with large high-low difference are backtested correctly)
- ROI applies before trailing-stop, ensuring profits are "top-capped" at ROI if both ROI and trailing stop applies - ROI applies before trailing-stop, ensuring profits are "top-capped" at ROI if both ROI and trailing stop applies

View File

@ -159,6 +159,7 @@ The stoploss price can only ever move upwards - if the stoploss value returned f
The method must return a stoploss value (float / number) as a percentage of the current price. The method must return a stoploss value (float / number) as a percentage of the current price.
E.g. If the `current_rate` is 200 USD, then returning `0.02` will set the stoploss price 2% lower, at 196 USD. E.g. If the `current_rate` is 200 USD, then returning `0.02` will set the stoploss price 2% lower, at 196 USD.
During backtesting, `current_rate` (and `current_profit`) are provided against the candle's high (or low for short trades) - while the resulting stoploss is evaluated against the candle's low (or high for short trades).
The absolute value of the return value is used (the sign is ignored), so returning `0.05` or `-0.05` have the same result, a stoploss 5% below the current price. The absolute value of the return value is used (the sign is ignored), so returning `0.05` or `-0.05` have the same result, a stoploss 5% below the current price.

View File

@ -1072,26 +1072,26 @@ class IStrategy(ABC, HyperStrategyMixin):
trade.stop_loss > (high or current_rate) trade.stop_loss > (high or current_rate)
) )
# Make sure current_profit is calculated using high for backtesting.
bound = (low if trade.is_short else high)
bound_profit = current_profit if not bound else trade.calc_profit_ratio(bound)
if self.use_custom_stoploss and dir_correct: if self.use_custom_stoploss and dir_correct:
stop_loss_value = strategy_safe_wrapper(self.custom_stoploss, default_retval=None stop_loss_value = strategy_safe_wrapper(self.custom_stoploss, default_retval=None
)(pair=trade.pair, trade=trade, )(pair=trade.pair, trade=trade,
current_time=current_time, current_time=current_time,
current_rate=current_rate, current_rate=(bound or current_rate),
current_profit=current_profit) current_profit=bound_profit)
# Sanity check - error cases will return None # Sanity check - error cases will return None
if stop_loss_value: if stop_loss_value:
# logger.info(f"{trade.pair} {stop_loss_value=} {current_profit=}") # logger.info(f"{trade.pair} {stop_loss_value=} {bound_profit=}")
trade.adjust_stop_loss(current_rate, stop_loss_value) trade.adjust_stop_loss(bound or current_rate, stop_loss_value)
else: else:
logger.warning("CustomStoploss function did not return valid stoploss") logger.warning("CustomStoploss function did not return valid stoploss")
if self.trailing_stop and dir_correct: if self.trailing_stop and dir_correct:
# trailing stoploss handling # trailing stoploss handling
sl_offset = self.trailing_stop_positive_offset sl_offset = self.trailing_stop_positive_offset
# Make sure current_profit is calculated using high for backtesting. # Make sure current_profit is calculated using high for backtesting.
bound = low if trade.is_short else high
bound_profit = current_profit if not bound else trade.calc_profit_ratio(bound)
# Don't update stoploss if trailing_only_offset_is_reached is true. # Don't update stoploss if trailing_only_offset_is_reached is true.
if not (self.trailing_only_offset_is_reached and bound_profit < sl_offset): if not (self.trailing_only_offset_is_reached and bound_profit < sl_offset):