From 3116548022862ae8e468af86c4ba7588efc5ff57 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 30 Jul 2026 19:48:13 +0200 Subject: [PATCH 1/2] fix: get_conversation_rate when rate is None --- freqtrade/exchange/exchange.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 46343544b0c..25277a5d838 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -2137,9 +2137,10 @@ def get_conversion_rate(self, coin: str, currency: str, *, cached=True) -> float ticker = tickers_other.get(pair, None) if ticker: rate: float | None = safe_value_fallback(ticker, "last", "ask", None) - if rate and pair.startswith(currency) and not pair.endswith(currency): - rate = 1.0 / rate - return rate + if rate: + if pair.startswith(currency) and not pair.endswith(currency): + rate = 1.0 / rate + return rate except ValueError: return None return None From b084fb206cf4bbe2d6e4eae49f79f2fa09e658ae Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 30 Jul 2026 20:03:55 +0200 Subject: [PATCH 2/2] test: improve test for get_conversation_rate --- tests/exchange/test_exchange.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 8f6ccf14e01..a704aee62f2 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -2363,7 +2363,7 @@ def test_get_conversion_rate(default_conf_usdt, mocker, exchange_name): api_mock = MagicMock() tick = { "ETH/USDT": { - "last": 42, + "last": None, }, "BCH/USDT": { "last": 41, @@ -2375,7 +2375,10 @@ def test_get_conversion_rate(default_conf_usdt, mocker, exchange_name): tick2 = { "ADA/USDT:USDT": { "last": 2.5, - } + }, + "ETH/USDT:USDT": { + "last": 42, + }, } mocker.patch(f"{EXMS}.exchange_has", return_value=True) api_mock.fetch_tickers = MagicMock(side_effect=[tick, tick2]) @@ -2386,14 +2389,24 @@ def test_get_conversion_rate(default_conf_usdt, mocker, exchange_name): # retrieve original ticker assert exchange.get_conversion_rate("USDT", "USDT") == 1 assert api_mock.fetch_tickers.call_count == 0 + # ETH must fall back to the "others" market since ETH/USDT is None. assert exchange.get_conversion_rate("ETH", "USDT") == 42 assert exchange.get_conversion_rate("ETH", "USDC") is None assert exchange.get_conversion_rate("ETH", "BTC") == 250 + assert api_mock.fetch_tickers.call_count == 2 + api_mock.fetch_tickers.reset_mock() + api_mock.fetch_tickers.side_effect = [tick, tick2] + # Cached tickers assert exchange.get_conversion_rate("BTC", "ETH") == 0.004 - assert api_mock.fetch_tickers.call_count == 1 + assert api_mock.fetch_tickers.call_count == 0 + # Uncached tickers api_mock.fetch_tickers.reset_mock() + assert exchange.get_conversion_rate("BTC", "ETH", cached=False) == 0.004 + assert api_mock.fetch_tickers.call_count == 1 + api_mock.fetch_tickers.reset_mock() + exchange._fetch_tickers_cache.clear() assert exchange.get_conversion_rate("ADA", "USDT") == 2.5 # Only the call to the "others" market assert api_mock.fetch_tickers.call_count == 1