From 6f0f6a44e6a4d1576e3743532b82c9a81fa2026e Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 24 Oct 2023 01:14:59 +0000 Subject: [PATCH] dev: add experimental websocket update for balance and position for binance-usds-futures --- include/ccapi_cpp/ccapi_macro.h | 10 ++ include/ccapi_cpp/ccapi_message.h | 8 + include/ccapi_cpp/ccapi_subscription.h | 3 +- ...xecution_management_service_binance_base.h | 38 +++++ .../binance_usds_futures/test.cpp | 144 +++++++++++++++--- 5 files changed, 179 insertions(+), 24 deletions(-) diff --git a/include/ccapi_cpp/ccapi_macro.h b/include/ccapi_cpp/ccapi_macro.h index bdec712d..d385220f 100644 --- a/include/ccapi_cpp/ccapi_macro.h +++ b/include/ccapi_cpp/ccapi_macro.h @@ -413,8 +413,18 @@ #ifndef CCAPI_UNKNOWN #define CCAPI_UNKNOWN "unknown" #endif +#ifndef CCAPI_EM_ORDER_UPDATE #define CCAPI_EM_ORDER_UPDATE "ORDER_UPDATE" +#endif +#ifndef CCAPI_EM_PRIVATE_TRADE #define CCAPI_EM_PRIVATE_TRADE "PRIVATE_TRADE" +#endif +#ifndef CCAPI_EM_BALANCE_UPDATE +#define CCAPI_EM_BALANCE_UPDATE "BALANCE_UPDATE" +#endif +#ifndef CCAPI_EM_POSITION_UPDATE +#define CCAPI_EM_POSITION_UPDATE "POSITION_UPDATE" +#endif #ifndef CCAPI_EM_ORDER_SIDE #define CCAPI_EM_ORDER_SIDE "SIDE" #endif diff --git a/include/ccapi_cpp/ccapi_message.h b/include/ccapi_cpp/ccapi_message.h index eb737a80..849ccd7f 100644 --- a/include/ccapi_cpp/ccapi_message.h +++ b/include/ccapi_cpp/ccapi_message.h @@ -48,6 +48,8 @@ class Message CCAPI_FINAL { MARKET_DATA_EVENTS_CANDLESTICK, EXECUTION_MANAGEMENT_EVENTS_ORDER_UPDATE, EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE, + EXECUTION_MANAGEMENT_EVENTS_BALANCE_UPDATE, + EXECUTION_MANAGEMENT_EVENTS_POSITION_UPDATE, SUBSCRIPTION_STARTED, SUBSCRIPTION_FAILURE, SESSION_CONNECTION_UP, @@ -110,6 +112,12 @@ class Message CCAPI_FINAL { case Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE: output = "EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE"; break; + case Type::EXECUTION_MANAGEMENT_EVENTS_BALANCE_UPDATE: + output = "EXECUTION_MANAGEMENT_EVENTS_BALANCE_UPDATE"; + break; + case Type::EXECUTION_MANAGEMENT_EVENTS_POSITION_UPDATE: + output = "EXECUTION_MANAGEMENT_EVENTS_POSITION_UPDATE"; + break; case Type::SUBSCRIPTION_STARTED: output = "SUBSCRIPTION_STARTED"; break; diff --git a/include/ccapi_cpp/ccapi_subscription.h b/include/ccapi_cpp/ccapi_subscription.h index 16aaa8b8..fcf5fa47 100644 --- a/include/ccapi_cpp/ccapi_subscription.h +++ b/include/ccapi_cpp/ccapi_subscription.h @@ -41,7 +41,8 @@ class Subscription CCAPI_FINAL { this->optionMap[optionKeyValue.at(0)] = optionKeyValue.at(1); } } - std::set executionManagementSubscriptionFieldSet = {std::string(CCAPI_EM_ORDER_UPDATE), std::string(CCAPI_EM_PRIVATE_TRADE)}; + std::set executionManagementSubscriptionFieldSet = {std::string(CCAPI_EM_ORDER_UPDATE), std::string(CCAPI_EM_PRIVATE_TRADE), + std::string(CCAPI_EM_BALANCE_UPDATE), std::string(CCAPI_EM_POSITION_UPDATE)}; if (field == CCAPI_GENERIC_PUBLIC_SUBSCRIPTION) { this->serviceName = CCAPI_MARKET_DATA; } else if (field == CCAPI_FIX || field == CCAPI_FIX_MARKET_DATA || field == CCAPI_FIX_EXECUTION_MANAGEMENT) { diff --git a/include/ccapi_cpp/service/ccapi_execution_management_service_binance_base.h b/include/ccapi_cpp/service/ccapi_execution_management_service_binance_base.h index bcc8bc82..3e869304 100644 --- a/include/ccapi_cpp/service/ccapi_execution_management_service_binance_base.h +++ b/include/ccapi_cpp/service/ccapi_execution_management_service_binance_base.h @@ -651,6 +651,44 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService messageList.emplace_back(std::move(message)); } } + } else if (this->isDerivatives && type == "ACCOUNT_UPDATE") { + event.setType(Event::Type::SUBSCRIPTION_DATA); + const rj::Value& data = document["a"]; + if (fieldSet.find(CCAPI_EM_BALANCE_UPDATE) != fieldSet.end() && !data["B"].Empty()) { + Message message; + message.setTimeReceived(timeReceived); + message.setCorrelationIdList({subscription.getCorrelationId()}); + message.setTime(TimePoint(std::chrono::milliseconds(std::stoll(document["E"].GetString())))); + message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_BALANCE_UPDATE); + std::vector elementList; + for (const auto& x : data["B"].GetArray()) { + Element element; + element.insert(CCAPI_EM_ASSET, x["a"].GetString()); + element.insert(CCAPI_EM_QUANTITY_TOTAL, x["wb"].GetString()); + elementList.emplace_back(std::move(element)); + } + message.setElementList(elementList); + messageList.emplace_back(std::move(message)); + } + if (fieldSet.find(CCAPI_EM_POSITION_UPDATE) != fieldSet.end() && !data["P"].Empty()) { + Message message; + message.setTimeReceived(timeReceived); + message.setCorrelationIdList({subscription.getCorrelationId()}); + message.setTime(TimePoint(std::chrono::milliseconds(std::stoll((this->isDerivatives ? document : data)["E"].GetString())))); + message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_POSITION_UPDATE); + std::vector elementList; + for (const auto& x : data["P"].GetArray()) { + Element element; + element.insert(CCAPI_INSTRUMENT, x["s"].GetString()); + element.insert(CCAPI_EM_POSITION_SIDE, x["ps"].GetString()); + element.insert(CCAPI_EM_POSITION_QUANTITY, x["pa"].GetString()); + element.insert(CCAPI_EM_POSITION_ENTRY_PRICE, x["ep"].GetString()); + element.insert(CCAPI_EM_UNREALIZED_PNL, x["up"].GetString()); + elementList.emplace_back(std::move(element)); + } + message.setElementList(elementList); + messageList.emplace_back(std::move(message)); + } } event.setMessageList(messageList); return event; diff --git a/test/test_unit/src/execution_management/binance_usds_futures/test.cpp b/test/test_unit/src/execution_management/binance_usds_futures/test.cpp index 35825a55..8e8337e4 100644 --- a/test/test_unit/src/execution_management/binance_usds_futures/test.cpp +++ b/test/test_unit/src/execution_management/binance_usds_futures/test.cpp @@ -71,7 +71,6 @@ TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, convertTextMessageToMes EXPECT_EQ(elementList.size(), 1); Element element = elementList.at(0); EXPECT_EQ(element.getValue(CCAPI_EM_ORDER_CUMULATIVE_FILLED_PRICE_TIMES_QUANTITY), "0.01"); - EXPECT_EQ(element.getValue(CCAPI_LAST_UPDATED_TIME_SECONDS), "1579276756.075"); } TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, createEventExecutionTypeTrade) { @@ -141,6 +140,110 @@ TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, createEventExecutionTyp EXPECT_EQ(element.getValue(CCAPI_EM_ORDER_FEE_ASSET), "USDT"); } +TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, createEventBalanceUpdate) { + Subscription subscription(CCAPI_EXCHANGE_NAME_BINANCE_USDS_FUTURES, "BTCUSDT", CCAPI_EM_BALANCE_UPDATE); + std::string textMessage = R"( + { + "e": "ACCOUNT_UPDATE", + "E": 1564745798939, + "T": 1564745798938, + "a": { + "m": "ORDER", + "B": [ + { + "a": "USDT", + "wb": "122624.12345678", + "cw": "100.12345678", + "bc": "50.12345678" + }, + { + "a": "BUSD", + "wb": "1.00000000", + "cw": "0.00000000", + "bc": "-49.12345678" + } + ] + } +} +)"; + rj::Document document; + document.Parse(textMessage.c_str()); + auto messageList = this->service->createEvent(std::shared_ptr(), subscription, textMessage, document, this->now).getMessageList(); + EXPECT_EQ(messageList.size(), 1); + verifyCorrelationId(messageList, subscription.getCorrelationId()); + auto message = messageList.at(0); + EXPECT_EQ(message.getType(), Message::Type::EXECUTION_MANAGEMENT_EVENTS_BALANCE_UPDATE); + auto elementList = message.getElementList(); + EXPECT_EQ(elementList.size(), 2); + Element element = elementList.at(0); + EXPECT_EQ(element.getValue(CCAPI_EM_ASSET), "USDT"); + EXPECT_EQ(element.getValue(CCAPI_EM_QUANTITY_TOTAL), "122624.12345678"); +} + +TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, createEventPositionUpdate) { + Subscription subscription(CCAPI_EXCHANGE_NAME_BINANCE_USDS_FUTURES, "BTCUSDT", CCAPI_EM_POSITION_UPDATE); + std::string textMessage = R"( + { + "e": "ACCOUNT_UPDATE", + "E": 1564745798939, + "T": 1564745798938, + "a": { + "m": "ORDER", + "P": [ + { + "s": "BTCUSDT", + "pa": "0", + "ep": "0.00000", + "bep": "0", + "cr": "200", + "up": "0", + "mt": "isolated", + "iw": "0.00000000", + "ps": "BOTH" + }, + { + "s": "BTCUSDT", + "pa": "20", + "ep": "6563.66500", + "bep": "6563.6", + "cr": "0", + "up": "2850.21200", + "mt": "isolated", + "iw": "13200.70726908", + "ps": "LONG" + }, + { + "s": "BTCUSDT", + "pa": "-10", + "ep": "6563.86000", + "bep": "6563.6", + "cr": "-45.04000000", + "up": "-1423.15600", + "mt": "isolated", + "iw": "6570.42511771", + "ps": "SHORT" + } + ] + } +} +)"; + rj::Document document; + document.Parse(textMessage.c_str()); + auto messageList = this->service->createEvent(std::shared_ptr(), subscription, textMessage, document, this->now).getMessageList(); + EXPECT_EQ(messageList.size(), 1); + verifyCorrelationId(messageList, subscription.getCorrelationId()); + auto message = messageList.at(0); + EXPECT_EQ(message.getType(), Message::Type::EXECUTION_MANAGEMENT_EVENTS_POSITION_UPDATE); + auto elementList = message.getElementList(); + EXPECT_EQ(elementList.size(), 3); + Element element = elementList.at(0); + EXPECT_EQ(element.getValue(CCAPI_INSTRUMENT), "BTCUSDT"); + EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_SIDE), "BOTH"); + EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_QUANTITY), "0"); + EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_ENTRY_PRICE), "0.00000"); + EXPECT_EQ(element.getValue(CCAPI_EM_UNREALIZED_PNL), "0"); +} + TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, createEventExecutionTypeNew) { Subscription subscription(CCAPI_EXCHANGE_NAME_BINANCE_USDS_FUTURES, "BTCUSDT", CCAPI_EM_ORDER_UPDATE); std::string textMessage = R"( @@ -301,7 +404,6 @@ TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, convertTextMessageToMes Element element = elementList.at(0); EXPECT_EQ(element.getValue(CCAPI_EM_ASSET), "USDT"); EXPECT_EQ(element.getValue(CCAPI_EM_QUANTITY_AVAILABLE_FOR_TRADING), "23.72469206"); - EXPECT_EQ(element.getValue(CCAPI_LAST_UPDATED_TIME_SECONDS), "1625474304.765"); } TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, convertRequestGetAccountPositions) { @@ -321,24 +423,21 @@ TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, convertTextMessageToMes std::string textMessage = R"( [ - { - "entryPrice": "0.00000", - "breakEvenPrice": "0.0", - "marginType": "isolated", - "isAutoAddMargin": "false", - "isolatedMargin": "0.00000000", - "leverage": "10", - "liquidationPrice": "0", - "markPrice": "6679.50671178", - "maxNotionalValue": "20000000", - "positionAmt": "0.000", - "notional": "0", - "isolatedWallet": "0", - "symbol": "BTCUSDT", - "unrealizedProfit": "0.00000000", - "positionSide": "BOTH", - "updateTime": 0 - } + { + "symbol": "BTCUSDT", + "initialMargin": "0", + "maintMargin": "0", + "unrealizedProfit": "0.00000000", + "positionInitialMargin": "0", + "openOrderInitialMargin": "0", + "leverage": "100", + "isolated": true, + "entryPrice": "0.00000", + "maxNotional": "250000", + "positionSide": "BOTH", + "positionAmt": "0", + "updateTime": 0 + } ] )"; auto messageList = this->service->convertTextMessageToMessageRest(request, textMessage, this->now); @@ -351,10 +450,9 @@ TEST_F(ExecutionManagementServiceBinanceUsdsFuturesTest, convertTextMessageToMes Element element = elementList.at(0); EXPECT_EQ(element.getValue(CCAPI_INSTRUMENT), "BTCUSDT"); EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_SIDE), "BOTH"); - EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_QUANTITY), "0.000"); + EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_QUANTITY), "0"); EXPECT_DOUBLE_EQ(std::stod(element.getValue(CCAPI_EM_POSITION_ENTRY_PRICE)), 0); - EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_LEVERAGE), "10"); - EXPECT_EQ(element.getValue(CCAPI_LAST_UPDATED_TIME_SECONDS), "0"); + EXPECT_EQ(element.getValue(CCAPI_EM_POSITION_LEVERAGE), "100"); } } /* namespace ccapi */ #endif