From 4925710fd9fcec9352861d972a5796f02def612a Mon Sep 17 00:00:00 2001 From: alplabin <122352306+alplabin@users.noreply.github.com> Date: Wed, 3 Jul 2024 18:58:17 +0900 Subject: [PATCH] Release v3.8.0 --- CHANGELOG.md | 15 + README.md | 2 +- binance/__version__.py | 2 +- binance/spot/__init__.py | 2 + binance/spot/_blvt.py | 2 +- binance/spot/_futures.py | 2 +- binance/spot/_gift_card.py | 6 +- binance/spot/_margin.py | 12 +- binance/spot/_portfolio_margin.py | 16 +- binance/spot/_sub_account.py | 8 +- binance/spot/_trade.py | 250 ++++++++- binance/spot/_wallet.py | 16 +- .../websocket/spot/websocket_api/__init__.py | 2 + .../websocket/spot/websocket_api/_trade.py | 520 +++++++++++++++--- docs/source/binance.spot.auto_invest.rst | 62 +++ docs/source/binance.spot.convert.rst | 15 +- docs/source/binance.spot.margin.rst | 32 ++ docs/source/binance.spot.rst | 1 + docs/source/binance.spot.sub_account.rst | 32 +- docs/source/binance.spot.wallet.rst | 6 +- docs/source/getting_started.rst | 2 +- examples/spot/convert/place_limit_order.py | 1 - examples/spot/trade/new_oco_order.py | 10 +- examples/spot/trade/new_oto_order.py | 37 ++ examples/spot/trade/new_otoco_order.py | 37 ++ .../spot/websocket_api/account/account.py | 2 +- .../spot/websocket_api/account/my_trades.py | 2 +- .../spot/websocket_api/account/oco_history.py | 2 +- .../websocket_api/account/order_history.py | 2 +- .../websocket_api/account/order_rate_limit.py | 2 +- .../account/prevented_matches.py | 2 +- .../websocket/spot/websocket_api/app_demo.py | 4 +- .../websocket_api/trade/cancel_oco_order.py | 2 +- .../websocket_api/trade/cancel_open_orders.py | 2 +- .../spot/websocket_api/trade/cancel_order.py | 2 +- .../trade/cancel_replace_order.py | 2 +- .../spot/websocket_api/trade/get_oco_order.py | 2 +- .../trade/get_open_oco_orders.py | 2 +- .../websocket_api/trade/get_open_orders.py | 2 +- .../spot/websocket_api/trade/get_order.py | 2 +- .../spot/websocket_api/trade/new_oco_order.py | 12 +- .../spot/websocket_api/trade/new_order.py | 2 +- .../websocket_api/trade/new_order_test.py | 2 +- .../spot/websocket_api/trade/new_oto_order.py | 49 ++ .../websocket_api/trade/new_otoco_order.py | 48 ++ .../websocket_api/user_data/user_data_ping.py | 2 +- .../user_data/user_data_start.py | 2 +- .../websocket_api/user_data/user_data_stop.py | 2 +- .../spot/websocket_stream/user_data.py | 2 +- tests/spot/trade/test_new_oco_order.py | 14 +- tests/spot/trade/test_new_oto_order.py | 48 ++ tests/spot/trade/test_new_otoco_order.py | 48 ++ 52 files changed, 1162 insertions(+), 191 deletions(-) create mode 100644 docs/source/binance.spot.auto_invest.rst create mode 100644 examples/spot/trade/new_oto_order.py create mode 100644 examples/spot/trade/new_otoco_order.py create mode 100644 examples/websocket/spot/websocket_api/trade/new_oto_order.py create mode 100644 examples/websocket/spot/websocket_api/trade/new_otoco_order.py create mode 100644 tests/spot/trade/test_new_oto_order.py create mode 100644 tests/spot/trade/test_new_otoco_order.py diff --git a/CHANGELOG.md b/CHANGELOG.md index a93f3c4f..857808df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 3.8.0 - 2024-07-04 +### Added +- Trade + - Spot + - `POST /api/v3/orderList/oto` + - `POST /api/v3/orderList/otoco` + - Websocket API + - `orderList.place.oto` + - `orderList.place.otoco` + +### Updated +- Updated and Resolved documentation issue +- Updated `Restful` OCO trade deprecated endpoint `POST /api/v3/order/oco` to `POST /api/v3/orderList/oco` +- Updated `Websocket API` OCO trade deprecated endpoint `orderList.place` to `orderList.place.oco` + ## 3.7.0 - 2024-05-03 ### Added - Convert diff --git a/README.md b/README.md index ffa4a7d9..96ef4e20 100644 --- a/README.md +++ b/README.md @@ -387,7 +387,7 @@ a 10 minutes period. This package handles the pong responses automatically. ```python from binance.websocket.spot.websocket_client import SpotWebsocketClient as WebsocketClient -ws_client = WebsocketClient(stream_url='wss://testnet.binance.vision') +ws_client = WebsocketClient(stream_url='wss://stream.testnet.binance.vision') ``` ## Test Case diff --git a/binance/__version__.py b/binance/__version__.py index 46f67e7f..32a78190 100644 --- a/binance/__version__.py +++ b/binance/__version__.py @@ -1 +1 @@ -__version__ = "3.7.0" +__version__ = "3.8.0" diff --git a/binance/spot/__init__.py b/binance/spot/__init__.py index d2f37914..589a51e6 100644 --- a/binance/spot/__init__.py +++ b/binance/spot/__init__.py @@ -34,6 +34,8 @@ def __init__(self, api_key=None, api_secret=None, **kwargs): from binance.spot._trade import get_open_orders from binance.spot._trade import get_orders from binance.spot._trade import new_oco_order + from binance.spot._trade import new_oto_order + from binance.spot._trade import new_otoco_order from binance.spot._trade import cancel_oco_order from binance.spot._trade import get_oco_order from binance.spot._trade import get_oco_orders diff --git a/binance/spot/_blvt.py b/binance/spot/_blvt.py index a8f2feb6..daf7d1d7 100644 --- a/binance/spot/_blvt.py +++ b/binance/spot/_blvt.py @@ -99,7 +99,7 @@ def user_limit_info(self, **kwargs): GET /sapi/v1/blvt/userLimit - https://binance-docs.github.io/apidocs/spot/en/#get-blvt-user-limit-info + https://binance-docs.github.io/apidocs/spot/en/#get-blvt-user-limit-info-user_data Keyword Args: tokenName (str, optional): BTCDOWN, BTCUP diff --git a/binance/spot/_futures.py b/binance/spot/_futures.py index a2ebf8d5..2eb3a7f6 100644 --- a/binance/spot/_futures.py +++ b/binance/spot/_futures.py @@ -13,7 +13,7 @@ def futures_transfer(self, asset: str, amount: float, type: int, **kwargs): POST /sapi/v1/futures/transfer - https://binance-docs.github.io/apidocs/spot/en/#new-future-account-transfer-futures + https://binance-docs.github.io/apidocs/spot/en/#new-future-account-transfer-user_data Args: asset (str): The asset being transferred, e.g. USDT diff --git a/binance/spot/_gift_card.py b/binance/spot/_gift_card.py index aa4d2a3b..32d727dc 100644 --- a/binance/spot/_gift_card.py +++ b/binance/spot/_gift_card.py @@ -11,7 +11,7 @@ def gift_card_create_code(self, token: str, amount: float, **kwargs): - You have a sufficient balance in your Binance funding wallet - You need Enable Withdrawals for the API Key which requests this endpoint. - https://binance-docs.github.io/apidocs/spot/en/#create-a-binance-code-user_data + https://binance-docs.github.io/apidocs/spot/en/#create-a-single-token-gift-card-user_data Args: token (str): The coin type contained in the Binance Code @@ -36,7 +36,7 @@ def gift_card_redeem_code(self, code: str, **kwargs): Please note that if you enter the wrong code 5 times within 24 hours, you will no longer be able to redeem any Binance Code that day. - https://binance-docs.github.io/apidocs/spot/en/#redeem-a-binance-code-user_data + https://binance-docs.github.io/apidocs/spot/en/#redeem-a-binance-gift-card-user_data Args: code (str): Binance Code @@ -60,7 +60,7 @@ def gift_card_verify_code(self, referenceNo: str, **kwargs): Please note that if you enter the wrong binance code 5 times within an hour, you will no longer be able to verify any binance code for that hour. - https://binance-docs.github.io/apidocs/spot/en/#verify-a-binance-code-user_data + https://binance-docs.github.io/apidocs/spot/en/#verify-binance-gift-card-by-gift-card-number-user_data Args: referenceNo (str): reference number diff --git a/binance/spot/_margin.py b/binance/spot/_margin.py index 538081b6..253a5f4f 100644 --- a/binance/spot/_margin.py +++ b/binance/spot/_margin.py @@ -65,7 +65,7 @@ def margin_all_pairs(self, **kwargs): GET /sapi/v1/margin/allPairs - https://binance-docs.github.io/apidocs/spot/en/#get-all-margin-pairs-market_data + https://binance-docs.github.io/apidocs/spot/en/#get-all-cross-margin-pairs-market_data Keyword Args: symbol (str, optional) @@ -158,7 +158,7 @@ def margin_transfer_history(self, asset: str, **kwargs): GET /sapi/v1/margin/transfer - https://binance-docs.github.io/apidocs/spot/en/#get-transfer-history-user_data + https://binance-docs.github.io/apidocs/spot/en/#get-cross-margin-transfer-history-user_data Args: asset (str) @@ -246,7 +246,7 @@ def margin_account(self, **kwargs): GET /sapi/v1/margin/account - https://binance-docs.github.io/apidocs/spot/en/#query-margin-account-details-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-cross-margin-account-details-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -281,7 +281,7 @@ def margin_open_orders(self, **kwargs): GET /sapi/v1/margin/openOrders - https://binance-docs.github.io/apidocs/spot/en/#query-margin-account-39-s-open-order-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-margin-account-39-s-open-orders-user_data Keyword Args: symbol (str, optional) @@ -316,7 +316,7 @@ def margin_all_orders(self, symbol: str, **kwargs): GET /sapi/v1/margin/allOrders - https://binance-docs.github.io/apidocs/spot/en/#query-margin-account-39-s-all-order-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-margin-account-39-s-all-orders-user_data Args: symbol (str) @@ -417,7 +417,7 @@ def isolated_margin_all_pairs(self, **kwargs): GET /sapi/v1/margin/isolated/allPairs - https://binance-docs.github.io/apidocs/spot/en/#get-all-isolated-margin-symbol-user_data + https://binance-docs.github.io/apidocs/spot/en/#get-all-isolated-margin-symbol-market_data Keyword Args: symbol (str, optional) diff --git a/binance/spot/_portfolio_margin.py b/binance/spot/_portfolio_margin.py index 1d1f1dd7..9edf64a3 100644 --- a/binance/spot/_portfolio_margin.py +++ b/binance/spot/_portfolio_margin.py @@ -13,7 +13,7 @@ def portfolio_margin_account(self, **kwargs): GET /sapi/v1/portfolio/account - https://binance-docs.github.io/apidocs/spot/en/#get-classic-portfolio-margin-account-info-user_data + https://binance-docs.github.io/apidocs/spot/en/#get-portfolio-margin-pro-account-info-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -32,7 +32,7 @@ def portfolio_margin_collateral_rate(self): GET /sapi/v1/portfolio/collateralRate - https://binance-docs.github.io/apidocs/spot/en/#portfolio-margin-collateral-rate-market_data + https://binance-docs.github.io/apidocs/spot/en/#portfolio-margin-pro-collateral-rate-market_data """ @@ -49,7 +49,7 @@ def portfolio_margin_bankruptcy_loan_amount(self, **kwargs): GET /sapi/v1/portfolio/pmLoan - https://binance-docs.github.io/apidocs/spot/en/#classic-portfolio-margin-collateral-rate-market_data + https://binance-docs.github.io/apidocs/spot/en/#query-portfolio-margin-pro-bankruptcy-loan-amount-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -68,7 +68,7 @@ def portfolio_margin_bankruptcy_loan_repay(self, **kwargs): POST /sapi/v1/portfolio/repay - https://binance-docs.github.io/apidocs/spot/en/#portfolio-margin-bankruptcy-loan-repay-user_data + https://binance-docs.github.io/apidocs/spot/en/#portfolio-margin-pro-bankruptcy-loan-repay Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -89,7 +89,7 @@ def query_classic_portfolio_margin_negative_balance_interest_history( GET /sapi/v1/portfolio/interest-history - https://binance-docs.github.io/apidocs/spot/en/#query-classic-portfolio-margin-negative-balance-interest-history-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-portfolio-margin-pro-negative-balance-interest-history-user_data Args: asset (str) @@ -136,7 +136,7 @@ def fund_auto_collection(self, **kwargs): POST /sapi/v1/portfolio/auto-collection - https://binance-docs.github.io/apidocs/spot/en/#fund-auto-collection-usdr_data + https://binance-docs.github.io/apidocs/spot/en/#fund-auto-collection-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -155,7 +155,7 @@ def bnb_transfer(self, transferSide: str, amount: float, **kwargs): POST /sapi/v1/portfolio/bnb-transfer - https://binance-docs.github.io/apidocs/spot/en/#bnb-transfer-usdr_data + https://binance-docs.github.io/apidocs/spot/en/#bnb-transfer-user_data Args: transferSide (str) @@ -240,7 +240,7 @@ def fund_collection_by_asset(self, asset: str, **kwargs): POST /sapi/v1/portfolio/asset-collection - https://binance-docs.github.io/apidocs/spot/en/#fund-collection-by-asset-usdr_data + https://binance-docs.github.io/apidocs/spot/en/#fund-collection-by-asset-user_data Args: asset (str) diff --git a/binance/spot/_sub_account.py b/binance/spot/_sub_account.py index 0ca20a0f..cf0dc523 100644 --- a/binance/spot/_sub_account.py +++ b/binance/spot/_sub_account.py @@ -30,7 +30,7 @@ def sub_account_list(self, **kwargs): GET /sapi/v1/sub-account/list - https://binance-docs.github.io/apidocs/spot/en/#query-sub-account-list-sapi-for-master-account + https://binance-docs.github.io/apidocs/spot/en/#query-sub-account-list-for-master-account Keyword Args: email (str, optional): Sub-account email @@ -49,7 +49,7 @@ def sub_account_assets(self, email: str, **kwargs): GET /sapi/v3/sub-account/assets - https://binance-docs.github.io/apidocs/spot/en/#query-sub-account-assets-sapi-for-master-account + https://binance-docs.github.io/apidocs/spot/en/#query-sub-account-assets-for-master-account Args: email (str) @@ -681,7 +681,7 @@ def sub_account_update_ip_restriction( POST /sapi/v2/sub-account/subAccountApi/ipRestriction - https://binance-docs.github.io/apidocs/spot/en/#update-ip-restriction-for-sub-account-api-key-for-master-account + https://binance-docs.github.io/apidocs/spot/en/#add-ip-restriction-for-sub-account-api-key-for-master-account Args: email (str): Sub-account email @@ -861,7 +861,7 @@ def managed_sub_account_trading_trans_log( GET /sapi/v1/managed-subaccount/queryTransLogForTradeParent - https://binance-docs.github.io/apidocs/spot/en/#query-managed-sub-account-transfer-log-trading-team-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-managed-sub-account-transfer-log-for-trading-team-master-account-user_data Args: email (str): email diff --git a/binance/spot/_trade.py b/binance/spot/_trade.py index ae62a0b6..d6789c77 100644 --- a/binance/spot/_trade.py +++ b/binance/spot/_trade.py @@ -152,7 +152,7 @@ def cancel_and_replace( POST /api/v3/order/cancelReplace - https://binance-docs.github.io/apidocs/spot/en/#cancel-an-existing-order-and-send-a-new-order-user_data + https://binance-docs.github.io/apidocs/spot/en/#cancel-an-existing-order-and-send-a-new-order-trade Args: symbol (str) @@ -246,37 +246,53 @@ def new_oco_order( symbol: str, side: str, quantity: float, - price: float, - stopPrice: float, + aboveType: str, + belowType: str, **kwargs ): - """New OCO (TRADE) + """New Order List - OCO (TRADE) - Post a new oco order + Send in an one-cancels-the-other (OCO) pair, where activation of one order immediately cancels the other. - POST /api/v3/order/oco + - An OCO has 2 legs called the above leg and below leg. + - One of the legs must be a LIMIT_MAKER order and the other leg must be STOP_LOSS or STOP_LOSS_LIMIT order. + - Price restrictions: + - If the OCO is on the SELL side: LIMIT_MAKER price > Last Traded Price > stopPrice + - If the OCO is on the BUY side: LIMIT_MAKER price < Last Traded Price < stopPrice + - OCO counts as 2 orders against the order rate limit. - https://binance-docs.github.io/apidocs/spot/en/#new-oco-trade + Response format for orderReports is selected using the newOrderRespType parameter. The response example is for the RESULT response type. See POST /api/v3/order for more examples. + + POST /api/v3/orderList/oco + + https://binance-docs.github.io/apidocs/spot/en/#new-order-list-oco-trade Args: symbol (str) side (str) quantity (float) - price (float) - stopPrice (float) + aboveType (str) + belowType (str) Keyword Args: - listClientOrderId (str, optional): A unique Id for the entire orderList - limitClientOrderId (str, optional) - limitStrategyId (int, optional) - limitStrategyType (int, optional): The value cannot be less than 1000000. - limitIcebergQty (float, optional) - stopClientOrderId (str, optional) - stopStrategyId (int, optional) - stopStrategyType (int, optional): The value cannot be less than 1000000. - stopLimitPrice (float, optional) - stopIcebergQty (float, optional) - stopLimitTimeInForce (str, optional) - newOrderRespType (str, optional): Set the response JSON. + listClientOrderId (str, optional): Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same listClientOrderId is accepted only when the previous one is filled or completely expired. listClientOrderId is distinct from the aboveClientOrderId and the belowCLientOrderId + aboveClientOrderId (str, optional): Supported values : STOP_LOSS_LIMIT, STOP_LOSS, LIMIT_MAKER + aboveIcebergQty (int, optional): Note that this can only be used if aboveTimeInForce is GTC. + abovePrice (float, optional) + aboveStopPrice (float, optional): Can be used if aboveType is STOP_LOSS or STOP_LOSS_LIMIT. Either aboveStopPrice or aboveTrailingDelta or both, must be specified. + aboveTrailingDelta (int, optional) + aboveTimeInForce (float, optional): Required if the aboveType is STOP_LOSS_LIMIT. + aboveStrategyId (int, optional): Arbitrary numeric value identifying the above leg order within an order strategy. + aboveStrategyType (int, optional): Arbitrary numeric value identifying the above leg order strategy. Values smaller than 1000000 are reserved and cannot be used. + belowClientOrderId (str, optional): Arbitrary unique ID among open orders for the below leg order. Automatically generated if not sent + belowIcebergQty (int, optional): Note that this can only be used if belowTimeInForce is GTC. + belowPrice (float, optional) + belowStopPrice (float, optional): Can be used if belowType is STOP_LOSS or STOP_LOSS_LIMIT. Either belowStopPrice or belowTrailingDelta or both, must be specified. + belowTrailingDelta (int, optional) + belowTimeInForce (str, optional): Required if the belowType is STOP_LOSS_LIMIT. + belowStrategyId (int, optional): Arbitrary numeric value identifying the below leg order within an order strategy. + belowStrategyType (int, optional): Arbitrary numeric value identifying the below leg order strategy. Values smaller than 1000000 are reserved and cannot be used. + newOrderRespType (str, optional): Select response format: ACK, RESULT, FULL + selfTradePreventionMode (str, optional): The allowed enums is dependent on what is configured on the symbol. The possible supported values are EXPIRE_TAKER, EXPIRE_MAKER, EXPIRE_BOTH, NONE. recvWindow (int, optional): The value cannot be greater than 60000 """ @@ -285,20 +301,194 @@ def new_oco_order( [symbol, "symbol"], [side, "side"], [quantity, "quantity"], - [price, "price"], - [stopPrice, "stopPrice"], + [aboveType, "aboveType"], + [belowType, "belowType"], ] ) params = { "symbol": symbol, "side": side, "quantity": quantity, - "price": price, - "stopPrice": stopPrice, + "aboveType": aboveType, + "belowType": belowType, + **kwargs, + } + + url_path = "/api/v3/orderList/oco" + return self.sign_request("POST", url_path, params) + + +def new_oto_order( + self, + symbol: str, + workingType: str, + workingSide: str, + workingPrice: float, + workingQuantity: float, + pendingType: str, + pendingSide: str, + pendingQuantity: float, + **kwargs +): + """New Order List - OTO (TRADE) + + + - An OTO (One-Triggers-the-Other) is an order list comprised of 2 orders. + - The first order is called the working order and must be LIMIT or LIMIT_MAKER. Initially, only the working order goes on the order book. + - The second order is called the pending order. It can be any order type except for MARKET orders using parameter quoteOrderQty. The pending order is only placed on the order book when the working order gets fully filled. + - If either the working order or the pending order is cancelled individually, the other order in the order list will also be canceled or expired. + - When the order list is placed, if the working order gets immediately fully filled, the placement response will show the working order as FILLED but the pending order will still appear as PENDING_NEW. You need to query the status of the pending order again to see its updated status. + - OTOs count as 2 orders against the order rate limit, EXCHANGE_MAX_NUM_ORDERS filter and MAX_NUM_ORDERS filter. + + POST /api/v3/orderList/oto + + https://binance-docs.github.io/apidocs/spot/en/#new-order-list-oto-trade + + Args: + symbol (str) + workingType (str) + workingSide (str) + workingPrice (float) + workingQuantity (float) + pendingType (str) + pendingSide (str) + pendingQuantity (float) + Keyword Args: + listClientOrderId (str, optional): Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same listClientOrderId is accepted only when the previous one is filled or completely expired. listClientOrderId is distinct from the workingClientOrderId and the pendingClientOrderId + newOrderRespType (str, optional): Format of the JSON response. Supported values: ACK, FULL, RESULT + selfTradePreventionMode (str, optional): The allowed values are dependent on what is configured on the symbol. + workingClientOrderId (str, optional): Arbitrary unique ID among open orders for the working order. Automatically generated if not sent. + workingIcebergQty (float, optional): This can only be used if workingTimeInForce is GTC or if workingType is LIMIT_MAKER. + workingTimeInForce (str, optional): Supported values: FOK, IOC, GTC + workingStrategyId (int, optional): Arbitrary numeric value identifying the working order within an order strategy. + workingStrategyType (int, optional): Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used. + pendingClientOrderId (str, optional): Arbitrary unique ID among open orders for the pending order. Automatically generated if not sent. + pendingPrice (float, optional) + pendingStopPrice (float, optional) + pendingTrailingDelta (float, optional) + pendingIcebergQty (float, optional): This can only be used if pendingTimeInForce is GTC or if pendingType is LIMIT_MAKER. + pendingTimeInForce (str, optional): Supported values: GTC, FOK, IOC + pendingStrategyId (int, optional): Arbitrary numeric value identifying the pending order within an order strategy. + pendingStrategyType (int, optional): Arbitrary numeric value identifying the pending order strategy. Values smaller than 1000000 are reserved and cannot be used. + recvWindow (int, optional): The value cannot be greater than 60000 + """ + check_required_parameters( + [ + [symbol, "symbol"], + [workingType, "workingType"], + [workingSide, "workingSide"], + [workingPrice, "workingPrice"], + [workingQuantity, "workingQuantity"], + [pendingType, "pendingType"], + [pendingSide, "pendingSide"], + [pendingQuantity, "pendingQuantity"], + ] + ) + params = { + "symbol": symbol, + "workingType": workingType, + "workingSide": workingSide, + "workingPrice": workingPrice, + "workingQuantity": workingQuantity, + "pendingType": pendingType, + "pendingSide": pendingSide, + "pendingQuantity": pendingQuantity, + **kwargs, + } + + url_path = "/api/v3/orderList/oto" + return self.sign_request("POST", url_path, params) + + +def new_otoco_order( + self, + symbol: str, + workingType: str, + workingSide: str, + workingPrice: float, + workingQuantity: float, + pendingSide: str, + pendingQuantity: float, + pendingAboveType: str, + **kwargs +): + """New Order List - OTOCO (TRADE) + + Place an OTOCO. + + - An OTOCO (One-Triggers-One-Cancels-the-Other) is an order list comprised of 3 orders. + - The first order is called the working order and must be LIMIT or LIMIT_MAKER. Initially, only the working order goes on the order book. + - The behavior of the working order is the same as the OTO. + - OTOCO has 2 pending orders (pending above and pending below), forming an OCO pair. The pending orders are only placed on the order book when the working order gets fully filled. + - The rules of the pending above and pending below follow the same rules as the Order List OCO. + - OTOCOs count as 3 orders against the order rate limit, EXCHANGE_MAX_NUM_ORDERS filter, and MAX_NUM_ORDERS filter. + + POST /api/v3/orderList/otoco + + https://binance-docs.github.io/apidocs/spot/en/#new-order-list-oto-trade + + Args: + symbol (str) + workingType (str) + workingSide (str) + workingPrice (float) + workingQuantity (float) + pendingSide (str) + pendingQuantity (float) + pendingAboveType (str) + Keyword Args: + listClientOrderId (str, optional): Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same listClientOrderId is accepted only when the previous one is filled or completely expired. listClientOrderId is distinct from the workingClientOrderId, pendingAboveClientOrderId, and the pendingBelowClientOrderId. + newOrderRespType (str, optional): Format the JSON response. Supported values: ACK, FULL, RESPONSE + selfTradePreventionMode (str, optional): The allowed values are dependent on what is configured on the symbol. + workingClientOrderId (str, optional): Arbitrary unique ID among open orders for the working order. Automatically generated if not sent. + workingIcebergQty (float, optional): This can only be used if workingTimeInForce is GTC or if workingType is LIMIT_MAKER. + workingTimeInForce (str, optional): Supported values: GTC, IOC, FOK + workingStrategyId (int, optional): Arbitrary numeric value identifying the working order within an order strategy. + workingStrategyType (int, optional): Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used. + pendingAboveClientOrderId (str, optional): Arbitrary unique ID among open orders for the pending above order. Automatically generated if not sent. + pendingAbovePrice (float, optional) + pendingAboveStopPrice (float, optional) + pendingAboveTrailingDelta (float, optional) + pendingAboveIcebergQty (float, optional): This can only be used if pendingAboveTimeInForce is GTC or if pendingAboveType is LIMIT_MAKER. + pendingAboveTimeInForce (str, optional) + pendingAboveStrategyId (int, optional): Arbitrary numeric value identifying the pending above order within an order strategy. + pendingAboveStrategyType (int, optional): Arbitrary numeric value identifying the pending above order strategy. Values smaller than 1000000 are reserved and cannot be used. + pendingBelowType (str, optional): Supported values: LIMIT_MAKER, STOP_LOSS, and STOP_LOSS_LIMIT + pendingBelowClientOrderId (str, optional): Arbitrary unique ID among open orders for the pending below order. Automatically generated if not sent. + pendingBelowPrice (float, optional) + pendingBelowStopPrice (float, optional) + pendingBelowTrailingDelta (float, optional) + pendingBelowIcebergQty (float, optional): This can only be used if pendingBelowTimeInForce is GTC or if pendingBelowType is LIMIT_MAKER. + pendingBelowTimeInForce (str, optional) + pendingBelowStrategyId (int, optional): Arbitrary numeric value identifying the pending below order within an order strategy. + pendingBelowStrategyType (int, optional): Arbitrary numeric value identifying the pending below order strategy. Values smaller than 1000000 are reserved and cannot be used. + recvWindow (int, optional): The value cannot be greater than 60000 + """ + check_required_parameters( + [ + [symbol, "symbol"], + [workingType, "workingType"], + [workingSide, "workingSide"], + [workingPrice, "workingPrice"], + [workingQuantity, "workingQuantity"], + [pendingSide, "pendingSide"], + [pendingQuantity, "pendingQuantity"], + [pendingAboveType, "pendingAboveType"], + ] + ) + params = { + "symbol": symbol, + "workingType": workingType, + "workingSide": workingSide, + "workingPrice": workingPrice, + "workingQuantity": workingQuantity, + "pendingSide": pendingSide, + "pendingQuantity": pendingQuantity, + "pendingAboveType": pendingAboveType, **kwargs, } - url_path = "/api/v3/order/oco" + url_path = "/api/v3/orderList/otoco" return self.sign_request("POST", url_path, params) @@ -309,7 +499,7 @@ def cancel_oco_order(self, symbol, **kwargs): DELETE /api/v3/orderList - https://binance-docs.github.io/apidocs/spot/en/#cancel-oco-trade + https://binance-docs.github.io/apidocs/spot/en/#cancel-order-lists-trade Args: symbol (str) @@ -333,7 +523,7 @@ def get_oco_order(self, **kwargs): GET /api/v3/orderList - https://binance-docs.github.io/apidocs/spot/en/#query-oco-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-order-lists-user_data Keyword Args: orderListId (int, optional): Either orderListId or listClientOrderId must be provided @@ -351,7 +541,7 @@ def get_oco_orders(self, **kwargs): GET /api/v3/allOrderList - https://binance-docs.github.io/apidocs/spot/en/#query-all-oco-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-all-order-lists-user_data Keyword Args: fromId (int, optional): If supplied, neither startTime or endTime can be provided @@ -370,7 +560,7 @@ def get_oco_open_orders(self, **kwargs): GET /api/v3/openOrderList - https://binance-docs.github.io/apidocs/spot/en/#query-open-oco-user_data + https://binance-docs.github.io/apidocs/spot/en/#query-open-order-lists-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 diff --git a/binance/spot/_wallet.py b/binance/spot/_wallet.py index bf60335f..736cd6cf 100644 --- a/binance/spot/_wallet.py +++ b/binance/spot/_wallet.py @@ -10,7 +10,7 @@ def system_status(self): GET /sapi/v1/system/status - https://binance-docs.github.io/apidocs/spot/en/#system-status-sapi-system + https://binance-docs.github.io/apidocs/spot/en/#system-status-system """ return self.query("/sapi/v1/system/status") @@ -143,7 +143,7 @@ def withdraw_history(self, **kwargs): GET /sapi/v1/capital/withdraw/history - https://binance-docs.github.io/apidocs/spot/en/#deposit-history-user_data + https://binance-docs.github.io/apidocs/spot/en/#withdraw-history-supporting-network-user_data Keyword Args: coin (str, optional) @@ -185,7 +185,7 @@ def account_status(self, **kwargs): GET /sapi/v1/account/status - https://binance-docs.github.io/apidocs/spot/en/#account-status-sapi-user_data + https://binance-docs.github.io/apidocs/spot/en/#account-status-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -200,7 +200,7 @@ def api_trading_status(self, **kwargs): GET /sapi/v1/account/apiTradingStatus - https://binance-docs.github.io/apidocs/spot/en/#account-api-trading-status-sapi-user_data + https://binance-docs.github.io/apidocs/spot/en/#account-api-trading-status-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -215,7 +215,7 @@ def dust_log(self, **kwargs): GET /sapi/v1/asset/dribblet - https://binance-docs.github.io/apidocs/spot/en/#dustlog-sapi-user_data + https://binance-docs.github.io/apidocs/spot/en/#dustlog-user_data Keyword Args: accountType (str, optional): SPOT or MARGIN, default SPOT @@ -320,7 +320,7 @@ def asset_detail(self, **kwargs): GET /sapi/v1/asset/assetDetail - https://binance-docs.github.io/apidocs/spot/en/#asset-detail-sapi-user_data + https://binance-docs.github.io/apidocs/spot/en/#asset-detail-user_data Keyword Args: recvWindow (int, optional): The value cannot be greater than 60000 @@ -335,7 +335,7 @@ def trade_fee(self, **kwargs): GET /sapi/v1/asset/tradeFee - https://binance-docs.github.io/apidocs/spot/en/#trade-fee-sapi-user_data + https://binance-docs.github.io/apidocs/spot/en/#trade-fee-user_data Keyword Args: symbol (str, optional) @@ -558,7 +558,7 @@ def one_click_arrival_deposit_apply(self, **kwargs): POST /sapi/v1/capital/deposit/credit-apply - https://binance-docs.github.io/apidocs/spot/en/#one-click-arrival-deposit-apply-user_data + https://binance-docs.github.io/apidocs/spot/en/#one-click-arrival-deposit-apply-for-expired-address-deposit-user_data Keyword Args: depositId (int, optional): Deposit record Id, priority use diff --git a/binance/websocket/spot/websocket_api/__init__.py b/binance/websocket/spot/websocket_api/__init__.py index f889525e..06a1e7e1 100644 --- a/binance/websocket/spot/websocket_api/__init__.py +++ b/binance/websocket/spot/websocket_api/__init__.py @@ -68,6 +68,8 @@ def __init__( from binance.websocket.spot.websocket_api._trade import get_open_orders from binance.websocket.spot.websocket_api._trade import cancel_open_orders from binance.websocket.spot.websocket_api._trade import new_oco_order + from binance.websocket.spot.websocket_api._trade import new_oto_order + from binance.websocket.spot.websocket_api._trade import new_otoco_order from binance.websocket.spot.websocket_api._trade import get_oco_order from binance.websocket.spot.websocket_api._trade import cancel_oco_order from binance.websocket.spot.websocket_api._trade import get_open_oco_orders diff --git a/binance/websocket/spot/websocket_api/_trade.py b/binance/websocket/spot/websocket_api/_trade.py index 316604f8..405c0d0f 100644 --- a/binance/websocket/spot/websocket_api/_trade.py +++ b/binance/websocket/spot/websocket_api/_trade.py @@ -737,29 +737,42 @@ def cancel_open_orders(self, symbol: str, **kwargs): self.send(payload) -def new_oco_order(self, symbol: str, side: str, price, quantity, **kwargs): - """Place a new OCO Order (TRADE) +def new_oco_order( + self, + symbol: str, + side: str, + quantity: float, + aboveType: str, + belowType: str, + **kwargs +): + """Place new Order list - OCO (TRADE) Args: symbol (str): Symbol. side (str): BUY or SELL. - price (float): Price. quantity (float): Quantity. + aboveType (str): Supported values : STOP_LOSS_LIMIT, STOP_LOSS, LIMIT_MAKER + belowType (str): Supported values : STOP_LOSS_LIMIT, STOP_LOSS, LIMIT_MAKER. Keyword Arguments: listClientOrderId (str): A unique id for the entire order list. - limitClientOrderId (str): A unique id for the limit order. - limitIcebergQty (float): Iceberg quantity. - limitStrategyId (int): Strategy id. - limitStrategyType (int): Strategy type. - stopPrice (float): Stop price. - trailingDelta (float): Trailing delta. - stopClientOrderId (str): A unique id for the stop loss order. - stopLimitPrice (float): Stop limit price. - stopLimitTimeInForce (str): GTC or FOK. - stopIcebergQty (float): Iceberg quantity. - stopStrategyId (int): Strategy id. - stopStrategyType (int): Strategy type. - newOrderRespType (str): ACK, RESULT, or FULL; MARKET and LIMIT order types default to FULL, all other orders default to ACK. - selfTradePreventionMode (str): NONE, EXPIRE_TAKER, EXPIRE_MAKER or EXPIRE_BOTH. + aboveClientOrderId (str): Arbitrary unique ID among open orders for the above leg order. Automatically generated if not sent + aboveIcebergQty (int): Note that this can only be used if aboveTimeInForce is GTC. + abovePrice (float) + aboveStopPrice (float): Can be used if aboveType is STOP_LOSS or STOP_LOSS_LIMIT. Either aboveStopPrice or aboveTrailingDelta or both, must be specified. + aboveTrailingDelta (int) + aboveTimeInForce (float): Required if the aboveType is STOP_LOSS_LIMIT. + aboveStrategyId (int): Arbitrary numeric value identifying the above leg order within an order strategy. + aboveStrategyType (int): Arbitrary numeric value identifying the above leg order strategy. Values smaller than 1000000 are reserved and cannot be used. + belowClientOrderId (str) + belowIcebergQty (int): Note that this can only be used if belowTimeInForce is GTC. + belowPrice (float) + belowStopPrice (float): Can be used if belowType is STOP_LOSS or STOP_LOSS_LIMIT. Either belowStopPrice or belowTrailingDelta or both, must be specified. + belowTrailingDelta (int) + belowTimeInForce (str): Required if the belowType is STOP_LOSS_LIMIT. + belowStrategyId (int): Arbitrary numeric value identifying the below leg order within an order strategy. + belowStrategyType (int): Arbitrary numeric value identifying the below leg order strategy. Values smaller than 1000000 are reserved and cannot be used. + newOrderRespType (str): Select response format: ACK, RESULT, FULL + selfTradePreventionMode (str): The allowed enums is dependent on what is configured on the symbol. The possible supported values are EXPIRE_TAKER, EXPIRE_MAKER, EXPIRE_BOTH, NONE. recvWindow (int): Recv window. Message sent: @@ -767,85 +780,89 @@ def new_oco_order(self, symbol: str, side: str, price, quantity, **kwargs): .. code-block:: json { - "id": "56374a46-3061-486b-a311-99ee972eb648", - "method": "orderList.place", - "params": { - "symbol": "BTCUSDT", - "side": "SELL", - "price": "23420.00000000", - "quantity": "0.00650000", - "stopPrice": "23410.00000000", - "stopLimitPrice": "23405.00000000", - "stopLimitTimeInForce": "GTC", - "newOrderRespType": "RESULT", - "apiKey": "vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A", - "signature": "6689c2a36a639ff3915c2904871709990ab65f3c7a9ff13857558fd350315c35", - "timestamp": 1660801713767 + "id": "56374a46-3261-486b-a211-99ed972eb648", + "method": "orderList.place.oco", + "params": + { + "symbol": "LTCBNB", + "side": "BUY", + "quantity": 1, + "timestamp": 1711062760647, + "aboveType": "STOP_LOSS_LIMIT", + "abovePrice": "1.5", + "aboveStopPrice": "1.50000001", + "aboveTimeInForce": "GTC", + "belowType": "LIMIT_MAKER", + "belowPrice": "1.49999999", + "apiKey": "duwNf97YPLqhFIk7kZF0dDdGYVAXStA7BeEz0fIT9RAhUbixJtyS6kJ3hhzJsRXC", + "signature": "64614cfd8dd38260d4fd86d3c455dbf4b9d1c8a8170ea54f700592a986c30ddb" } } + Response: .. code-block:: json { - "id": "57833dc0-e3f2-43fb-ba20-46480973b0aa", + "id": "56374a46-3261-486b-a211-99ed972eb648", "status": 200, - "result": { - "orderListId": 1274512, + "result": + { + "orderListId": 2, "contingencyType": "OCO", "listStatusType": "EXEC_STARTED", "listOrderStatus": "EXECUTING", - "listClientOrderId": "08985fedd9ea2cf6b28996", - "transactionTime": 1660801713793, - "symbol": "BTCUSDT", + "listClientOrderId": "cKPMnDCbcLQILtDYM4f4fX", + "transactionTime": 1711062760648, + "symbol": "LTCBNB", "orders": [ { - "symbol": "BTCUSDT", - "orderId": 12569138901, - "clientOrderId": "BqtFCj5odMoWtSqGk2X9tU" + "symbol": "LTCBNB", + "orderId": 2, + "clientOrderId": "0m6I4wfxvTUrOBSMUl0OPU" }, { - "symbol": "BTCUSDT", - "orderId": 12569138902, - "clientOrderId": "jLnZpj5enfMXTuhKB1d0us" + "symbol": "LTCBNB", + "orderId": 3, + "clientOrderId": "Z2IMlR79XNY5LU0tOxrWyW" } ], "orderReports": [ { - "symbol": "BTCUSDT", - "orderId": 12569138901, - "orderListId": 1274512, - "clientOrderId": "BqtFCj5odMoWtSqGk2X9tU", - "transactTime": 1660801713793, - "price": "23410.00000000", - "origQty": "0.00650000", - "executedQty": "0.00000000", + "symbol": "LTCBNB", + "orderId": 2, + "orderListId": 2, + "clientOrderId": "0m6I4wfxvTUrOBSMUl0OPU", + "transactTime": 1711062760648, + "price": "1.50000000", + "origQty": "1.000000", + "executedQty": "0.000000", "cummulativeQuoteQty": "0.00000000", "status": "NEW", "timeInForce": "GTC", "type": "STOP_LOSS_LIMIT", - "side": "SELL", - "stopPrice": "23405.00000000", + "side": "BUY", + "stopPrice": "1.50000001", "workingTime": -1, "selfTradePreventionMode": "NONE" }, { - "symbol": "BTCUSDT", - "orderId": 12569138902, - "orderListId": 1274512, - "clientOrderId": "jLnZpj5enfMXTuhKB1d0us", - "transactTime": 1660801713793, - "price": "23420.00000000", - "origQty": "0.00650000", - "executedQty": "0.00000000", + "symbol": "LTCBNB", + "orderId": 3, + "orderListId": 2, + "clientOrderId": "Z2IMlR79XNY5LU0tOxrWyW", + "transactTime": 1711062760648, + "price": "1.49999999", + "origQty": "1.000000", + "executedQty": "0.000000", "cummulativeQuoteQty": "0.00000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT_MAKER", - "side": "SELL", - "workingTime": 1660801713793, + "side": "BUY", + "workingTime": 1711062760648, "selfTradePreventionMode": "NONE" } ] @@ -869,25 +886,396 @@ def new_oco_order(self, symbol: str, side: str, price, quantity, **kwargs): "rateLimitType": "REQUEST_WEIGHT", "interval": "MINUTE", "intervalNum": 1, - "limit": 1200, + "limit": 6000, "count": 1 } ] } + """ parameters = { "symbol": symbol, "side": side, - "price": price, "quantity": quantity, + "aboveType": aboveType, + "belowType": belowType, + **kwargs, + } + + payload = { + "id": parameters.pop("id", get_uuid()), + "method": "orderList.place.oco", + "params": websocket_api_signature(self.api_key, self.api_secret, parameters), + } + self.send(payload) + + +def new_oto_order( + self, + symbol: str, + workingType: str, + workingSide: str, + workingPrice: float, + workingQuantity: float, + pendingType: str, + pendingSide: str, + pendingQuantity: float, + **kwargs +): + """Place new Order list - OTO (TRADE) + Args: + symbol (str): Symbol. + workingType (str): Supported values : LIMIT, MARKET + workingSide (str): BUY or SELL. + workingPrice (float) + workingQuantity (float) + pendingType (str): Supported values : LIMIT, MARKET + pendingSide (str): BUY or SELL. + pendingQuantity (float) + Keyword Args: + listClientOrderId (str): Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same listClientOrderId is accepted only when the previous one is filled or completely expired. listClientOrderId is distinct from the workingClientOrderId and the pendingClientOrderId. + newOrderRespType (str): Sets the response JSON. Supported values: ACK, FULL, RESULT + selfTradePreventionMode (str): The allowed enums is dependent on what is configured on the symbol. + workingClientOrderId (str): Arbitrary unique ID among open orders for the working order. Automatically generated if not sent. + workingTimeInForce (str): Supported values: GTC, FOK, IOC + workingStrategyId (int): Arbitrary numeric value identifying the working order within an order strategy. + workingStrategyType (int): Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used. + pendingClientOrderId (str): Arbitrary unique ID among open orders for the pending order. Automatically generated if not sent. + pendingPrice (float) + pendingStopPrice (float) + pendingTrailingDelta (float) + pendingIcebergQty (float): Note this can only be used if pendingTimeInForce is GTC or if pendingType is LIMIT_MAKER. + pendingTimeInForce (str): Supported values: GTC, FOK, IOC + pendingStrategyId (int): Arbitrary numeric value identifying the pending order within an order strategy. + pendingStrategyType (int): Arbitrary numeric value identifying the pending order strategy. Values smaller than 1000000 are reserved and cannot be used. + recvWindow (int): Recv window. + + Message sent: + + .. code-block:: json + + { + "id": "1712544395950", + "method": "orderList.place.oto", + "params": { + "signature": "3e1e5ac8690b0caf9a2afd5c5de881ceba69939cc9d817daead5386bf65d0cbb", + "apiKey": "Rf07JlnL9PHVxjs27O5CvKNyOsV4qJ5gXdrRfpvlOdvMZbGZbPO5Ce2nIwfRP0iA", + "pendingQuantity": 1, + "pendingSide": "BUY", + "pendingType": "MARKET", + "symbol": "LTCBNB", + "recvWindow": "5000", + "timestamp": "1712544395951", + "workingPrice": 1, + "workingQuantity": 1, + "workingSide": "SELL", + "workingTimeInForce": "GTC", + "workingType": "LIMIT" + } + } + + Response: + + .. code-block:: json + + { + "id": "1712544395950", + "status": 200, + "result": { + "orderListId": 626, + "contingencyType": "OTO", + "listStatusType": "EXEC_STARTED", + "listOrderStatus": "EXECUTING", + "listClientOrderId": "KA4EBjGnzvSwSCQsDdTrlf", + "transactionTime": 1712544395981, + "symbol": "1712544378871", + "orders": [ + { + "symbol": "LTCBNB", + "orderId": 13, + "clientOrderId": "YiAUtM9yJjl1a2jXHSp9Ny" + }, + { + "symbol": "LTCBNB", + "orderId": 14, + "clientOrderId": "9MxJSE1TYkmyx5lbGLve7R" + } + ], + "orderReports": [ + { + "symbol": "LTCBNB", + "orderId": 13, + "orderListId": 626, + "clientOrderId": "YiAUtM9yJjl1a2jXHSp9Ny", + "transactTime": 1712544395981, + "price": "1.000000", + "origQty": "1.000000", + "executedQty": "0.000000", + "cummulativeQuoteQty": "0.000000", + "status": "NEW", + "timeInForce": "GTC", + "type": "LIMIT", + "side": "SELL", + "workingTime": 1712544395981, + "selfTradePreventionMode": "NONE" + }, + { + "symbol": "LTCBNB", + "orderId": 14, + "orderListId": 626, + "clientOrderId": "9MxJSE1TYkmyx5lbGLve7R", + "transactTime": 1712544395981, + "price": "0.000000", + "origQty": "1.000000", + "executedQty": "0.000000", + "cummulativeQuoteQty": "0.000000", + "status": "PENDING_NEW", + "timeInForce": "GTC", + "type": "MARKET", + "side": "BUY", + "workingTime": -1, + "selfTradePreventionMode": "NONE" + } + ] + }, + "rateLimits": [ + { + "rateLimitType": "ORDERS", + "interval": "MINUTE", + "intervalNum": 1, + "limit": 10000000, + "count": 10 + }, + { + "rateLimitType": "REQUEST_WEIGHT", + "interval": "MINUTE", + "intervalNum": 1, + "limit": 1000, + "count": 38 + } + ] + } + + """ + + parameters = { + "symbol": symbol, + "workingType": workingType, + "workingSide": workingSide, + "workingPrice": workingPrice, + "workingQuantity": workingQuantity, + "pendingType": pendingType, + "pendingSide": pendingSide, + "pendingQuantity": pendingQuantity, + **kwargs, + } + + payload = { + "id": parameters.pop("id", get_uuid()), + "method": "orderList.place.oto", + "params": websocket_api_signature(self.api_key, self.api_secret, parameters), + } + self.send(payload) + + +def new_otoco_order( + self, + symbol: str, + workingType: str, + workingSide: str, + workingPrice: float, + pendingSide: str, + pendingQuantity: float, + pendingAboveType: str, + **kwargs +): + """Place new Order list - OTOCO (TRADE) + Args: + symbol (str): Symbol. + workingType (str): Supported values: LIMIT, LIMIT_MAKER + workingSide (str): Supported values: BUY, SELL + workingPrice (float) + pendingSide (str): Supported values: BUY, SELL + pendingQuantity (float) + pendingAboveType (str): Supported values: LIMIT_MAKER, STOP_LOSS, and STOP_LOSS_LIMIT + Keyword Args: + listClientOrderId (str): Arbitrary unique ID among open order lists. Automatically generated if not sent. A new order list with the same listClientOrderId is accepted only when the previous one is filled or completely expired. listClientOrderId is distinct from the workingClientOrderId, pendingAboveClientOrderId, and the pendingBelowClientOrderId + newOrderRespType (str): Format the JSON response. Supported values: ACK, FULL, RESULT + selfTradePreventionMode (str): The allowed enums is dependent on what is configured on the symbol. + workingClientOrderId (str): Arbitrary unique ID among open orders for the working order. Automatically generated if not sent. + workingQuantity (float) + workingIcebergQty (float): This can only be used if workingTimeInForce is GTC or if workingType is LIMIT_MAKER. + workingTimeInForce (str): Supported values: GTC, FOK, IOC + workingStrategyId (int): Arbitrary numeric value identifying the working order within an order strategy. + workingStrategyType (int): Arbitrary numeric value identifying the working order strategy. Values smaller than 1000000 are reserved and cannot be used. + pendingAboveClientOrderId (str): Arbitrary unique ID among open orders for the pending above order. Automatically generated if not sent. + pendingAbovePrice (float) + pendingAboveStopPrice (float) + pendingAboveTrailingDelta (float) + pendingAboveIcebergQty (float) + pendingAboveTimeInForce (str): This can only be used if pendingAboveTimeInForce is GTC or if pendingAboveType is LIMIT_MAKER. + pendingAboveStrategyId (int): Arbitrary numeric value identifying the pending above order within an order strategy. + pendingAboveStrategyType (int): Arbitrary numeric value identifying the pending above order strategy. Values smaller than 1000000 are reserved and cannot be used. + pendingBelowType (str): Supported values: LIMIT_MAKER, STOP_LOSS, and STOP_LOSS_LIMIT + pendingBelowClientOrderId (str): Arbitrary unique ID among open orders for the pending below order. Automatically generated if not sent. + pendingBelowPrice (float) + pendingBelowStopPrice (float) + pendingBelowTrailingDelta (float) + pendingBelowIcebergQty (float): Note this can only be used if pendingBelowTimeInForce is GTC or if pendingBelowType is LIMIT_MAKER. + pendingBelowTimeInForce (str) + pendingBelowStrategyId (int): Arbitrary numeric value identifying the pending below order within an order strategy. + pendingBelowStrategyType (int): Arbitrary numeric value identifying the pending below order strategy. Values smaller than 1000000 are reserved and cannot be used. + recvWindow (int): Recv window. + + Message sent: + + .. code-block:: json + + { + "id": "1712544408508", + "method": "orderList.place.otoco", + "params": { + "signature": "c094473304374e1b9c5f7e2558358066cfa99df69f50f63d09cfee755136cb07", + "apiKey": "Rf07JlnL9PHVxjs27O5CvKNyOsV4qJ5gXdrRfpvlOdvMZbGZbPO5Ce2nIwfRP0iA", + "pendingQuantity": 5, + "pendingSide": "SELL", + "pendingBelowPrice": 5, + "pendingBelowType": "LIMIT_MAKER", + "pendingAboveStopPrice": 0.5, + "pendingAboveType": "STOP_LOSS", + "symbol": "LTCBNB", + "recvWindow": "5000", + "timestamp": "1712544408509", + "workingPrice": 1.5, + "workingQuantity": 1, + "workingSide": "BUY", + "workingTimeInForce": "GTC", + "workingType": "LIMIT" + } + } + + Response: + + .. code-block:: json + + { + "id": "1712544408508", + "status": 200, + "result": { + "orderListId": 629, + "contingencyType": "OTO", + "listStatusType": "EXEC_STARTED", + "listOrderStatus": "EXECUTING", + "listClientOrderId": "GaeJHjZPasPItFj4x7Mqm6", + "transactionTime": 1712544408537, + "symbol": "1712544378871", + "orders": [ + { + "symbol": "1712544378871", + "orderId": 23, + "clientOrderId": "OVQOpKwfmPCfaBTD0n7e7H" + }, + { + "symbol": "1712544378871", + "orderId": 24, + "clientOrderId": "YcCPKCDMQIjNvLtNswt82X" + }, + { + "symbol": "1712544378871", + "orderId": 25, + "clientOrderId": "ilpIoShcFZ1ZGgSASKxMPt" + } + ], + "orderReports": [ + { + "symbol": "LTCBNB", + "orderId": 23, + "orderListId": 629, + "clientOrderId": "OVQOpKwfmPCfaBTD0n7e7H", + "transactTime": 1712544408537, + "price": "1.500000", + "origQty": "1.000000", + "executedQty": "0.000000", + "cummulativeQuoteQty": "0.000000", + "status": "NEW", + "timeInForce": "GTC", + "type": "LIMIT", + "side": "BUY", + "workingTime": 1712544408537, + "selfTradePreventionMode": "NONE" + }, + { + "symbol": "LTCBNB", + "orderId": 24, + "orderListId": 629, + "clientOrderId": "YcCPKCDMQIjNvLtNswt82X", + "transactTime": 1712544408537, + "price": "0.000000", + "origQty": "5.000000", + "executedQty": "0.000000", + "cummulativeQuoteQty": "0.000000", + "status": "PENDING_NEW", + "timeInForce": "GTC", + "type": "STOP_LOSS", + "side": "SELL", + "stopPrice": "0.500000", + "workingTime": -1, + "selfTradePreventionMode": "NONE" + }, + { + "symbol": "LTCBNB", + "orderId": 25, + "orderListId": 629, + "clientOrderId": "ilpIoShcFZ1ZGgSASKxMPt", + "transactTime": 1712544408537, + "price": "5.000000", + "origQty": "5.000000", + "executedQty": "0.000000", + "cummulativeQuoteQty": "0.000000", + "status": "PENDING_NEW", + "timeInForce": "GTC", + "type": "LIMIT_MAKER", + "side": "SELL", + "workingTime": -1, + "selfTradePreventionMode": "NONE" + } + ] + }, + "rateLimits": [ + { + "rateLimitType": "ORDERS", + "interval": "MINUTE", + "intervalNum": 1, + "limit": 10000000, + "count": 18 + }, + { + "rateLimitType": "REQUEST_WEIGHT", + "interval": "MINUTE", + "intervalNum": 1, + "limit": 1000, + "count": 65 + } + ] + } + """ + + parameters = { + "symbol": symbol, + "workingType": workingType, + "workingSide": workingSide, + "workingPrice": workingPrice, + "pendingSide": pendingSide, + "pendingQuantity": pendingQuantity, + "pendingAboveType": pendingAboveType, **kwargs, } payload = { "id": parameters.pop("id", get_uuid()), - "method": "orderList.place", + "method": "orderList.place.otoco", "params": websocket_api_signature(self.api_key, self.api_secret, parameters), } self.send(payload) diff --git a/docs/source/binance.spot.auto_invest.rst b/docs/source/binance.spot.auto_invest.rst new file mode 100644 index 00000000..0fc612e6 --- /dev/null +++ b/docs/source/binance.spot.auto_invest.rst @@ -0,0 +1,62 @@ +Auto Invest Endpoints +====================== + +Get target asset list (USER_DATA) +--------------------------------- +.. autofunction:: binance.spot.Spot.get_target_asset_list + +Get target asset ROI data (USER_DATA) +------------------------------------- +.. autofunction:: binance.spot.Spot.get_target_asset_roi_data + +Query all source asset and target asset (USER_DATA) +--------------------------------------------------- +.. autofunction:: binance.spot.Spot.query_all_source_asset_and_target_asset + +Query source asset list (USER_DATA) +----------------------------------- +.. autofunction:: binance.spot.Spot.query_source_asset_list + +Change Plan Status (TRADE) +-------------------------- +.. autofunction:: binance.spot.Spot.change_plan_status + +Get list of plans (USER_DATA) +------------------------------ +.. autofunction:: binance.spot.Spot.get_list_of_plans + +Query holding details of the plan (USER_DATA) +--------------------------------------------- +.. autofunction:: binance.spot.Spot.query_holding_details_of_the_plan + +Query subscription transaction history (USER_DATA) +-------------------------------------------------- +.. autofunction:: binance.spot.Spot.query_subscription_transaction_history + +Query Index Details (USER_DATA) +------------------------------- +.. autofunction:: binance.spot.Spot.query_index_details + +Query Index Linked Plan Position Details (USER_DATA) +---------------------------------------------------- +.. autofunction:: binance.spot.Spot.query_index_linked_plan_position_details + +One Time Transaction (TRADE) +---------------------------- +.. autofunction:: binance.spot.Spot.one_time_transaction + +Query One-Time Transaction Status (USER_DATA) +--------------------------------------------- +.. autofunction:: binance.spot.Spot.query_one_time_transaction_status + +Index Linked Plan Redemption (TRADE) +------------------------------------ +.. autofunction:: binance.spot.Spot.index_linked_plan_redemption + +Index Linked Plan Redemption (USER_DATA) +---------------------------------------- +.. autofunction:: binance.spot.Spot.get_index_linked_plan_redemption_history + +Index Linked Plan Rebalance Details (USER_DATA) +----------------------------------------------- +.. autofunction:: binance.spot.Spot.index_linked_plan_rebalance_details \ No newline at end of file diff --git a/docs/source/binance.spot.convert.rst b/docs/source/binance.spot.convert.rst index 31941a9c..180b1b95 100644 --- a/docs/source/binance.spot.convert.rst +++ b/docs/source/binance.spot.convert.rst @@ -1,7 +1,6 @@ Convert Endpoints ================= - List All Convert Pairs ---------------------- .. autofunction:: binance.spot.Spot.list_all_convert_pairs @@ -18,10 +17,22 @@ Accept Quote (TRADE) -------------------- .. autofunction:: binance.spot.Spot.accept_quote -Order status (USER_DATA) +Order Status (USER_DATA) ------------------------ .. autofunction:: binance.spot.Spot.order_status +Place limit order (USER_DATA) +----------------------------- +.. autofunction:: binance.spot.Spot.place_limit_order + +Cancel limit order (USER_DATA) +------------------------------ +.. autofunction:: binance.spot.Spot.cancel_limit_order + +Query limit open orders (USER_DATA) +----------------------------------- +.. autofunction:: binance.spot.Spot.query_limit_open_order + Get Convert Trade History (USER_DATA) ------------------------------------- .. autofunction:: binance.spot.Spot.get_convert_trade_history diff --git a/docs/source/binance.spot.margin.rst b/docs/source/binance.spot.margin.rst index 1914e6b0..9f9f9326 100644 --- a/docs/source/binance.spot.margin.rst +++ b/docs/source/binance.spot.margin.rst @@ -144,3 +144,35 @@ Query Current Margin Order Count Usage (TRADE) Get Summary of Margin account (USER_DATA) ----------------------------------------- .. autofunction:: binance.spot.Spot.summary_of_margin_account + +Cross margin collateral ratio (MARKET_DATA) +-------------------------------------------- +.. autofunction:: binance.spot.Spot.cross_margin_collateral_ratio + +Get Small Liability Exchange Coin List (USER_DATA) +-------------------------------------------------- +.. autofunction:: binance.spot.Spot.get_small_liability_exchange_coin_list + +Get Small Liability Exchange History (USER_DATA) +------------------------------------------------ +.. autofunction:: binance.spot.Spot.get_small_liability_exchange_history + +Get a future hourly interest rate (USER_DATA) +--------------------------------------------- +.. autofunction:: binance.spot.Spot.get_a_future_hourly_interest_rate + +Adjust cross margin max leverage (USER_DATA) +-------------------------------------------- +.. autofunction:: binance.spot.Spot.adjust_cross_margin_max_leverage + +Query Margin Available Inventory (USER_DATA) +--------------------------------------------- +.. autofunction:: binance.spot.Spot.margin_available_inventory + +Margin manual liquidation (MARGIN) +---------------------------------- +.. autofunction:: binance.spot.Spot.margin_manual_liquidation + +Query Liability Coin Leverage Bracket in Cross Margin Pro Mode(MARKET_DATA) +--------------------------------------------------------------------------- +.. autofunction:: binance.spot.Spot.liability_coin_leverage_bracket diff --git a/docs/source/binance.spot.rst b/docs/source/binance.spot.rst index 8974e223..6b79b666 100644 --- a/docs/source/binance.spot.rst +++ b/docs/source/binance.spot.rst @@ -4,6 +4,7 @@ Spot APIs .. toctree:: :maxdepth: 2 + binance.spot.auto_invest binance.spot.blvt binance.spot.c2c binance.spot.convert diff --git a/docs/source/binance.spot.sub_account.rst b/docs/source/binance.spot.sub_account.rst index 7d2ee0a9..5b72b4da 100644 --- a/docs/source/binance.spot.sub_account.rst +++ b/docs/source/binance.spot.sub_account.rst @@ -1,16 +1,16 @@ Sub Account Endpoints ===================== -Create a Virtual Sub-account(For Master Account) ------------------------------------------------- +Create a Virtual Sub-account (For Master Account) +------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_create -Query Sub-account List(For Master Account) ------------------------------------------- +Query Sub-account List (For Master Account) +------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_list -Query Sub-account Assets(For Master Account) --------------------------------------------- +Query Sub-account Assets (For Master Account) +--------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_assets Get Sub-account Deposit Address (For Master Account) @@ -41,19 +41,19 @@ Enable Futures for Sub-account (For Master Account) --------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_enable_futures -Futures Transfer for Sub-account(For Master Account) +Futures Transfer for Sub-account (For Master Account) ------------------------------------------------------ .. autofunction:: binance.spot.Spot.sub_account_futures_transfer -Margin Transfer for Sub-account(For Master Account) +Margin Transfer for Sub-account (For Master Account) ---------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_margin_transfer -Transfer to Sub-account of Same Master(For Sub-account) +Transfer to Sub-account of Same Master (For Sub-account) --------------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_transfer_to_sub -Transfer to Master(For Sub-account) +Transfer to Master (For Sub-account) ------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_transfer_to_master @@ -61,12 +61,12 @@ Sub-account Transfer History (For Sub-account) ---------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_transfer_sub_account_history -Query Sub-account Futures Asset Transfer History(For Master Account) --------------------------------------------------------------------- +Query Sub-account Futures Asset Transfer History (For Master Account) +--------------------------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_futures_asset_transfer_history -Query Sub-account Futures Asset Transfer History(For Master Account) --------------------------------------------------------------------- +Query Sub-account Futures Asset Transfer History (For Master Account) +--------------------------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_futures_asset_transfer Query Sub-account Spot Assets Summary (For Master Account) @@ -97,8 +97,8 @@ Query Sub-account Spot Asset Transfer History (SAPI For Master Account) ----------------------------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_spot_transfer_history -Enable Leverage Token for Sub-account(For Master Account) ---------------------------------------------------------- +Enable Leverage Token for Sub-account (For Master Account) +---------------------------------------------------------- .. autofunction:: binance.spot.Spot.sub_account_enable_leverage_token Deposit assets into the managed sub-account (For Investor Master Account) diff --git a/docs/source/binance.spot.wallet.rst b/docs/source/binance.spot.wallet.rst index f4053a5c..8115b82e 100644 --- a/docs/source/binance.spot.wallet.rst +++ b/docs/source/binance.spot.wallet.rst @@ -25,7 +25,7 @@ Withdraw (USER_DATA) -------------------- .. autofunction:: binance.spot.Spot.withdraw -Deposit History(supporting network) (USER_DATA) +Deposit History (supporting network) (USER_DATA) ------------------------------------------------- .. autofunction:: binance.spot.Spot.deposit_history @@ -116,3 +116,7 @@ One click arrival deposit apply (USER_DATA) Query User Wallet Balance (USER_DATA) ------------------------------------- .. autofunction:: binance.spot.Spot.balance + +Get symbols delist schedule for spot (MARKET_DATA) +-------------------------------------------------- +.. autofunction:: binance.spot.Spot.delist_schedule_symbols diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index fd123514..5a4e1fe9 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -175,7 +175,7 @@ WebSocket from binance.websocket.spot.websocket_api import SpotWebsocketAPIClient - ws_client = SpotWebsocketAPIClient(stream_url='wss://testnet.binance.vision') + ws_client = SpotWebsocketAPIClient(stream_url='wss://ws-api.testnet.binance.vision/ws-api/v3') Errors ------ diff --git a/examples/spot/convert/place_limit_order.py b/examples/spot/convert/place_limit_order.py index 85465340..788d1ae8 100644 --- a/examples/spot/convert/place_limit_order.py +++ b/examples/spot/convert/place_limit_order.py @@ -17,7 +17,6 @@ try: response = client.place_limit_order( baseAsset="BNB", - quoteAsset="USDT", limitPrice=0.0001, side="BUY", expiredType="1_D", diff --git a/examples/spot/trade/new_oco_order.py b/examples/spot/trade/new_oco_order.py index 76bb3f82..4709b2dc 100644 --- a/examples/spot/trade/new_oco_order.py +++ b/examples/spot/trade/new_oco_order.py @@ -11,13 +11,13 @@ api_key, api_secret = get_api_key() params = { - "symbol": "BTCUSDT", + "symbol": "BNBUSDT", "side": "SELL", "quantity": 0.002, - "price": 9500, - "stopPrice": 7500, - "stopLimitPrice": 7000, - "stopLimitTimeInForce": "GTC", + "aboveType": "LIMIT_MAKER", + "belowType": "LIMIT_MAKER", + "abovePrice": 510, + "belowPrice": 500, } client = Client(api_key, api_secret, base_url="https://testnet.binance.vision") diff --git a/examples/spot/trade/new_oto_order.py b/examples/spot/trade/new_oto_order.py new file mode 100644 index 00000000..10ac8f1e --- /dev/null +++ b/examples/spot/trade/new_oto_order.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import logging +from binance.spot import Spot as Client +from binance.lib.utils import config_logging +from binance.error import ClientError +from examples.utils.prepare_env import get_api_key + +config_logging(logging, logging.DEBUG) + +api_key, api_secret = get_api_key() + +params = { + "symbol": "BNBUSDT", + "workingType": "LIMIT", + "workingSide": "BUY", + "workingPrice": 400, + "workingQuantity": 1, + "pendingType": "LIMIT", + "pendingSide": "BUY", + "pendingQuantity": 1, + "workingTimeInForce": "GTC", + "pendingPrice": 400, + "pendingTimeInForce": "GTC", +} + +client = Client(api_key, api_secret, base_url="https://testnet.binance.vision") + +try: + response = client.new_oto_order(**params) + logging.info(response) +except ClientError as error: + logging.error( + "Found error. status: {}, error code: {}, error message: {}".format( + error.status_code, error.error_code, error.error_message + ) + ) diff --git a/examples/spot/trade/new_otoco_order.py b/examples/spot/trade/new_otoco_order.py new file mode 100644 index 00000000..b6574083 --- /dev/null +++ b/examples/spot/trade/new_otoco_order.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import logging +from binance.spot import Spot as Client +from binance.lib.utils import config_logging +from binance.error import ClientError +from examples.utils.prepare_env import get_api_key + +config_logging(logging, logging.DEBUG) + +api_key, api_secret = get_api_key() + +params = { + "symbol": "BNBUSDT", + "workingType": "LIMIT", + "workingSide": "BUY", + "workingPrice": 400, + "workingQuantity": 1, + "pendingSide": "BUY", + "pendingQuantity": 1, + "pendingAboveType": "LIMIT_MAKER", + "workingTimeInForce": "GTC", + "pendingPrice": 400, + "pendingTimeInForce": "GTC", +} + +client = Client(api_key, api_secret, base_url="https://testnet.binance.vision") + +try: + response = client.new_otoco_order(**params) + logging.info(response) +except ClientError as error: + logging.error( + "Found error. status: {}, error code: {}, error message: {}".format( + error.status_code, error.error_code, error.error_message + ) + ) diff --git a/examples/websocket/spot/websocket_api/account/account.py b/examples/websocket/spot/websocket_api/account/account.py index 1ef55dc2..71c7a82d 100644 --- a/examples/websocket/spot/websocket_api/account/account.py +++ b/examples/websocket/spot/websocket_api/account/account.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/account/my_trades.py b/examples/websocket/spot/websocket_api/account/my_trades.py index 98443c4b..1b2358e2 100644 --- a/examples/websocket/spot/websocket_api/account/my_trades.py +++ b/examples/websocket/spot/websocket_api/account/my_trades.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/account/oco_history.py b/examples/websocket/spot/websocket_api/account/oco_history.py index 1cc591da..456de434 100644 --- a/examples/websocket/spot/websocket_api/account/oco_history.py +++ b/examples/websocket/spot/websocket_api/account/oco_history.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/account/order_history.py b/examples/websocket/spot/websocket_api/account/order_history.py index e8a247c5..b812e6bf 100644 --- a/examples/websocket/spot/websocket_api/account/order_history.py +++ b/examples/websocket/spot/websocket_api/account/order_history.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/account/order_rate_limit.py b/examples/websocket/spot/websocket_api/account/order_rate_limit.py index 15ab1631..486f8d80 100644 --- a/examples/websocket/spot/websocket_api/account/order_rate_limit.py +++ b/examples/websocket/spot/websocket_api/account/order_rate_limit.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/account/prevented_matches.py b/examples/websocket/spot/websocket_api/account/prevented_matches.py index 82df3b4c..146f6dc4 100644 --- a/examples/websocket/spot/websocket_api/account/prevented_matches.py +++ b/examples/websocket/spot/websocket_api/account/prevented_matches.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/app_demo.py b/examples/websocket/spot/websocket_api/app_demo.py index 2e856ee1..60bd9fb6 100644 --- a/examples/websocket/spot/websocket_api/app_demo.py +++ b/examples/websocket/spot/websocket_api/app_demo.py @@ -37,7 +37,7 @@ def websocket_stream_message_handler(_, message): # make a connection to the websocket api ws_api_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=websocket_api_message_handler, @@ -46,7 +46,7 @@ def websocket_stream_message_handler(_, message): # make a connection to the websocket stream ws_stream_client = SpotWebsocketStreamClient( - stream_url="wss://testnet.binance.vision", + stream_url="wss://stream.testnet.binance.vision", on_message=websocket_stream_message_handler, ) diff --git a/examples/websocket/spot/websocket_api/trade/cancel_oco_order.py b/examples/websocket/spot/websocket_api/trade/cancel_oco_order.py index e171a824..a5a84f65 100644 --- a/examples/websocket/spot/websocket_api/trade/cancel_oco_order.py +++ b/examples/websocket/spot/websocket_api/trade/cancel_oco_order.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/cancel_open_orders.py b/examples/websocket/spot/websocket_api/trade/cancel_open_orders.py index 5d9c8290..4336820e 100644 --- a/examples/websocket/spot/websocket_api/trade/cancel_open_orders.py +++ b/examples/websocket/spot/websocket_api/trade/cancel_open_orders.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/cancel_order.py b/examples/websocket/spot/websocket_api/trade/cancel_order.py index 16402e85..cf830434 100644 --- a/examples/websocket/spot/websocket_api/trade/cancel_order.py +++ b/examples/websocket/spot/websocket_api/trade/cancel_order.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/cancel_replace_order.py b/examples/websocket/spot/websocket_api/trade/cancel_replace_order.py index d171357e..d84b4100 100644 --- a/examples/websocket/spot/websocket_api/trade/cancel_replace_order.py +++ b/examples/websocket/spot/websocket_api/trade/cancel_replace_order.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/get_oco_order.py b/examples/websocket/spot/websocket_api/trade/get_oco_order.py index 63e6e5ee..1dc15523 100644 --- a/examples/websocket/spot/websocket_api/trade/get_oco_order.py +++ b/examples/websocket/spot/websocket_api/trade/get_oco_order.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/get_open_oco_orders.py b/examples/websocket/spot/websocket_api/trade/get_open_oco_orders.py index a6bf2070..f58148e9 100644 --- a/examples/websocket/spot/websocket_api/trade/get_open_oco_orders.py +++ b/examples/websocket/spot/websocket_api/trade/get_open_oco_orders.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/get_open_orders.py b/examples/websocket/spot/websocket_api/trade/get_open_orders.py index b0f62ab5..4b763036 100644 --- a/examples/websocket/spot/websocket_api/trade/get_open_orders.py +++ b/examples/websocket/spot/websocket_api/trade/get_open_orders.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/get_order.py b/examples/websocket/spot/websocket_api/trade/get_order.py index 3ea43f6b..04f0b372 100644 --- a/examples/websocket/spot/websocket_api/trade/get_order.py +++ b/examples/websocket/spot/websocket_api/trade/get_order.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/new_oco_order.py b/examples/websocket/spot/websocket_api/trade/new_oco_order.py index 27d39d34..75e15283 100644 --- a/examples/websocket/spot/websocket_api/trade/new_oco_order.py +++ b/examples/websocket/spot/websocket_api/trade/new_oco_order.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, @@ -31,14 +31,12 @@ def message_handler(_, message): my_client.new_oco_order( symbol="BNBUSDT", side="BUY", - price=200, quantity=1, + aboveType="LIMIT_MAKER", + belowType="LIMIT_MAKER", + abovePrice=400, + belowPrice=395, listClientOrderId="123", - limitClientOrderId="456", - stopPrice=350, - stopLimitPrice=400, - stopLimitTimeInForce="GTC", - newOrderRespType="RESULT", ) time.sleep(2) diff --git a/examples/websocket/spot/websocket_api/trade/new_order.py b/examples/websocket/spot/websocket_api/trade/new_order.py index 79f96998..4d7d55c3 100644 --- a/examples/websocket/spot/websocket_api/trade/new_order.py +++ b/examples/websocket/spot/websocket_api/trade/new_order.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/new_order_test.py b/examples/websocket/spot/websocket_api/trade/new_order_test.py index d390e130..37c56d4a 100644 --- a/examples/websocket/spot/websocket_api/trade/new_order_test.py +++ b/examples/websocket/spot/websocket_api/trade/new_order_test.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/trade/new_oto_order.py b/examples/websocket/spot/websocket_api/trade/new_oto_order.py new file mode 100644 index 00000000..910a9ab2 --- /dev/null +++ b/examples/websocket/spot/websocket_api/trade/new_oto_order.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +import logging +import time +from binance.lib.utils import config_logging +from binance.websocket.spot.websocket_api import SpotWebsocketAPIClient +from examples.utils.prepare_env import get_api_key + +api_key, api_secret = get_api_key() + +config_logging(logging, logging.DEBUG) + + +def on_close(_): + logging.info("Do custom stuff when connection is closed") + + +def message_handler(_, message): + logging.info(message) + + +my_client = SpotWebsocketAPIClient( + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", + api_key=api_key, + api_secret=api_secret, + on_message=message_handler, + on_close=on_close, +) + + +my_client.new_oto_order( + symbol="BNBUSDT", + workingType="LIMIT", + workingSide="BUY", + workingPrice=400, + workingQuantity=1, + pendingType="LIMIT", + pendingSide="BUY", + pendingQuantity=1, + workingTimeInForce="GTC", + pendingPrice=400, + pendingTimeInForce="GTC", + listClientOrderId="123", +) + +time.sleep(2) + +logging.info("closing ws connection") +my_client.stop() diff --git a/examples/websocket/spot/websocket_api/trade/new_otoco_order.py b/examples/websocket/spot/websocket_api/trade/new_otoco_order.py new file mode 100644 index 00000000..a57294be --- /dev/null +++ b/examples/websocket/spot/websocket_api/trade/new_otoco_order.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +import logging +import time +from binance.lib.utils import config_logging +from binance.websocket.spot.websocket_api import SpotWebsocketAPIClient +from examples.utils.prepare_env import get_api_key + +api_key, api_secret = get_api_key() + +config_logging(logging, logging.DEBUG) + + +def on_close(_): + logging.info("Do custom stuff when connection is closed") + + +def message_handler(_, message): + logging.info(message) + + +my_client = SpotWebsocketAPIClient( + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", + api_key=api_key, + api_secret=api_secret, + on_message=message_handler, + on_close=on_close, +) + + +my_client.new_otoco_order( + symbol="BNBUSDT", + workingType="LIMIT", + workingSide="BUY", + workingPrice=400, + workingQuantity=1, + pendingSide="BUY", + pendingQuantity=1, + pendingAboveType="LIMIT_MAKER", + workingTimeInForce="GTC", + pendingPrice=400, + pendingTimeInForce="GTC", +) + +time.sleep(2) + +logging.info("closing ws connection") +my_client.stop() diff --git a/examples/websocket/spot/websocket_api/user_data/user_data_ping.py b/examples/websocket/spot/websocket_api/user_data/user_data_ping.py index 08ea1fec..6765a0c4 100644 --- a/examples/websocket/spot/websocket_api/user_data/user_data_ping.py +++ b/examples/websocket/spot/websocket_api/user_data/user_data_ping.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/user_data/user_data_start.py b/examples/websocket/spot/websocket_api/user_data/user_data_start.py index b8f7f65d..6ebcf7ae 100644 --- a/examples/websocket/spot/websocket_api/user_data/user_data_start.py +++ b/examples/websocket/spot/websocket_api/user_data/user_data_start.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_api/user_data/user_data_stop.py b/examples/websocket/spot/websocket_api/user_data/user_data_stop.py index c3c5248a..4ab3b389 100644 --- a/examples/websocket/spot/websocket_api/user_data/user_data_stop.py +++ b/examples/websocket/spot/websocket_api/user_data/user_data_stop.py @@ -20,7 +20,7 @@ def message_handler(_, message): my_client = SpotWebsocketAPIClient( - stream_url="wss://testnet.binance.vision/ws-api/v3", + stream_url="wss://ws-api.testnet.binance.vision/ws-api/v3", api_key=api_key, api_secret=api_secret, on_message=message_handler, diff --git a/examples/websocket/spot/websocket_stream/user_data.py b/examples/websocket/spot/websocket_stream/user_data.py index 765d82eb..b712c014 100644 --- a/examples/websocket/spot/websocket_stream/user_data.py +++ b/examples/websocket/spot/websocket_stream/user_data.py @@ -24,7 +24,7 @@ def message_handler(_, message): # create the websocket connection to testnet as well ws_client = SpotWebsocketStreamClient( - stream_url="wss://testnet.binance.vision", on_message=message_handler + stream_url="wss://stream.testnet.binance.vision", on_message=message_handler ) ws_client.user_data(listen_key=response["listenKey"]) diff --git a/tests/spot/trade/test_new_oco_order.py b/tests/spot/trade/test_new_oco_order.py index 4dde6e70..bb68c61e 100644 --- a/tests/spot/trade/test_new_oco_order.py +++ b/tests/spot/trade/test_new_oco_order.py @@ -13,18 +13,18 @@ secret = random_str() params = { - "symbol": "BTCUSDT", + "symbol": "BNBUSDT", "side": "SELL", "quantity": 0.002, - "price": 9500, - "stopPrice": 7500, - "stopLimitPrice": 7000, - "stopLimitTimeInForce": "GTC", + "aboveType": "LIMIT_MAKER", + "belowType": "LIMIT_MAKER", + "abovePrice": 510, + "belowPrice": 500, "recvWindow": 1000, } -@mock_http_response(responses.POST, "/api/v3/order/oco", mock_exception, 400) +@mock_http_response(responses.POST, "/api/v3/orderList/oco", mock_exception, 400) def test_post_an_oco_order_without_param(): """Tests the API endpoint to post a new oco order without parameters""" @@ -35,7 +35,7 @@ def test_post_an_oco_order_without_param(): @mock_http_response( - responses.POST, "/api/v3/order/oco\\?" + urlencode(params), mock_item, 200 + responses.POST, "/api/v3/orderList/oco\\?" + urlencode(params), mock_item, 200 ) def test_post_an_oco_order(): """Tests the API endpoint to post a new oco order""" diff --git a/tests/spot/trade/test_new_oto_order.py b/tests/spot/trade/test_new_oto_order.py new file mode 100644 index 00000000..9be4f79c --- /dev/null +++ b/tests/spot/trade/test_new_oto_order.py @@ -0,0 +1,48 @@ +import responses + +from tests.util import random_str +from urllib.parse import urlencode +from tests.util import mock_http_response +from binance.spot import Spot as Client +from binance.error import ParameterRequiredError + +mock_item = {"key_1": "value_1", "key_2": "value_2"} +mock_exception = {"code": -1, "msg": "error message"} + +key = random_str() +secret = random_str() + +params = { + "symbol": "BNBUSDT", + "workingType": "LIMIT", + "workingSide": "BUY", + "workingPrice": 400, + "workingQuantity": 1, + "pendingType": "LIMIT", + "pendingSide": "BUY", + "pendingQuantity": 1, + "workingTimeInForce": "GTC", + "pendingPrice": 400, + "pendingTimeInForce": "GTC", +} + + +@mock_http_response(responses.POST, "/api/v3/orderList/oto", mock_exception, 400) +def test_post_an_oto_order_without_param(): + """Tests the API endpoint to post a new oto order without parameters""" + + client = Client(key, secret) + client.new_oto_order.when.called_with("", "", "", "", "", "", "", "").should.throw( + ParameterRequiredError + ) + + +@mock_http_response( + responses.POST, "/api/v3/orderList/oto\\?" + urlencode(params), mock_item, 200 +) +def test_post_an_oto_order(): + """Tests the API endpoint to post a new oto order""" + + client = Client(key, secret) + response = client.new_oto_order(**params) + response.should.equal(mock_item) diff --git a/tests/spot/trade/test_new_otoco_order.py b/tests/spot/trade/test_new_otoco_order.py new file mode 100644 index 00000000..43e1efb0 --- /dev/null +++ b/tests/spot/trade/test_new_otoco_order.py @@ -0,0 +1,48 @@ +import responses + +from tests.util import random_str +from urllib.parse import urlencode +from tests.util import mock_http_response +from binance.spot import Spot as Client +from binance.error import ParameterRequiredError + +mock_item = {"key_1": "value_1", "key_2": "value_2"} +mock_exception = {"code": -1, "msg": "error message"} + +key = random_str() +secret = random_str() + +params = { + "symbol": "BNBUSDT", + "workingType": "LIMIT", + "workingSide": "BUY", + "workingPrice": 400, + "workingQuantity": 1, + "pendingSide": "BUY", + "pendingQuantity": 1, + "pendingAboveType": "LIMIT_MAKER", + "workingTimeInForce": "GTC", + "pendingPrice": 400, + "pendingTimeInForce": "GTC", +} + + +@mock_http_response(responses.POST, "/api/v3/order/otoco", mock_exception, 400) +def test_post_an_otoco_order_without_param(): + """Tests the API endpoint to post a new otoco order without parameters""" + + client = Client(key, secret) + client.new_otoco_order.when.called_with( + "", "", "", "", "", "", "", "" + ).should.throw(ParameterRequiredError) + + +@mock_http_response( + responses.POST, "/api/v3/orderList/otoco\\?" + urlencode(params), mock_item, 200 +) +def test_post_an_otoco_order(): + """Tests the API endpoint to post a new otoco order""" + + client = Client(key, secret) + response = client.new_otoco_order(**params) + response.should.equal(mock_item)