Add exchange_has validation
This commit is contained in:
parent
78a84f8081
commit
0550f261f1
@ -13,7 +13,7 @@ from tabulate import tabulate
|
|||||||
from freqtrade.configuration import setup_utils_configuration
|
from freqtrade.configuration import setup_utils_configuration
|
||||||
from freqtrade.constants import USERPATH_HYPEROPTS, USERPATH_STRATEGIES
|
from freqtrade.constants import USERPATH_HYPEROPTS, USERPATH_STRATEGIES
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.exchange import available_exchanges, ccxt_exchanges, market_is_active
|
from freqtrade.exchange import market_is_active, validate_exchanges
|
||||||
from freqtrade.misc import plural
|
from freqtrade.misc import plural
|
||||||
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
||||||
from freqtrade.state import RunMode
|
from freqtrade.state import RunMode
|
||||||
@ -28,14 +28,18 @@ def start_list_exchanges(args: Dict[str, Any]) -> None:
|
|||||||
:param args: Cli args from Arguments()
|
:param args: Cli args from Arguments()
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
exchanges = ccxt_exchanges() if args['list_exchanges_all'] else available_exchanges()
|
exchanges = validate_exchanges(args['list_exchanges_all'])
|
||||||
|
|
||||||
if args['print_one_column']:
|
if args['print_one_column']:
|
||||||
print('\n'.join(exchanges))
|
print('\n'.join([e[0] for e in exchanges]))
|
||||||
else:
|
else:
|
||||||
if args['list_exchanges_all']:
|
if args['list_exchanges_all']:
|
||||||
print(f"All exchanges supported by the ccxt library: {', '.join(exchanges)}")
|
print("All exchanges supported by the ccxt library:")
|
||||||
else:
|
else:
|
||||||
print(f"Exchanges available for Freqtrade: {', '.join(exchanges)}")
|
print("Exchanges available for Freqtrade:")
|
||||||
|
exchanges = [e for e in exchanges if e[1] is not False]
|
||||||
|
|
||||||
|
print(tabulate(exchanges, headers=['Exchange name', 'Valid', 'reason']))
|
||||||
|
|
||||||
|
|
||||||
def _print_objs_tabular(objs: List, print_colorized: bool) -> None:
|
def _print_objs_tabular(objs: List, print_colorized: bool) -> None:
|
||||||
|
@ -12,6 +12,6 @@ from freqtrade.exchange.exchange import (available_exchanges, ccxt_exchanges,
|
|||||||
is_exchange_known_ccxt, is_exchange_officially_supported,
|
is_exchange_known_ccxt, is_exchange_officially_supported,
|
||||||
market_is_active, timeframe_to_minutes, timeframe_to_msecs,
|
market_is_active, timeframe_to_minutes, timeframe_to_msecs,
|
||||||
timeframe_to_next_date, timeframe_to_prev_date,
|
timeframe_to_next_date, timeframe_to_prev_date,
|
||||||
timeframe_to_seconds)
|
timeframe_to_seconds, validate_exchanges)
|
||||||
from freqtrade.exchange.ftx import Ftx
|
from freqtrade.exchange.ftx import Ftx
|
||||||
from freqtrade.exchange.kraken import Kraken
|
from freqtrade.exchange.kraken import Kraken
|
||||||
|
@ -98,6 +98,29 @@ MAP_EXCHANGE_CHILDCLASS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EXCHANGE_HAS_REQUIRED = [
|
||||||
|
# Required / private
|
||||||
|
'fetchOrder',
|
||||||
|
'cancelOrder',
|
||||||
|
'createOrder',
|
||||||
|
# 'createLimitOrder', 'createMarketOrder',
|
||||||
|
'fetchBalance',
|
||||||
|
|
||||||
|
# Public endpoints
|
||||||
|
'loadMarkets',
|
||||||
|
'fetchOHLCV',
|
||||||
|
]
|
||||||
|
|
||||||
|
EXCHANGE_HAS_OPTIONAL = [
|
||||||
|
# Private
|
||||||
|
'fetchMyTrades', # Trades for order - fee detection
|
||||||
|
# Public
|
||||||
|
'fetchOrderBook', 'fetchL2OrderBook', 'fetchTicker', # OR for pricing
|
||||||
|
'fetchTickers', # For volumepairlist?
|
||||||
|
'fetchTrades', # Downloading trades data
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def calculate_backoff(retrycount, max_retries):
|
def calculate_backoff(retrycount, max_retries):
|
||||||
"""
|
"""
|
||||||
Calculate backoff
|
Calculate backoff
|
||||||
|
@ -23,7 +23,8 @@ from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list
|
|||||||
from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError,
|
from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError,
|
||||||
InvalidOrderException, OperationalException, RetryableOrderError,
|
InvalidOrderException, OperationalException, RetryableOrderError,
|
||||||
TemporaryError)
|
TemporaryError)
|
||||||
from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, BAD_EXCHANGES, retrier,
|
from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, BAD_EXCHANGES,
|
||||||
|
EXCHANGE_HAS_OPTIONAL, EXCHANGE_HAS_REQUIRED, retrier,
|
||||||
retrier_async)
|
retrier_async)
|
||||||
from freqtrade.misc import deep_merge_dicts, safe_value_fallback2
|
from freqtrade.misc import deep_merge_dicts, safe_value_fallback2
|
||||||
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
|
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
|
||||||
@ -1337,6 +1338,32 @@ def available_exchanges(ccxt_module: CcxtModuleType = None) -> List[str]:
|
|||||||
return [x for x in exchanges if not is_exchange_bad(x)]
|
return [x for x in exchanges if not is_exchange_bad(x)]
|
||||||
|
|
||||||
|
|
||||||
|
def validate_exchange(exchange: str) -> Tuple[bool, str]:
|
||||||
|
ex_mod = getattr(ccxt, exchange.lower())()
|
||||||
|
if not ex_mod or not ex_mod.has:
|
||||||
|
return False, ''
|
||||||
|
missing = [k for k in EXCHANGE_HAS_REQUIRED if not ex_mod.has.get(k)]
|
||||||
|
if missing:
|
||||||
|
return False, f"missing: {', '.join(missing)}"
|
||||||
|
|
||||||
|
missing_opt = [k for k in EXCHANGE_HAS_OPTIONAL if not ex_mod.has.get(k)]
|
||||||
|
if missing_opt:
|
||||||
|
return True, f"missing opt: {', '.join(missing_opt)}"
|
||||||
|
|
||||||
|
return True, ''
|
||||||
|
|
||||||
|
|
||||||
|
def validate_exchanges(all_exchanges: bool) -> List[Tuple[str, bool, str]]:
|
||||||
|
"""
|
||||||
|
:return: List of tuples with exchangename, valid, reason.
|
||||||
|
"""
|
||||||
|
exchanges = ccxt_exchanges() if all_exchanges else available_exchanges()
|
||||||
|
exchanges_valid = [
|
||||||
|
(e, *validate_exchange(e)) for e in exchanges
|
||||||
|
]
|
||||||
|
return exchanges_valid
|
||||||
|
|
||||||
|
|
||||||
def timeframe_to_seconds(timeframe: str) -> int:
|
def timeframe_to_seconds(timeframe: str) -> int:
|
||||||
"""
|
"""
|
||||||
Translates the timeframe interval value written in the human readable
|
Translates the timeframe interval value written in the human readable
|
||||||
|
Loading…
Reference in New Issue
Block a user