diff --git a/include/ccapi_cpp/service/ccapi_execution_management_service_bybit.h b/include/ccapi_cpp/service/ccapi_execution_management_service_bybit.h index 12983bc8..85d8438d 100644 --- a/include/ccapi_cpp/service/ccapi_execution_management_service_bybit.h +++ b/include/ccapi_cpp/service/ccapi_execution_management_service_bybit.h @@ -34,6 +34,7 @@ class ExecutionManagementServiceBybit : public ExecutionManagementServiceBybitBa this->cancelOrderTarget = "/spot/v3/private/cancel-order"; this->getOrderTarget = "/spot/v3/private/order"; this->getOpenOrdersTarget = "/spot/v3/private/open-orders"; + this->cancelOpenOrdersTarget = "/spot/v3/private/cancel-orders"; this->getAccountBalancesTarget = "/spot/v3/private/account"; } virtual ~ExecutionManagementServiceBybit() {} @@ -85,7 +86,7 @@ class ExecutionManagementServiceBybit : public ExecutionManagementServiceBybitBa document.AddMember("orderType", rj::Value("LIMIT").Move(), allocator); } if (!symbolId.empty()) { - this->appendSymbolId(document, allocator, symbolId); + this->appendSymbolId(document, allocator, symbolId, "symbol"); } rj::StringBuffer stringBuffer; rj::Writer writer(stringBuffer); @@ -126,11 +127,31 @@ class ExecutionManagementServiceBybit : public ExecutionManagementServiceBybitBa const std::map param = request.getFirstParamWithDefault(); this->appendParamToQueryString(queryString, param); if (!symbolId.empty()) { - this->appendSymbolId(queryString, symbolId); + this->appendSymbolId(queryString, symbolId, "symbol"); } req.target(this->getOpenOrdersTarget + "?" + queryString); this->signRequest(req, queryString, now, credential); } break; + case Request::Operation::CANCEL_OPEN_ORDERS: { + req.method(http::verb::post); + req.set(beast::http::field::content_type, "application/json"); + const std::map param = request.getFirstParamWithDefault(); + req.target(this->cancelOpenOrdersTarget); + rj::Document document; + document.SetObject(); + rj::Document::AllocatorType& allocator = document.GetAllocator(); + this->appendParam(document, allocator, param); + if (!symbolId.empty()) { + this->appendSymbolId(document, allocator, symbolId, "symbol"); + } + rj::StringBuffer stringBuffer; + rj::Writer writer(stringBuffer); + document.Accept(writer); + auto body = stringBuffer.GetString(); + req.body() = body; + req.prepare_payload(); + this->signRequest(req, body, now, credential); + } break; case Request::Operation::GET_ACCOUNT_BALANCES: { req.method(http::verb::get); std::string queryString; @@ -161,7 +182,7 @@ class ExecutionManagementServiceBybit : public ExecutionManagementServiceBybitBa this->extractOrderInfo(element, x, extractionFieldNameMap); elementList.emplace_back(std::move(element)); } - } else { + } else if (operation != Request::Operation::CANCEL_OPEN_ORDERS) { Element element; this->extractOrderInfo(element, document["result"], extractionFieldNameMap); elementList.emplace_back(std::move(element)); @@ -198,14 +219,15 @@ class ExecutionManagementServiceBybit : public ExecutionManagementServiceBybitBa event.setType(Event::Type::SUBSCRIPTION_DATA); const rj::Value& data = document["data"]; for (const auto& x : data.GetArray()) { - Message message; - message.setTimeReceived(timeReceived); - message.setCorrelationIdList({subscription.getCorrelationId()}); std::string instrument = x["s"].GetString(); if (instrumentSet.empty() || instrumentSet.find(instrument) != instrumentSet.end()) { - message.setTime(TimePoint(std::chrono::milliseconds(std::stoll(x["E"].GetString())))); + auto time = TimePoint(std::chrono::milliseconds(std::stoll(x["E"].GetString()))); auto itTradeId = x.FindMember("t"); if (itTradeId != x.MemberEnd() && !itTradeId->value.IsNull() && fieldSet.find(CCAPI_EM_PRIVATE_TRADE) != fieldSet.end()) { + Message message; + message.setTimeReceived(timeReceived); + message.setCorrelationIdList({subscription.getCorrelationId()}); + message.setTime(time); message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE); std::vector elementList; Element element; @@ -233,6 +255,10 @@ class ExecutionManagementServiceBybit : public ExecutionManagementServiceBybitBa messageList.emplace_back(std::move(message)); } if (fieldSet.find(CCAPI_EM_ORDER_UPDATE) != fieldSet.end()) { + Message message; + message.setTimeReceived(timeReceived); + message.setCorrelationIdList({subscription.getCorrelationId()}); + message.setTime(time); message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_ORDER_UPDATE); const std::map >& extractionFieldNameMap = { {CCAPI_EM_ORDER_ID, std::make_pair("i", JsonDataType::INTEGER)}, diff --git a/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_base.h b/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_base.h index 9ccce8bb..b51c8a8c 100644 --- a/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_base.h +++ b/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_base.h @@ -54,14 +54,14 @@ class ExecutionManagementServiceBybitBase : public ExecutionManagementService { queryString += "&"; } } - void appendSymbolId(std::string& queryString, const std::string& symbolId) { - queryString += "symbol="; - queryString += Url::urlEncode(symbolId); - queryString += "&"; - } - void appendSymbolId(rj::Value& rjValue, rj::Document::AllocatorType& allocator, const std::string& symbolId) { - rjValue.AddMember("symbol", rj::Value(symbolId.c_str(), allocator).Move(), allocator); - } + // void appendSymbolId(std::string& queryString, const std::string& symbolId) { + // queryString += "symbol="; + // queryString += Url::urlEncode(symbolId); + // queryString += "&"; + // } + // void appendSymbolId(rj::Value& rjValue, rj::Document::AllocatorType& allocator, const std::string& symbolId) { + // rjValue.AddMember("symbol", rj::Value(symbolId.c_str(), allocator).Move(), allocator); + // } void prepareReq(http::request& req, const TimePoint& now, const std::map& credential) { auto apiKey = mapGetWithDefault(credential, this->apiKeyName); req.set("X-BAPI-SIGN-TYPE", "2"); diff --git a/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_derivatives.h b/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_derivatives.h index 8cde5f4d..603be4e3 100644 --- a/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_derivatives.h +++ b/include/ccapi_cpp/service/ccapi_execution_management_service_bybit_derivatives.h @@ -88,7 +88,7 @@ class ExecutionManagementServiceBybitDerivatives : public ExecutionManagementSer document.AddMember("orderType", rj::Value("Limit").Move(), allocator); } if (!symbolId.empty()) { - this->appendSymbolId(document, allocator, symbolId); + this->appendSymbolId(document, allocator, symbolId, "symbol"); } rj::StringBuffer stringBuffer; rj::Writer writer(stringBuffer); @@ -107,7 +107,7 @@ class ExecutionManagementServiceBybitDerivatives : public ExecutionManagementSer document.SetObject(); rj::Document::AllocatorType& allocator = document.GetAllocator(); this->appendParam(document, allocator, param); - this->appendSymbolId(document, allocator, symbolId); + this->appendSymbolId(document, allocator, symbolId, "symbol"); rj::StringBuffer stringBuffer; rj::Writer writer(stringBuffer); document.Accept(writer); @@ -142,7 +142,7 @@ class ExecutionManagementServiceBybitDerivatives : public ExecutionManagementSer {CCAPI_INSTRUMENT_TYPE, "category"}, }); if (!symbolId.empty()) { - this->appendSymbolId(queryString, symbolId); + this->appendSymbolId(queryString, symbolId, "symbol"); } req.target(this->getOpenOrdersTarget + "?" + queryString); this->signRequest(req, queryString, now, credential); @@ -157,7 +157,7 @@ class ExecutionManagementServiceBybitDerivatives : public ExecutionManagementSer rj::Document::AllocatorType& allocator = document.GetAllocator(); this->appendParam(document, allocator, param); if (!symbolId.empty()) { - this->appendSymbolId(document, allocator, symbolId); + this->appendSymbolId(document, allocator, symbolId, "symbol"); } rj::StringBuffer stringBuffer; rj::Writer writer(stringBuffer); diff --git a/include/ccapi_cpp/service/ccapi_execution_management_service_kucoin_base.h b/include/ccapi_cpp/service/ccapi_execution_management_service_kucoin_base.h index 0ea6c905..a203c977 100644 --- a/include/ccapi_cpp/service/ccapi_execution_management_service_kucoin_base.h +++ b/include/ccapi_cpp/service/ccapi_execution_management_service_kucoin_base.h @@ -200,8 +200,7 @@ class ExecutionManagementServiceKucoinBase : public ExecutionManagementService { std::string id = useOrderId ? param.at(CCAPI_EM_ORDER_ID) : param.find(CCAPI_EM_CLIENT_ORDER_ID) != param.end() ? param.at(CCAPI_EM_CLIENT_ORDER_ID) : ""; - auto target = - std::regex_replace(useOrderId ? this->getOrderTarget : this->getOrderByClientOrderIdTarget, std::regex(""), Url::urlEncode(id)); + auto target = std::regex_replace(useOrderId ? this->getOrderTarget : this->getOrderByClientOrderIdTarget, std::regex(""), Url::urlEncode(id)); req.target(target); this->signRequest(req, "", credential); } break; @@ -209,10 +208,9 @@ class ExecutionManagementServiceKucoinBase : public ExecutionManagementService { req.method(http::verb::get); auto target = this->getOpenOrdersTarget; target += "?status=active"; - target += std::string("&tradeType=") + - (request.getMarginType() == CCAPI_EM_MARGIN_TYPE_CROSS_MARGIN ? "MARGIN_TRADE" - : request.getMarginType() == CCAPI_EM_MARGIN_TYPE_ISOLATED_MARGIN ? "MARGIN_ISOLATED_TRADE" - : "TRADE"); + target += std::string("&tradeType=") + (request.getMarginType() == CCAPI_EM_MARGIN_TYPE_CROSS_MARGIN ? "MARGIN_TRADE" + : request.getMarginType() == CCAPI_EM_MARGIN_TYPE_ISOLATED_MARGIN ? "MARGIN_ISOLATED_TRADE" + : "TRADE"); if (!symbolId.empty()) { target += "&symbol="; target += symbolId; @@ -223,10 +221,9 @@ class ExecutionManagementServiceKucoinBase : public ExecutionManagementService { case Request::Operation::CANCEL_OPEN_ORDERS: { req.method(http::verb::delete_); auto target = this->cancelOpenOrdersTarget; - target += std::string("?tradeType=") + - (request.getMarginType() == CCAPI_EM_MARGIN_TYPE_CROSS_MARGIN ? "MARGIN_TRADE" - : request.getMarginType() == CCAPI_EM_MARGIN_TYPE_ISOLATED_MARGIN ? "MARGIN_ISOLATED_TRADE" - : "TRADE"); + target += std::string("?tradeType=") + (request.getMarginType() == CCAPI_EM_MARGIN_TYPE_CROSS_MARGIN ? "MARGIN_TRADE" + : request.getMarginType() == CCAPI_EM_MARGIN_TYPE_ISOLATED_MARGIN ? "MARGIN_ISOLATED_TRADE" + : "TRADE"); if (!symbolId.empty()) { target += "&symbol="; target += symbolId; @@ -387,9 +384,13 @@ class ExecutionManagementServiceKucoinBase : public ExecutionManagementService { std::string instrument = data["symbol"].GetString(); if (instrumentSet.empty() || instrumentSet.find(instrument) != instrumentSet.end()) { std::string ts = std::string(data["ts"].GetString()); - message.setTime(UtilTime::makeTimePoint({std::stoll(ts.substr(0, ts.length() - 9)), std::stoll(ts.substr(ts.length() - 9))})); + auto time = UtilTime::makeTimePoint({std::stoll(ts.substr(0, ts.length() - 9)), std::stoll(ts.substr(ts.length() - 9))}); std::string dataType = data["type"].GetString(); - if (dataType == "match" && (fieldSet.find(CCAPI_EM_PRIVATE_TRADE) != fieldSet.end() || fieldSet.find(CCAPI_EM_ORDER_UPDATE) != fieldSet.end())) { + if (dataType == "match" && fieldSet.find(CCAPI_EM_PRIVATE_TRADE) != fieldSet.end()) { + Message message; + message.setTimeReceived(timeReceived); + message.setCorrelationIdList({subscription.getCorrelationId()}); + message.setTime(time); message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE); std::vector elementList; Element element; @@ -405,6 +406,10 @@ class ExecutionManagementServiceKucoinBase : public ExecutionManagementService { messageList.emplace_back(std::move(message)); } if (fieldSet.find(CCAPI_EM_ORDER_UPDATE) != fieldSet.end()) { + Message message; + message.setTimeReceived(timeReceived); + message.setCorrelationIdList({subscription.getCorrelationId()}); + message.setTime(time); message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_ORDER_UPDATE); std::map > extractionFieldNameMap = { {CCAPI_EM_ORDER_ID, std::make_pair("orderId", JsonDataType::STRING)}, diff --git a/include/ccapi_cpp/service/ccapi_service.h b/include/ccapi_cpp/service/ccapi_service.h index a3dd0bf5..289ebf61 100644 --- a/include/ccapi_cpp/service/ccapi_service.h +++ b/include/ccapi_cpp/service/ccapi_service.h @@ -592,6 +592,7 @@ class Service : public std::enable_shared_from_this { if (ec) { CCAPI_LOGGER_TRACE("fail"); this->onError(Event::Type::REQUEST_STATUS, Message::Type::REQUEST_FAILURE, ec, "write", {request.getCorrelationId()}, eventQueuePtr); + this->httpConnectionPool.purge(); auto now = UtilTime::now(); auto req = this->convertRequest(request, now); retry.numRetry += 1; @@ -832,6 +833,9 @@ class Service : public std::enable_shared_from_this { ++i; } } + void appendSymbolId(rj::Value& rjValue, rj::Document::AllocatorType& allocator, const std::string& symbolId, const std::string symbolIdCalled) { + rjValue.AddMember(rj::Value(symbolIdCalled.c_str(), allocator).Move(), rj::Value(symbolId.c_str(), allocator).Move(), allocator); + } void appendSymbolId(std::string& queryString, const std::string& symbolId, const std::string symbolIdCalled) { if (!symbolId.empty()) { queryString += symbolIdCalled;