Merge pull request #11796 from freqtrade/dependabot/pip/develop/ccxt-4.4.85

chore(deps): bump ccxt from 4.4.82 to 4.4.85
This commit is contained in:
Matthias
2025-05-31 17:57:26 +02:00
committed by GitHub
4 changed files with 32 additions and 28 deletions
+6 -5
View File
@@ -637,9 +637,9 @@ class Exchange:
if self._exchange_ws: if self._exchange_ws:
self._exchange_ws.reset_connections() self._exchange_ws.reset_connections()
async def _api_reload_markets(self, reload: bool = False) -> dict[str, Any]: async def _api_reload_markets(self, reload: bool = False) -> None:
try: try:
return await self._api_async.load_markets(reload=reload, params={}) await self._api_async.load_markets(reload=reload, params={})
except ccxt.DDoSProtection as e: except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e raise DDosProtection(e) from e
except (ccxt.OperationFailed, ccxt.ExchangeError) as e: except (ccxt.OperationFailed, ccxt.ExchangeError) as e:
@@ -649,14 +649,14 @@ class Exchange:
except ccxt.BaseError as e: except ccxt.BaseError as e:
raise TemporaryError(e) from e raise TemporaryError(e) from e
def _load_async_markets(self, reload: bool = False) -> dict[str, Any]: def _load_async_markets(self, reload: bool = False) -> None:
try: try:
with self._loop_lock: with self._loop_lock:
markets = self.loop.run_until_complete(self._api_reload_markets(reload=reload)) markets = self.loop.run_until_complete(self._api_reload_markets(reload=reload))
if isinstance(markets, Exception): if isinstance(markets, Exception):
raise markets raise markets
return markets return None
except asyncio.TimeoutError as e: except asyncio.TimeoutError as e:
logger.warning("Could not load markets. Reason: %s", e) logger.warning("Could not load markets. Reason: %s", e)
raise TemporaryError from e raise TemporaryError from e
@@ -679,7 +679,8 @@ class Exchange:
# on initial load, we retry 3 times to ensure we get the markets # on initial load, we retry 3 times to ensure we get the markets
retries: int = 3 if force else 0 retries: int = 3 if force else 0
# Reload async markets, then assign them to sync api # Reload async markets, then assign them to sync api
self._markets = retrier(self._load_async_markets, retries=retries)(reload=True) retrier(self._load_async_markets, retries=retries)(reload=True)
self._markets = self._api_async.markets
self._api.set_markets(self._api_async.markets, self._api_async.currencies) self._api.set_markets(self._api_async.markets, self._api_async.currencies)
# Assign options array, as it contains some temporary information from the exchange. # Assign options array, as it contains some temporary information from the exchange.
self._api.options = self._api_async.options self._api.options = self._api_async.options
+2 -2
View File
@@ -4,9 +4,9 @@ bottleneck==1.4.2
numexpr==2.10.2 numexpr==2.10.2
pandas-ta==0.3.14b pandas-ta==0.3.14b
ccxt==4.4.82 ccxt==4.4.85
cryptography==45.0.3 cryptography==45.0.3
aiohttp==3.9.5 aiohttp==3.11.18
SQLAlchemy==2.0.41 SQLAlchemy==2.0.41
python-telegram-bot==22.1 python-telegram-bot==22.1
# can't be hard-pinned due to telegram-bot pinning httpx with ~ # can't be hard-pinned due to telegram-bot pinning httpx with ~
+22 -20
View File
@@ -590,7 +590,8 @@ def test__load_markets(default_conf, mocker, caplog):
expected_return = {"ETH/BTC": "available"} expected_return = {"ETH/BTC": "available"}
api_mock = MagicMock() api_mock = MagicMock()
api_mock.load_markets = get_mock_coro(return_value=expected_return) api_mock.load_markets = get_mock_coro()
api_mock.markets = expected_return
mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock)) mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock))
default_conf["exchange"]["pair_whitelist"] = ["ETH/BTC"] default_conf["exchange"]["pair_whitelist"] = ["ETH/BTC"]
ex = Exchange(default_conf) ex = Exchange(default_conf)
@@ -606,6 +607,7 @@ def test_reload_markets(default_conf, mocker, caplog, time_machine):
time_machine.move_to(start_dt, tick=False) time_machine.move_to(start_dt, tick=False)
api_mock = MagicMock() api_mock = MagicMock()
api_mock.load_markets = get_mock_coro(return_value=initial_markets) api_mock.load_markets = get_mock_coro(return_value=initial_markets)
api_mock.markets = initial_markets
default_conf["exchange"]["markets_refresh_interval"] = 10 default_conf["exchange"]["markets_refresh_interval"] = 10
exchange = get_patched_exchange( exchange = get_patched_exchange(
mocker, default_conf, api_mock, exchange="binance", mock_markets=False mocker, default_conf, api_mock, exchange="binance", mock_markets=False
@@ -624,6 +626,7 @@ def test_reload_markets(default_conf, mocker, caplog, time_machine):
api_mock.load_markets = get_mock_coro(return_value=updated_markets) api_mock.load_markets = get_mock_coro(return_value=updated_markets)
# more than 10 minutes have passed, reload is executed # more than 10 minutes have passed, reload is executed
time_machine.move_to(start_dt + timedelta(minutes=11), tick=False) time_machine.move_to(start_dt + timedelta(minutes=11), tick=False)
api_mock.markets = updated_markets
exchange.reload_markets() exchange.reload_markets()
assert exchange.markets == updated_markets assert exchange.markets == updated_markets
assert lam_spy.call_count == 1 assert lam_spy.call_count == 1
@@ -669,34 +672,33 @@ def test_reload_markets_exception(default_conf, mocker, caplog):
@pytest.mark.parametrize("stake_currency", ["ETH", "BTC", "USDT"]) @pytest.mark.parametrize("stake_currency", ["ETH", "BTC", "USDT"])
def test_validate_stakecurrency(default_conf, stake_currency, mocker, caplog): def test_validate_stakecurrency(default_conf, stake_currency, mocker):
default_conf["stake_currency"] = stake_currency default_conf["stake_currency"] = stake_currency
api_mock = MagicMock() api_mock = MagicMock()
type(api_mock).load_markets = get_mock_coro( api_mock.load_markets = get_mock_coro()
return_value={ api_mock.markets = {
"ETH/BTC": {"quote": "BTC"}, "ETH/BTC": {"quote": "BTC"},
"LTC/BTC": {"quote": "BTC"}, "LTC/BTC": {"quote": "BTC"},
"XRP/ETH": {"quote": "ETH"}, "XRP/ETH": {"quote": "ETH"},
"NEO/USDT": {"quote": "USDT"}, "NEO/USDT": {"quote": "USDT"},
} }
)
mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock)) mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock))
mocker.patch(f"{EXMS}.validate_timeframes") mocker.patch(f"{EXMS}.validate_timeframes")
mocker.patch(f"{EXMS}.validate_pricing") mocker.patch(f"{EXMS}.validate_pricing")
Exchange(default_conf) Exchange(default_conf)
def test_validate_stakecurrency_error(default_conf, mocker, caplog): def test_validate_stakecurrency_error(default_conf, mocker):
default_conf["stake_currency"] = "XRP" default_conf["stake_currency"] = "XRP"
api_mock = MagicMock() api_mock = MagicMock()
type(api_mock).load_markets = get_mock_coro( api_mock.load_markets = get_mock_coro()
return_value={ api_mock.markets = {
"ETH/BTC": {"quote": "BTC"}, "ETH/BTC": {"quote": "BTC"},
"LTC/BTC": {"quote": "BTC"}, "LTC/BTC": {"quote": "BTC"},
"XRP/ETH": {"quote": "ETH"}, "XRP/ETH": {"quote": "ETH"},
"NEO/USDT": {"quote": "USDT"}, "NEO/USDT": {"quote": "USDT"},
} }
)
mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock)) mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock))
mocker.patch(f"{EXMS}.validate_timeframes") mocker.patch(f"{EXMS}.validate_timeframes")
with pytest.raises( with pytest.raises(
@@ -705,7 +707,7 @@ def test_validate_stakecurrency_error(default_conf, mocker, caplog):
): ):
Exchange(default_conf) Exchange(default_conf)
type(api_mock).load_markets = get_mock_coro(side_effect=ccxt.NetworkError("No connection.")) api_mock.load_markets = get_mock_coro(side_effect=ccxt.NetworkError("No connection."))
mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock)) mocker.patch(f"{EXMS}._init_ccxt", MagicMock(return_value=api_mock))
with pytest.raises( with pytest.raises(
+2 -1
View File
@@ -283,7 +283,8 @@ def test_hyperliquid_dry_run_liquidation_price(default_conf, mocker):
default_conf["trading_mode"] = "futures" default_conf["trading_mode"] = "futures"
default_conf["margin_mode"] = "isolated" default_conf["margin_mode"] = "isolated"
default_conf["stake_currency"] = "USDC" default_conf["stake_currency"] = "USDC"
api_mock.load_markets = get_mock_coro(return_value=markets) api_mock.load_markets = get_mock_coro()
api_mock.markets = markets
exchange = get_patched_exchange( exchange = get_patched_exchange(
mocker, default_conf, api_mock, exchange="hyperliquid", mock_markets=False mocker, default_conf, api_mock, exchange="hyperliquid", mock_markets=False
) )