Introduce ExchangeError

This commit is contained in:
Matthias 2020-06-28 16:01:40 +02:00
parent e74d2af857
commit bf61bc9d83
8 changed files with 34 additions and 26 deletions

View File

@ -10,7 +10,7 @@ from typing import Any, Dict, List, Optional
from pandas import DataFrame from pandas import DataFrame
from freqtrade.data.history import load_pair_history from freqtrade.data.history import load_pair_history
from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.exceptions import ExchangeError, OperationalException
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
from freqtrade.state import RunMode from freqtrade.state import RunMode
from freqtrade.constants import ListPairsWithTimeframes from freqtrade.constants import ListPairsWithTimeframes
@ -105,7 +105,7 @@ class DataProvider:
""" """
try: try:
return self._exchange.fetch_ticker(pair) return self._exchange.fetch_ticker(pair)
except DependencyException: except ExchangeError:
return {} return {}
def orderbook(self, pair: str, maximum: int) -> Dict[str, List]: def orderbook(self, pair: str, maximum: int) -> Dict[str, List]:

View File

@ -37,7 +37,14 @@ class InvalidOrderException(FreqtradeException):
""" """
class TemporaryError(DependencyException): class ExchangeError(DependencyException):
"""
Error raised out of the exchange.
Has multiple Errors to determine the appropriate error.
"""
class TemporaryError(ExchangeError):
""" """
Temporary network or exchange related error. Temporary network or exchange related error.
This could happen when an exchange is congested, unavailable, or the user This could happen when an exchange is congested, unavailable, or the user

View File

@ -4,7 +4,7 @@ from typing import Dict
import ccxt import ccxt
from freqtrade.exceptions import (DDosProtection, DependencyException, from freqtrade.exceptions import (DDosProtection, ExchangeError,
InvalidOrderException, OperationalException, InvalidOrderException, OperationalException,
TemporaryError) TemporaryError)
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
@ -80,7 +80,7 @@ class Binance(Exchange):
'stop price: %s. limit: %s', pair, stop_price, rate) 'stop price: %s. limit: %s', pair, stop_price, rate)
return order return order
except ccxt.InsufficientFunds as e: except ccxt.InsufficientFunds as e:
raise DependencyException( 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'Tried to sell amount {amount} at rate {rate}. '
f'Message: {e}') from e f'Message: {e}') from e

View File

@ -20,7 +20,7 @@ from pandas import DataFrame
from freqtrade.constants import ListPairsWithTimeframes from freqtrade.constants import ListPairsWithTimeframes
from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list
from freqtrade.exceptions import (DDosProtection, DependencyException, from freqtrade.exceptions import (DDosProtection, ExchangeError,
InvalidOrderException, OperationalException, InvalidOrderException, OperationalException,
TemporaryError) TemporaryError)
from freqtrade.exchange.common import BAD_EXCHANGES, retrier, retrier_async from freqtrade.exchange.common import BAD_EXCHANGES, retrier, retrier_async
@ -352,7 +352,7 @@ class Exchange:
for pair in [f"{curr_1}/{curr_2}", f"{curr_2}/{curr_1}"]: for pair in [f"{curr_1}/{curr_2}", f"{curr_2}/{curr_1}"]:
if pair in self.markets and self.markets[pair].get('active'): if pair in self.markets and self.markets[pair].get('active'):
return pair return pair
raise DependencyException(f"Could not combine {curr_1} and {curr_2} to get a valid pair.") raise ExchangeError(f"Could not combine {curr_1} and {curr_2} to get a valid pair.")
def validate_timeframes(self, timeframe: Optional[str]) -> None: def validate_timeframes(self, timeframe: Optional[str]) -> None:
""" """
@ -519,12 +519,12 @@ class Exchange:
amount, rate_for_order, params) amount, rate_for_order, params)
except ccxt.InsufficientFunds as e: except ccxt.InsufficientFunds as e:
raise DependencyException( 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'Tried to {side} amount {amount} at rate {rate}.'
f'Message: {e}') from e f'Message: {e}') from e
except ccxt.InvalidOrder as e: except ccxt.InvalidOrder as e:
raise DependencyException( raise ExchangeError(
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}.' f'Tried to {side} amount {amount} at rate {rate}.'
f'Message: {e}') from e f'Message: {e}') from e
@ -637,7 +637,7 @@ class Exchange:
def fetch_ticker(self, pair: str) -> dict: def fetch_ticker(self, pair: str) -> dict:
try: try:
if pair not in self._api.markets or not self._api.markets[pair].get('active'): if pair not in self._api.markets or not self._api.markets[pair].get('active'):
raise DependencyException(f"Pair {pair} not available") raise ExchangeError(f"Pair {pair} not available")
data = self._api.fetch_ticker(pair) data = self._api.fetch_ticker(pair)
return data return data
except ccxt.DDoSProtection as e: except ccxt.DDoSProtection as e:
@ -1151,7 +1151,7 @@ class Exchange:
fee_to_quote_rate = safe_value_fallback(tick, tick, 'last', 'ask') fee_to_quote_rate = safe_value_fallback(tick, tick, 'last', 'ask')
return round((order['fee']['cost'] * fee_to_quote_rate) / order['cost'], 8) return round((order['fee']['cost'] * fee_to_quote_rate) / order['cost'], 8)
except DependencyException: except ExchangeError:
return None return None
def extract_cost_curr_rate(self, order: Dict) -> Tuple[float, str, Optional[float]]: def extract_cost_curr_rate(self, order: Dict) -> Tuple[float, str, Optional[float]]:

