From 9a830c261c391235ffb6ebc9ed863a51a2802189 Mon Sep 17 00:00:00 2001 From: Pablo Date: Sun, 7 Dec 2025 12:36:25 +0100 Subject: [PATCH] feat: add support for rpi orders --- binance/async_client.py | 10 ++++ binance/client.py | 78 ++++++++++++++++++++++++++++++ binance/enums.py | 1 + binance/ws/streams.py | 16 ++++++ tests/test_async_client_futures.py | 19 ++++++++ tests/test_client_futures.py | 21 ++++++++ 6 files changed, 145 insertions(+) diff --git a/binance/async_client.py b/binance/async_client.py index f0a623f4..1791d860 100644 --- a/binance/async_client.py +++ b/binance/async_client.py @@ -1716,6 +1716,11 @@ async def futures_exchange_info(self): async def futures_order_book(self, **params): return await self._request_futures_api("get", "depth", data=params) + async def futures_rpi_depth(self, **params): + return await self._request_futures_api("get", "rpiDepth", data=params) + + futures_rpi_depth.__doc__ = Client.futures_rpi_depth.__doc__ + async def futures_recent_trades(self, **params): return await self._request_futures_api("get", "trades", data=params) @@ -2139,6 +2144,11 @@ async def futures_account(self, **params): "get", "account", True, version=2, data=params ) + async def futures_symbol_adl_risk(self, **params): + return await self._request_futures_api("get", "symbolAdlRisk", True, data=params) + + futures_symbol_adl_risk.__doc__ = Client.futures_symbol_adl_risk.__doc__ + async def futures_change_leverage(self, **params): return await self._request_futures_api("post", "leverage", True, data=params) diff --git a/binance/client.py b/binance/client.py index 5774469e..6e9acea2 100755 --- a/binance/client.py +++ b/binance/client.py @@ -7309,6 +7309,43 @@ def futures_order_book(self, **params): """ return self._request_futures_api("get", "depth", data=params) + def futures_rpi_depth(self, **params): + """Get RPI Order Book with Retail Price Improvement orders + + https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/rest-api/RPI-Order-Book + + :param symbol: required + :type symbol: str + :param limit: Default 1000; Valid limits:[1000] + :type limit: int + + :returns: API response + + .. code-block:: python + + { + "lastUpdateId": 1027024, + "E": 1589436922972, // Message output time + "T": 1589436922959, // Transaction time + "bids": [ + [ + "4.00000000", // PRICE + "431.00000000" // QTY + ] + ], + "asks": [ + [ + "4.00000200", + "12.00000000" + ] + ] + } + + :raises: BinanceRequestException, BinanceAPIException + + """ + return self._request_futures_api("get", "rpiDepth", data=params) + def futures_recent_trades(self, **params): """Get recent trades (up to last 500). @@ -8195,6 +8232,47 @@ def futures_account(self, **params): """ return self._request_futures_api("get", "account", True, 2, data=params) + def futures_symbol_adl_risk(self, **params): + """Query the symbol-level ADL (Auto-Deleveraging) risk rating + + The ADL risk rating measures the likelihood of ADL during liquidation. + Rating can be: high, medium, low. Updated every 30 minutes. + + https://developers.binance.com/docs/derivatives/usds-margined-futures/account/rest-api/Query-ADL-Risk-Rating + + :param symbol: optional - if not provided, returns ADL risk for all symbols + :type symbol: str + + :returns: API response + + .. code-block:: python + + # Single symbol + { + "symbol": "BTCUSDT", + "adlRisk": "low", + "updateTime": 1597370495002 + } + + # All symbols (when symbol not provided) + [ + { + "symbol": "BTCUSDT", + "adlRisk": "low", + "updateTime": 1597370495002 + }, + { + "symbol": "ETHUSDT", + "adlRisk": "high", + "updateTime": 1597370495004 + } + ] + + :raises: BinanceRequestException, BinanceAPIException + + """ + return self._request_futures_api("get", "symbolAdlRisk", True, data=params) + def futures_change_leverage(self, **params): """Change user's initial leverage of specific symbol market diff --git a/binance/enums.py b/binance/enums.py index ed793524..50f26e4c 100644 --- a/binance/enums.py +++ b/binance/enums.py @@ -56,6 +56,7 @@ TIME_IN_FORCE_FOK = "FOK" # Fill or kill TIME_IN_FORCE_GTX = "GTX" # Post only order TIME_IN_FORCE_GTD = "GTD" # Good till date +TIME_IN_FORCE_RPI = "RPI" # Retail Price Improvement ORDER_RESP_TYPE_ACK = "ACK" ORDER_RESP_TYPE_RESULT = "RESULT" diff --git a/binance/ws/streams.py b/binance/ws/streams.py index 33d5f3be..4a359251 100755 --- a/binance/ws/streams.py +++ b/binance/ws/streams.py @@ -1128,6 +1128,22 @@ def futures_depth_socket(self, symbol: str, depth: str = "10", futures_type=Futu symbol.lower() + "@depth" + str(depth), futures_type=futures_type ) + def futures_rpi_depth_socket(self, symbol: str, futures_type=FuturesType.USD_M): + """Subscribe to a futures RPI (Retail Price Improvement) depth data stream + + RPI orders are included and aggregated in the stream. Crossed price levels are hidden. + Updates every 500ms. + + https://developers.binance.com/docs/derivatives/usds-margined-futures/market-data/websocket-market-streams/RPI-Order-Book + + :param symbol: required + :type symbol: str + :param futures_type: use USD-M or COIN-M futures default USD-M + """ + return self._get_futures_socket( + symbol.lower() + "@rpiDepth@500ms", futures_type=futures_type + ) + def options_new_symbol_socket(self): """Subscribe to a new symbol listing information stream. diff --git a/tests/test_async_client_futures.py b/tests/test_async_client_futures.py index 1b986779..1f796064 100644 --- a/tests/test_async_client_futures.py +++ b/tests/test_async_client_futures.py @@ -18,6 +18,10 @@ async def test_futures_order_book(futuresClientAsync): order_book = await futuresClientAsync.futures_order_book(symbol="BTCUSDT") assert_ob(order_book) +async def test_futures_rpi_depth(futuresClientAsync): + rpi_depth = await futuresClientAsync.futures_rpi_depth(symbol="BTCUSDT") + assert_ob(rpi_depth) + async def test_futures_recent_trades(futuresClientAsync): await futuresClientAsync.futures_recent_trades(symbol="BTCUSDT") @@ -251,6 +255,21 @@ async def test_futures_account_balance(futuresClientAsync): async def test_futures_account(futuresClientAsync): await futuresClientAsync.futures_account() +async def test_futures_symbol_adl_risk(futuresClientAsync): + # Test without symbol (get all) + adl_risks = await futuresClientAsync.futures_symbol_adl_risk() + assert isinstance(adl_risks, list) + + # Test with specific symbol (if any symbols available) + if len(adl_risks) > 0: + test_symbol = adl_risks[0]["symbol"] + adl_risk = await futuresClientAsync.futures_symbol_adl_risk(symbol=test_symbol) + assert isinstance(adl_risk, dict) + assert "symbol" in adl_risk + assert "adlRisk" in adl_risk + assert adl_risk["adlRisk"] in ["low", "medium", "high"] + assert adl_risk["symbol"] == test_symbol + async def test_futures_change_leverage(futuresClientAsync): await futuresClientAsync.futures_change_leverage(symbol="LTCUSDT", leverage=10) diff --git a/tests/test_client_futures.py b/tests/test_client_futures.py index c710d91d..e2564e27 100644 --- a/tests/test_client_futures.py +++ b/tests/test_client_futures.py @@ -24,6 +24,11 @@ def test_futures_order_book(futuresClient): assert_ob(order_book) +def test_futures_rpi_depth(futuresClient): + rpi_depth = futuresClient.futures_rpi_depth(symbol="BTCUSDT") + assert_ob(rpi_depth) + + def test_futures_recent_trades(futuresClient): futuresClient.futures_recent_trades(symbol="BTCUSDT") @@ -300,6 +305,22 @@ def test_futures_account(futuresClient): futuresClient.futures_account() +def test_futures_symbol_adl_risk(futuresClient): + # Test without symbol (get all) + adl_risks = futuresClient.futures_symbol_adl_risk() + assert isinstance(adl_risks, list) + + # Test with specific symbol (if any symbols available) + if len(adl_risks) > 0: + test_symbol = adl_risks[0]["symbol"] + adl_risk = futuresClient.futures_symbol_adl_risk(symbol=test_symbol) + assert isinstance(adl_risk, dict) + assert "symbol" in adl_risk + assert "adlRisk" in adl_risk + assert adl_risk["adlRisk"] in ["low", "medium", "high"] + assert adl_risk["symbol"] == test_symbol + + def test_futures_change_leverage(futuresClient): futuresClient.futures_change_leverage(symbol="LTCUSDT", leverage=10)