diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 29971c897..1b3e94951 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -1,4 +1,4 @@ -from freqtrade.exchange.exchange import Exchange # noqa: F401 +from freqtrade.exchange.exchange import Exchange, MAP_EXCHANGE_CHILDCLASS # noqa: F401 from freqtrade.exchange.exchange import (get_exchange_bad_reason, # noqa: F401 is_exchange_bad, is_exchange_known_ccxt, diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index df7e5e2b4..859240695 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -102,6 +102,11 @@ BAD_EXCHANGES = { ], "Does not provide timeframes. ccxt fetchOHLCV: emulated"), } +MAP_EXCHANGE_CHILDCLASS = { + 'binanceus': 'binance', + 'binanceje': 'binance', +} + def retrier_async(f): async def wrapper(*args, **kwargs): diff --git a/freqtrade/resolvers/exchange_resolver.py b/freqtrade/resolvers/exchange_resolver.py index 6fb12a65f..8ae40d971 100644 --- a/freqtrade/resolvers/exchange_resolver.py +++ b/freqtrade/resolvers/exchange_resolver.py @@ -3,7 +3,7 @@ This module loads custom exchanges """ import logging -from freqtrade.exchange import Exchange +from freqtrade.exchange import Exchange, MAP_EXCHANGE_CHILDCLASS import freqtrade.exchange as exchanges from freqtrade.resolvers import IResolver @@ -22,6 +22,8 @@ class ExchangeResolver(IResolver): Load the custom class from config parameter :param config: configuration dictionary """ + # Map exchange name to avoid duplicate classes for identical exchanges + exchange_name = MAP_EXCHANGE_CHILDCLASS.get(exchange_name, exchange_name) exchange_name = exchange_name.title() try: self.exchange = self._load_exchange(exchange_name, kwargs={'config': config}) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index bf6025322..72b536afa 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -142,6 +142,12 @@ def test_exchange_resolver(default_conf, mocker, caplog): assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.", caplog) + # Test mapping + exchange = ExchangeResolver('binanceus', default_conf).exchange + assert isinstance(exchange, Exchange) + assert isinstance(exchange, Binance) + assert not isinstance(exchange, Kraken) + def test_validate_order_time_in_force(default_conf, mocker, caplog): caplog.set_level(logging.INFO)