View File

@ -4,7 +4,7 @@ from typing import Dict
import ccxt import ccxt
from freqtrade.exceptions import (DDosProtection, DependencyException, from freqtrade.exceptions import (DDosProtection, ExchangeError,
InvalidOrderException, OperationalException, InvalidOrderException, OperationalException,
TemporaryError) TemporaryError)
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
@ -61,7 +61,7 @@ class Ftx(Exchange):
'stop price: %s.', pair, stop_price) 'stop price: %s.', pair, stop_price)
return order return order
except ccxt.InsufficientFunds as e: except ccxt.InsufficientFunds as e:
raise DependencyException( 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'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
f'Message: {e}') from e f'Message: {e}') from e

View File

@ -4,8 +4,9 @@ from typing import Dict
import ccxt import ccxt
from freqtrade.exceptions import (DependencyException, InvalidOrderException, DDosProtection, from freqtrade.exceptions import (DDosProtection, ExchangeError,
OperationalException, TemporaryError) InvalidOrderException, OperationalException,
TemporaryError)
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
from freqtrade.exchange.common import retrier from freqtrade.exchange.common import retrier
@ -87,7 +88,7 @@ class Kraken(Exchange):
'stop price: %s.', pair, stop_price) 'stop price: %s.', pair, stop_price)
return order return order
except ccxt.InsufficientFunds as e: except ccxt.InsufficientFunds as e:
raise DependencyException( 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'Tried to create stoploss with amount {amount} at stoploss {stop_price}. '
f'Message: {e}') from e f'Message: {e}') from e

View File

@ -11,14 +11,14 @@ from typing import Any, Dict, List, Optional
import arrow import arrow
from cachetools import TTLCache from cachetools import TTLCache
from requests.exceptions import RequestException
from freqtrade import __version__, constants, persistence from freqtrade import __version__, constants, persistence
from freqtrade.configuration import validate_config_consistency from freqtrade.configuration import validate_config_consistency
from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.converter import order_book_to_dataframe
from freqtrade.data.dataprovider import DataProvider from freqtrade.data.dataprovider import DataProvider
from freqtrade.edge import Edge from freqtrade.edge import Edge
from freqtrade.exceptions import DependencyException, InvalidOrderException, PricingError from freqtrade.exceptions import (DependencyException, ExchangeError,
InvalidOrderException, PricingError)
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_next_date from freqtrade.exchange import timeframe_to_minutes, timeframe_to_next_date
from freqtrade.misc import safe_value_fallback from freqtrade.misc import safe_value_fallback
from freqtrade.pairlist.pairlistmanager import PairListManager from freqtrade.pairlist.pairlistmanager import PairListManager
@ -755,7 +755,7 @@ class FreqtradeBot:
logger.warning('Selling the trade forcefully') logger.warning('Selling the trade forcefully')
self.execute_sell(trade, trade.stop_loss, sell_reason=SellType.EMERGENCY_SELL) self.execute_sell(trade, trade.stop_loss, sell_reason=SellType.EMERGENCY_SELL)
except DependencyException: except ExchangeError:
trade.stoploss_order_id = None trade.stoploss_order_id = None
logger.exception('Unable to place a stoploss order on exchange.') logger.exception('Unable to place a stoploss order on exchange.')
return False return False
@ -891,7 +891,7 @@ class FreqtradeBot:
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, InvalidOrderException): except (ExchangeError, InvalidOrderException):
logger.info('Cannot query order for %s due to %s', trade, traceback.format_exc()) logger.info('Cannot query order for %s due to %s', trade, traceback.format_exc())
continue continue

