Introduce cancel_stoploss_with_result

This commit is contained in:
Matthias 2021-05-16 14:15:24 +02:00
parent 380754b8ab
commit 6f38976470
4 changed files with 29 additions and 4 deletions

View File

@ -1120,6 +1120,27 @@ class Exchange:
return order return order
def cancel_stoploss_order_with_result(self, order_id: str, pair: str, amount: float) -> Dict:
"""
Cancel stoploss order returning a result.
Creates a fake result if cancel order returns a non-usable result
and fetch_order does not work (certain exchanges don't return cancelled orders)
:param order_id: stoploss-order-id to cancel
:param pair: Pair corresponding to order_id
:param amount: Amount to use for fake response
:return: Result from either cancel_order if usable, or fetch_order
"""
corder = self.cancel_stoploss_order(order_id, pair)
if self.is_cancel_order_result_suitable(corder):
return corder
try:
order = self.fetch_stoploss_order(order_id, pair)
except InvalidOrderException:
logger.warning(f"Could not fetch cancelled stoploss order {order_id}.")
order = {'fee': {}, 'status': 'canceled', 'amount': amount, 'info': {}}
return order
@retrier(retries=API_FETCH_ORDER_RETRY_COUNT) @retrier(retries=API_FETCH_ORDER_RETRY_COUNT)
def fetch_order(self, order_id: str, pair: str) -> Dict: def fetch_order(self, order_id: str, pair: str) -> Dict:
if self._config['dry_run']: if self._config['dry_run']:

View File

@ -939,7 +939,8 @@ class FreqtradeBot(LoggingMixin):
logger.info(f"Cancelling current stoploss on exchange for pair {trade.pair} " logger.info(f"Cancelling current stoploss on exchange for pair {trade.pair} "
f"(orderid:{order['id']}) in order to add another one ...") f"(orderid:{order['id']}) in order to add another one ...")
try: try:
co = self.exchange.cancel_stoploss_order(order['id'], trade.pair) co = self.exchange.cancel_stoploss_order_with_result(order['id'], trade.pair,
trade.amount)
trade.update_order(co) trade.update_order(co)
except InvalidOrderException: except InvalidOrderException:
logger.exception(f"Could not cancel stoploss order {order['id']} " logger.exception(f"Could not cancel stoploss order {order['id']} "
@ -1172,7 +1173,9 @@ class FreqtradeBot(LoggingMixin):
# First cancelling stoploss on exchange ... # First cancelling stoploss on exchange ...
if self.strategy.order_types.get('stoploss_on_exchange') and trade.stoploss_order_id: if self.strategy.order_types.get('stoploss_on_exchange') and trade.stoploss_order_id:
try: try:
self.exchange.cancel_stoploss_order(trade.stoploss_order_id, trade.pair) co = self.exchange.cancel_stoploss_order_with_result(trade.stoploss_order_id,
trade.pair, trade.amount)
trade.update_order(co)
except InvalidOrderException: except InvalidOrderException:
logger.exception(f"Could not cancel stoploss order {trade.stoploss_order_id}") logger.exception(f"Could not cancel stoploss order {trade.stoploss_order_id}")

View File

@ -1371,7 +1371,8 @@ def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, c
} }
mocker.patch('freqtrade.exchange.Binance.cancel_stoploss_order', mocker.patch('freqtrade.exchange.Binance.cancel_stoploss_order',
side_effect=InvalidOrderException()) side_effect=InvalidOrderException())
mocker.patch('freqtrade.exchange.Binance.fetch_stoploss_order', stoploss_order_hanging) mocker.patch('freqtrade.exchange.Binance.fetch_stoploss_order',
return_value=stoploss_order_hanging)
freqtrade.handle_trailing_stoploss_on_exchange(trade, stoploss_order_hanging) freqtrade.handle_trailing_stoploss_on_exchange(trade, stoploss_order_hanging)
assert log_has_re(r"Could not cancel stoploss order abcd for pair ETH/BTC.*", caplog) assert log_has_re(r"Could not cancel stoploss order abcd for pair ETH/BTC.*", caplog)

View File

@ -63,7 +63,7 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
amount_to_precision=lambda s, x, y: y, amount_to_precision=lambda s, x, y: y,
price_to_precision=lambda s, x, y: y, price_to_precision=lambda s, x, y: y,
fetch_stoploss_order=stoploss_order_mock, fetch_stoploss_order=stoploss_order_mock,
cancel_stoploss_order=cancel_order_mock, cancel_stoploss_order_with_result=cancel_order_mock,
) )
mocker.patch.multiple( mocker.patch.multiple(