Merge pull request #2055 from freqtrade/get_order_exception

Get order exception
This commit is contained in:
Matthias 2019-07-26 06:17:15 +02:00 committed by GitHub
commit fef8fe8525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 33 deletions

View File

@ -174,10 +174,10 @@ class Exchange(object):
try: try:
api = getattr(ccxt_module, name.lower())(ex_config) api = getattr(ccxt_module, name.lower())(ex_config)
except (KeyError, AttributeError): except (KeyError, AttributeError) as e:
raise OperationalException(f'Exchange {name} is not supported') raise OperationalException(f'Exchange {name} is not supported') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(f"Initialization of ccxt failed. Reason: {e}") raise OperationalException(f"Initialization of ccxt failed. Reason: {e}") from e
self.set_sandbox(api, exchange_config, name) self.set_sandbox(api, exchange_config, name)
@ -398,17 +398,17 @@ class Exchange(object):
raise DependencyException( raise DependencyException(
f'Insufficient funds to create {ordertype} {side} order on market {pair}.' f'Insufficient funds to create {ordertype} {side} order on market {pair}.'
f'Tried to {side} amount {amount} at rate {rate} (total {rate * amount}).' f'Tried to {side} amount {amount} at rate {rate} (total {rate * amount}).'
f'Message: {e}') f'Message: {e}') from e
except ccxt.InvalidOrder as e: except ccxt.InvalidOrder as e:
raise DependencyException( raise DependencyException(
f'Could not create {ordertype} {side} order on market {pair}.' f'Could not create {ordertype} {side} order on market {pair}.'
f'Tried to {side} amount {amount} at rate {rate} (total {rate * amount}).' f'Tried to {side} amount {amount} at rate {rate} (total {rate * amount}).'
f'Message: {e}') f'Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not place {side} order due to {e.__class__.__name__}. Message: {e}') f'Could not place {side} order due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
def buy(self, pair: str, ordertype: str, amount: float, def buy(self, pair: str, ordertype: str, amount: float,
rate: float, time_in_force) -> Dict: rate: float, time_in_force) -> Dict:
@ -493,9 +493,9 @@ class Exchange(object):
return balances return balances
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not get balance due to {e.__class__.__name__}. Message: {e}') f'Could not get balance due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
@retrier @retrier
def get_tickers(self) -> Dict: def get_tickers(self) -> Dict:
@ -504,12 +504,12 @@ class Exchange(object):
except ccxt.NotSupported as e: except ccxt.NotSupported as e:
raise OperationalException( raise OperationalException(
f'Exchange {self._api.name} does not support fetching tickers in batch.' f'Exchange {self._api.name} does not support fetching tickers in batch.'
f'Message: {e}') f'Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not load tickers due to {e.__class__.__name__}. Message: {e}') f'Could not load tickers due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
@retrier @retrier
def get_ticker(self, pair: str, refresh: Optional[bool] = True) -> dict: def get_ticker(self, pair: str, refresh: Optional[bool] = True) -> dict:
@ -528,9 +528,9 @@ class Exchange(object):
return data return data
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not load ticker due to {e.__class__.__name__}. Message: {e}') f'Could not load ticker due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
else: else:
logger.info("returning cached ticker-data for %s", pair) logger.info("returning cached ticker-data for %s", pair)
return self._cached_ticker[pair] return self._cached_ticker[pair]
@ -651,12 +651,12 @@ class Exchange(object):
except ccxt.NotSupported as e: except ccxt.NotSupported as e:
raise OperationalException( raise OperationalException(
f'Exchange {self._api.name} does not support fetching historical candlestick data.' f'Exchange {self._api.name} does not support fetching historical candlestick data.'
f'Message: {e}') f'Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(f'Could not load ticker history due to {e.__class__.__name__}. '
f'Could not load ticker history due to {e.__class__.__name__}. Message: {e}') f'Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(f'Could not fetch ticker data. Msg: {e}') raise OperationalException(f'Could not fetch ticker data. Msg: {e}') from e
@retrier @retrier
def cancel_order(self, order_id: str, pair: str) -> None: def cancel_order(self, order_id: str, pair: str) -> None:
@ -667,12 +667,12 @@ class Exchange(object):
return self._api.cancel_order(order_id, pair) return self._api.cancel_order(order_id, pair)
except ccxt.InvalidOrder as e: except ccxt.InvalidOrder as e:
raise InvalidOrderException( raise InvalidOrderException(
f'Could not cancel order. Message: {e}') f'Could not cancel order. Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not cancel order due to {e.__class__.__name__}. Message: {e}') f'Could not cancel order due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
@retrier @retrier
def get_order(self, order_id: str, pair: str) -> Dict: def get_order(self, order_id: str, pair: str) -> Dict:
@ -683,12 +683,12 @@ class Exchange(object):
return self._api.fetch_order(order_id, pair) return self._api.fetch_order(order_id, pair)
except ccxt.InvalidOrder as e: except ccxt.InvalidOrder as e:
raise InvalidOrderException( raise InvalidOrderException(
f'Tried to get an invalid order (id: {order_id}). Message: {e}') f'Tried to get an invalid order (id: {order_id}). Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not get order due to {e.__class__.__name__}. Message: {e}') f'Could not get order due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
@retrier @retrier
def get_order_book(self, pair: str, limit: int = 100) -> dict: def get_order_book(self, pair: str, limit: int = 100) -> dict:
@ -704,12 +704,12 @@ class Exchange(object):
except ccxt.NotSupported as e: except ccxt.NotSupported as e:
raise OperationalException( raise OperationalException(
f'Exchange {self._api.name} does not support fetching order book.' f'Exchange {self._api.name} does not support fetching order book.'
f'Message: {e}') f'Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not get order book due to {e.__class__.__name__}. Message: {e}') f'Could not get order book due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
@retrier @retrier
def get_trades_for_order(self, order_id: str, pair: str, since: datetime) -> List: def get_trades_for_order(self, order_id: str, pair: str, since: datetime) -> List:
@ -726,9 +726,9 @@ class Exchange(object):
except ccxt.NetworkError as e: except ccxt.NetworkError as e:
raise TemporaryError( raise TemporaryError(
f'Could not get trades due to networking error. Message: {e}') f'Could not get trades due to networking error. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
@retrier @retrier
def get_fee(self, symbol='ETH/BTC', type='', side='', amount=1, def get_fee(self, symbol='ETH/BTC', type='', side='', amount=1,
@ -742,9 +742,9 @@ class Exchange(object):
price=price, takerOrMaker=taker_or_maker)['rate'] price=price, takerOrMaker=taker_or_maker)['rate']
except (ccxt.NetworkError, ccxt.ExchangeError) as e: except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError( raise TemporaryError(
f'Could not get fee info due to {e.__class__.__name__}. Message: {e}') f'Could not get fee info due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise OperationalException(e) raise OperationalException(e) from e
def is_exchange_bad(exchange: str) -> bool: def is_exchange_bad(exchange: str) -> bool:

View File

@ -524,7 +524,11 @@ class FreqtradeBot(object):
if trade.open_order_id: if trade.open_order_id:
# Update trade with order values # Update trade with order values
logger.info('Found open order for %s', trade) logger.info('Found open order for %s', trade)
order = action_order or self.exchange.get_order(trade.open_order_id, trade.pair) try:
order = action_order or self.exchange.get_order(trade.open_order_id, trade.pair)
except InvalidOrderException as exception:
logger.warning('Unable to fetch order %s: %s', trade.open_order_id, exception)
return
# Try update amount (binance-fix) # Try update amount (binance-fix)
try: try:
new_amount = self.get_real_amount(trade, order) new_amount = self.get_real_amount(trade, order)
@ -749,7 +753,7 @@ class FreqtradeBot(object):
if not trade.open_order_id: if not trade.open_order_id:
continue continue
order = self.exchange.get_order(trade.open_order_id, trade.pair) order = self.exchange.get_order(trade.open_order_id, trade.pair)
except (RequestException, DependencyException): except (RequestException, DependencyException, InvalidOrderException):
logger.info( logger.info(
'Cannot query order for %s due to %s', 'Cannot query order for %s due to %s',
trade, trade,

View File

@ -1460,6 +1460,22 @@ def test_update_trade_state_exception(mocker, default_conf,
assert log_has('Could not update trade amount: ', caplog.record_tuples) assert log_has('Could not update trade amount: ', caplog.record_tuples)
def test_update_trade_state_orderexception(mocker, default_conf, caplog) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.get_order',
MagicMock(side_effect=InvalidOrderException))
trade = MagicMock()
trade.open_order_id = '123'
trade.open_fee = 0.001
# Test raise of OperationalException exception
grm_mock = mocker.patch("freqtrade.freqtradebot.FreqtradeBot.get_real_amount", MagicMock())
freqtrade.update_trade_state(trade)
assert grm_mock.call_count == 0
assert log_has(f'Unable to fetch order {trade.open_order_id}: ', caplog.record_tuples)
def test_update_trade_state_sell(default_conf, trades_for_order, limit_sell_order, mocker): def test_update_trade_state_sell(default_conf, trades_for_order, limit_sell_order, mocker):
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=trades_for_order)
# get_order should not be called!! # get_order should not be called!!