Merge branch 'develop' into fix/3579

This commit is contained in:
Matthias
2020-08-12 15:28:51 +02:00
55 changed files with 989 additions and 216 deletions

View File

@@ -81,7 +81,7 @@ class Binance(Exchange):
return order
except ccxt.InsufficientFunds as e:
raise ExchangeError(
f'Insufficient funds to create {ordertype} sell order on market {pair}.'
f'Insufficient funds to create {ordertype} sell order on market {pair}. '
f'Tried to sell amount {amount} at rate {rate}. '
f'Message: {e}') from e
except ccxt.InvalidOrder as e:

View File

@@ -107,12 +107,12 @@ def retrier_async(f):
except TemporaryError as ex:
logger.warning('%s() returned exception: "%s"', f.__name__, ex)
if count > 0:
logger.warning('retrying %s() still for %s times', f.__name__, count)
count -= 1
kwargs.update({'count': count})
logger.warning('retrying %s() still for %s times', f.__name__, count)
if isinstance(ex, DDosProtection):
backoff_delay = calculate_backoff(count + 1, API_RETRY_COUNT)
logger.debug(f"Applying DDosProtection backoff delay: {backoff_delay}")
logger.info(f"Applying DDosProtection backoff delay: {backoff_delay}")
await asyncio.sleep(backoff_delay)
return await wrapper(*args, **kwargs)
else:
@@ -131,13 +131,13 @@ def retrier(_func=None, retries=API_RETRY_COUNT):
except (TemporaryError, RetryableOrderError) as ex:
logger.warning('%s() returned exception: "%s"', f.__name__, ex)
if count > 0:
logger.warning('retrying %s() still for %s times', f.__name__, count)
count -= 1
kwargs.update({'count': count})
logger.warning('retrying %s() still for %s times', f.__name__, count)
if isinstance(ex, DDosProtection) or isinstance(ex, RetryableOrderError):
# increasing backoff
backoff_delay = calculate_backoff(count + 1, retries)
logger.debug(f"Applying DDosProtection backoff delay: {backoff_delay}")
logger.info(f"Applying DDosProtection backoff delay: {backoff_delay}")
time.sleep(backoff_delay)
return wrapper(*args, **kwargs)
else:

View File

@@ -187,6 +187,11 @@ class Exchange:
def timeframes(self) -> List[str]:
return list((self._api.timeframes or {}).keys())
@property
def ohlcv_candle_limit(self) -> int:
"""exchange ohlcv candle limit"""
return int(self._ohlcv_candle_limit)
@property
def markets(self) -> Dict:
"""exchange ccxt markets"""
@@ -253,8 +258,8 @@ class Exchange:
api.urls['api'] = api.urls['test']
logger.info("Enabled Sandbox API on %s", name)
else:
logger.warning(name, "No Sandbox URL in CCXT, exiting. "
"Please check your config.json")
logger.warning(
f"No Sandbox URL in CCXT for {name}, exiting. Please check your config.json")
raise OperationalException(f'Exchange {name} does not provide a sandbox api')
def _load_async_markets(self, reload: bool = False) -> None:
@@ -521,13 +526,13 @@ class Exchange:
except ccxt.InsufficientFunds as e:
raise ExchangeError(
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}.'
f'Message: {e}') from e
except ccxt.InvalidOrder as e:
raise ExchangeError(
f'Could not create {ordertype} {side} order on market {pair}.'
f'Tried to {side} amount {amount} at rate {rate}.'
f'Could not create {ordertype} {side} order on market {pair}. '
f'Tried to {side} amount {amount} at rate {rate}. '
f'Message: {e}') from e
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
@@ -995,7 +1000,7 @@ class Exchange:
if self.is_cancel_order_result_suitable(corder):
return corder
except InvalidOrderException:
logger.warning(f"Could not cancel order {order_id}.")
logger.warning(f"Could not cancel order {order_id} for {pair}.")
try:
order = self.fetch_order(order_id, pair)
except InvalidOrderException:
@@ -1004,7 +1009,7 @@ class Exchange:
return order
@retrier
@retrier(retries=5)
def fetch_order(self, order_id: str, pair: str) -> Dict:
if self._config['dry_run']:
try:
@@ -1018,10 +1023,10 @@ class Exchange:
return self._api.fetch_order(order_id, pair)
except ccxt.OrderNotFound as e:
raise RetryableOrderError(
f'Order not found (id: {order_id}). Message: {e}') from e
f'Order not found (pair: {pair} id: {order_id}). Message: {e}') from e
except ccxt.InvalidOrder as e:
raise InvalidOrderException(
f'Tried to get an invalid order (id: {order_id}). Message: {e}') from e
f'Tried to get an invalid order (pair: {pair} id: {order_id}). Message: {e}') from e
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:

View File

@@ -78,7 +78,7 @@ class Ftx(Exchange):
except ccxt.BaseError as e:
raise OperationalException(e) from e
@retrier
@retrier(retries=5)
def fetch_stoploss_order(self, order_id: str, pair: str) -> Dict:
if self._config['dry_run']:
try:

View File

@@ -89,7 +89,7 @@ class Kraken(Exchange):
return order
except ccxt.InsufficientFunds as e:
raise ExchangeError(
f'Insufficient funds to create {ordertype} sell order on market {pair}.'
f'Insufficient funds to create {ordertype} sell order on market {pair}. '
f'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
f'Message: {e}') from e
except ccxt.InvalidOrder as e: