Merge pull request #12581 from freqtrade/fix/sloe_handling
Improve stoploss cancellation logic
This commit is contained in:
@@ -1063,7 +1063,16 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def cancel_stoploss_on_exchange(self, trade: Trade) -> Trade:
|
def cancel_stoploss_on_exchange(self, trade: Trade, allow_nonblocking: bool = False) -> Trade:
|
||||||
|
"""
|
||||||
|
Cancels on exchange stoploss orders for the given trade.
|
||||||
|
:param trade: Trade for which to cancel stoploss order
|
||||||
|
:param allow_nonblocking: If True, will skip cancelling stoploss on exchange
|
||||||
|
if the exchange supports blocking stoploss orders.
|
||||||
|
"""
|
||||||
|
if allow_nonblocking and not self.exchange.get_option("stoploss_blocks_assets", True):
|
||||||
|
logger.info(f"Skipping cancelling stoploss on exchange for {trade}.")
|
||||||
|
return trade
|
||||||
# First cancelling stoploss on exchange ...
|
# First cancelling stoploss on exchange ...
|
||||||
for oslo in trade.open_sl_orders:
|
for oslo in trade.open_sl_orders:
|
||||||
try:
|
try:
|
||||||
@@ -2088,7 +2097,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
limit = self.get_valid_price(custom_exit_price, proposed_limit_rate)
|
limit = self.get_valid_price(custom_exit_price, proposed_limit_rate)
|
||||||
|
|
||||||
# First cancelling stoploss on exchange ...
|
# First cancelling stoploss on exchange ...
|
||||||
trade = self.cancel_stoploss_on_exchange(trade)
|
trade = self.cancel_stoploss_on_exchange(trade, allow_nonblocking=True)
|
||||||
|
|
||||||
order_type = ordertype or self.strategy.order_types[exit_type]
|
order_type = ordertype or self.strategy.order_types[exit_type]
|
||||||
if exit_check.exit_type == ExitType.EMERGENCY_EXIT:
|
if exit_check.exit_type == ExitType.EMERGENCY_EXIT:
|
||||||
@@ -2378,6 +2387,8 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
self.strategy.ft_stoploss_adjust(
|
self.strategy.ft_stoploss_adjust(
|
||||||
current_rate, trade, datetime.now(UTC), profit, 0, after_fill=True
|
current_rate, trade, datetime.now(UTC), profit, 0, after_fill=True
|
||||||
)
|
)
|
||||||
|
if not trade.is_open:
|
||||||
|
self.cancel_stoploss_on_exchange(trade)
|
||||||
# Updating wallets when order is closed
|
# Updating wallets when order is closed
|
||||||
self.wallets.update()
|
self.wallets.update()
|
||||||
return trade
|
return trade
|
||||||
|
|||||||
@@ -800,9 +800,13 @@ def test_dca_handle_similar_open_order(
|
|||||||
# Should Create a new exit order
|
# Should Create a new exit order
|
||||||
freqtrade.exchange.amount_to_contract_precision = MagicMock(return_value=2)
|
freqtrade.exchange.amount_to_contract_precision = MagicMock(return_value=2)
|
||||||
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-2)
|
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-2)
|
||||||
|
msg = r"Skipping cancelling stoploss on exchange for.*"
|
||||||
|
|
||||||
mocker.patch(f"{EXMS}._dry_is_price_crossed", return_value=False)
|
mocker.patch(f"{EXMS}._dry_is_price_crossed", return_value=False)
|
||||||
|
assert not log_has_re(msg, caplog)
|
||||||
freqtrade.process()
|
freqtrade.process()
|
||||||
|
assert log_has_re(msg, caplog)
|
||||||
|
|
||||||
trade = Trade.get_trades().first()
|
trade = Trade.get_trades().first()
|
||||||
|
|
||||||
assert trade.orders[-2].status == "closed"
|
assert trade.orders[-2].status == "closed"
|
||||||
|
|||||||
Reference in New Issue
Block a user