View File

@ -11,7 +11,7 @@ from typing import Any, Dict, List, Optional, Tuple
import arrow import arrow
from numpy import NAN, mean from numpy import NAN, mean
from freqtrade.exceptions import DependencyException, TemporaryError from freqtrade.exceptions import ExchangeError, PricingError
from freqtrade.misc import shorten_date from freqtrade.misc import shorten_date
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
@ -130,7 +130,7 @@ class RPC:
# calculate profit and send message to user # calculate profit and send message to user
try: try:
current_rate = self._freqtrade.get_sell_rate(trade.pair, False) current_rate = self._freqtrade.get_sell_rate(trade.pair, False)
except DependencyException: except (ExchangeError, PricingError):
current_rate = NAN current_rate = NAN
current_profit = trade.calc_profit_ratio(current_rate) current_profit = trade.calc_profit_ratio(current_rate)
current_profit_abs = trade.calc_profit(current_rate) current_profit_abs = trade.calc_profit(current_rate)
@ -174,7 +174,7 @@ class RPC:
# calculate profit and send message to user # calculate profit and send message to user
try: try:
current_rate = self._freqtrade.get_sell_rate(trade.pair, False) current_rate = self._freqtrade.get_sell_rate(trade.pair, False)
except DependencyException: except (PricingError, ExchangeError):
current_rate = NAN current_rate = NAN
trade_percent = (100 * trade.calc_profit_ratio(current_rate)) trade_percent = (100 * trade.calc_profit_ratio(current_rate))
trade_profit = trade.calc_profit(current_rate) trade_profit = trade.calc_profit(current_rate)
@ -286,7 +286,7 @@ class RPC:
# Get current rate # Get current rate
try: try:
current_rate = self._freqtrade.get_sell_rate(trade.pair, False) current_rate = self._freqtrade.get_sell_rate(trade.pair, False)
except DependencyException: except (PricingError, ExchangeError):
current_rate = NAN current_rate = NAN
profit_ratio = trade.calc_profit_ratio(rate=current_rate) profit_ratio = trade.calc_profit_ratio(rate=current_rate)
@ -352,7 +352,7 @@ class RPC:
total = 0.0 total = 0.0
try: try:
tickers = self._freqtrade.exchange.get_tickers() tickers = self._freqtrade.exchange.get_tickers()
except (TemporaryError, DependencyException): except (ExchangeError):
raise RPCException('Error getting current tickers.') raise RPCException('Error getting current tickers.')
self._freqtrade.wallets.update(require_update=False) self._freqtrade.wallets.update(require_update=False)
@ -373,7 +373,7 @@ class RPC:
if pair.startswith(stake_currency): if pair.startswith(stake_currency):
rate = 1.0 / rate rate = 1.0 / rate
est_stake = rate * balance.total est_stake = rate * balance.total
except (TemporaryError, DependencyException): except (ExchangeError):
logger.warning(f" Could not get rate for pair {coin}.") logger.warning(f" Could not get rate for pair {coin}.")
continue continue
total = total + (est_stake or 0) total = total + (est_stake or 0)