From 8c5194d5e2fb1bb5d5b534e8790c169d16739aee Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 25 Nov 2023 15:05:56 +0100 Subject: [PATCH] force-reload markets when BadSymbol appears closes #9463 --- freqtrade/exchange/exchange.py | 15 ++++++++++++--- tests/exchange/test_exchange.py | 10 +++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index d0b6f4caf..5d0bc704f 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -486,11 +486,14 @@ class Exchange: except ccxt.BaseError: logger.exception('Unable to initialize markets.') - def reload_markets(self) -> None: + def reload_markets(self, force: bool = False) -> None: """Reload markets both sync and async if refresh interval has passed """ # Check whether markets have to be reloaded - if (self._last_markets_refresh > 0) and ( - self._last_markets_refresh + self.markets_refresh_interval > dt_ts()): + if ( + not force + and self._last_markets_refresh > 0 + and (self._last_markets_refresh + self.markets_refresh_interval > dt_ts()) + ): return None logger.debug("Performing scheduled market reload..") try: @@ -1547,6 +1550,12 @@ class Exchange: raise OperationalException( f'Exchange {self._api.name} does not support fetching tickers in batch. ' f'Message: {e}') from e + except ccxt.BadSymbol as e: + logger.warning(f"Could not load tickers due to {e.__class__.__name__}. Message: {e} ." + "Reloading markets.") + self.reload_markets(True) + # Re-raise exception to repeat the call. + raise TemporaryError from e except ccxt.DDoSProtection as e: raise DDosProtection(e) from e except (ccxt.NetworkError, ccxt.ExchangeError) as e: diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index e2b3cc102..ad993cb6d 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1851,7 +1851,7 @@ def test_fetch_bids_asks(default_conf, mocker): @pytest.mark.parametrize("exchange_name", EXCHANGES) -def test_get_tickers(default_conf, mocker, exchange_name): +def test_get_tickers(default_conf, mocker, exchange_name, caplog): api_mock = MagicMock() tick = {'ETH/BTC': { 'symbol': 'ETH/BTC', @@ -1900,6 +1900,14 @@ def test_get_tickers(default_conf, mocker, exchange_name): exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_tickers() + caplog.clear() + api_mock.fetch_tickers = MagicMock(side_effect=[ccxt.BadSymbol("SomeSymbol"), []]) + exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) + x = exchange.get_tickers() + assert x == [] + assert log_has_re(r'Could not load tickers due to BadSymbol\..*SomeSymbol', caplog) + caplog.clear() + api_mock.fetch_tickers = MagicMock(return_value={}) exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name) exchange.get_tickers()