Skip to content

Commit

Permalink
Merge pull request #488 from crypto-chassis/develop
Browse files Browse the repository at this point in the history
misc: integrate BitMart api broker; feat: updated execution for Bitget futures
  • Loading branch information
obergaba authored Nov 5, 2024
2 parents 832168f + 28fe04b commit 9c957b5
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 45 deletions.
6 changes: 6 additions & 0 deletions include/ccapi_cpp/ccapi_macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,9 @@
#ifndef CCAPI_INSTRUMENT
#define CCAPI_INSTRUMENT "INSTRUMENT"
#endif
#ifndef CCAPI_MARGIN_MODE
#define CCAPI_MARGIN_MODE "MARGIN_MODE"
#endif
#ifndef CCAPI_EM_ORDER_STATUS
#define CCAPI_EM_ORDER_STATUS "STATUS"
#endif
Expand Down Expand Up @@ -1218,4 +1221,7 @@
#ifndef CCAPI_BINANCE_USDS_FUTURES_API_LINK_ID
#define CCAPI_BINANCE_USDS_FUTURES_API_LINK_ID "QzcVS63u"
#endif
#ifndef CCAPI_BITMART_BROKER_ID
#define CCAPI_BITMART_BROKER_ID "cryptochassis01"
#endif
#endif // INCLUDE_CCAPI_CPP_CCAPI_MACRO_H_
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
ServiceContextPtr serviceContextPtr)
: ExecutionManagementServiceBitgetBase(eventHandler, sessionOptions, sessionConfigs, serviceContextPtr) {
this->exchangeName = CCAPI_EXCHANGE_NAME_BITGET_FUTURES;
this->baseUrlWs = sessionConfigs.getUrlWebsocketBase().at(this->exchangeName) + "/mix/v1/stream";
this->baseUrlWs = sessionConfigs.getUrlWebsocketBase().at(this->exchangeName) + "/v2/ws/private";
this->baseUrlRest = sessionConfigs.getUrlRestBase().at(this->exchangeName);
this->setHostRestFromUrlRest(this->baseUrlRest);
this->setHostWsFromUrlWs(this->baseUrlWs);
Expand All @@ -31,15 +31,15 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
this->apiSecretName = CCAPI_BITGET_FUTURES_API_SECRET;
this->apiPassphraseName = CCAPI_BITGET_FUTURES_API_PASSPHRASE;
this->setupCredential({this->apiKeyName, this->apiSecretName, this->apiPassphraseName});
this->createOrderTarget = "/api/mix/v1/order/placeOrder";
this->cancelOrderTarget = "/api/mix/v1/order/cancel-order";
this->getOrderTarget = "/api/mix/v1/order/detail";
this->getOpenOrdersTarget = "/api/mix/v1/order/current";
this->getAllOpenOrdersTarget = "/api/mix/v1/order/marginCoinCurrent";
this->cancelOpenOrdersTarget = "/api/mix/v1/order/cancel-all-orders";
this->getAccountBalancesTarget = "/api/mix/v1/account/accounts";
this->getAccountPositionsTarget = "/api/mix/v1/position/singlePosition";
this->getAccountAllPositionsTarget = "/api/mix/v1/position/allPosition";
this->createOrderTarget = "/api/v2/mix/order/place-order";
this->cancelOrderTarget = "/api/v2/mix/order/cancel-order";
this->getOrderTarget = "/api/v2/mix/order/detail";
this->getOpenOrdersTarget = "/api/v2/mix/order/orders-pending";
this->getAllOpenOrdersTarget = "/api/v2/mix/order/orders-pending";
this->cancelOpenOrdersTarget = "/api/v2/mix/order/cancel-all-orders";
this->getAccountBalancesTarget = "/api/v2/mix/account/accounts";
this->getAccountPositionsTarget = "/api/v2/mix/position/single-position";
this->getAccountAllPositionsTarget = "/api/v2/mix/position/all-position";
}
virtual ~ExecutionManagementServiceBitgetFutures() {}
#ifndef CCAPI_EXPOSE_INTERNAL
Expand All @@ -49,6 +49,7 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
void appendParam(Request::Operation operation, rj::Value& rjValue, rj::Document::AllocatorType& allocator, const std::map<std::string, std::string>& param,
const std::map<std::string, std::string> standardizationMap = {
{CCAPI_MARGIN_ASSET, "marginCoin"},
{CCAPI_MARGIN_MODE, "marginMode"},
{CCAPI_EM_ORDER_SIDE, "side"},
{CCAPI_EM_ORDER_QUANTITY, "size"},
{CCAPI_EM_ORDER_LIMIT_PRICE, "price"},
Expand All @@ -65,8 +66,9 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
}
void appendParam(std::string& queryString, const std::map<std::string, std::string>& param,
const std::map<std::string, std::string> standardizationMap = {
{CCAPI_MARGIN_ASSET, "marginCoin"},
{CCAPI_EM_ORDER_ID, "orderId"},
{CCAPI_EM_CLIENT_ORDER_ID, "clientOrderId"},
{CCAPI_EM_CLIENT_ORDER_ID, "clientOid"},
{CCAPI_SYMBOL_ID, "symbol"},
{CCAPI_INSTRUMENT_TYPE, "productType"},
}) {
Expand Down Expand Up @@ -97,9 +99,6 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
if (param.find("orderType") == param.end()) {
document.AddMember("orderType", rj::Value("limit").Move(), allocator);
}
if (param.find("timeInForceValue") == param.end()) {
document.AddMember("timeInForceValue", rj::Value("normal").Move(), allocator);
}
if (!symbolId.empty()) {
this->appendSymbolId(document, allocator, symbolId);
}
Expand Down Expand Up @@ -219,20 +218,34 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
{CCAPI_EM_ORDER_SIDE, std::make_pair("side", JsonDataType::STRING)},
{CCAPI_EM_ORDER_QUANTITY, std::make_pair("size", JsonDataType::STRING)},
{CCAPI_EM_ORDER_LIMIT_PRICE, std::make_pair("price", JsonDataType::STRING)},
{CCAPI_EM_ORDER_CUMULATIVE_FILLED_QUANTITY, std::make_pair("filledQty", JsonDataType::STRING)},
{CCAPI_EM_ORDER_STATUS, std::make_pair("state", JsonDataType::STRING)},
{CCAPI_EM_ORDER_CUMULATIVE_FILLED_QUANTITY, std::make_pair("baseVolume", JsonDataType::STRING)},
{CCAPI_EM_ORDER_STATUS, std::make_pair("status", JsonDataType::STRING)},
{CCAPI_EM_ORDER_INSTRUMENT, std::make_pair("symbol", JsonDataType::STRING)}};
const rj::Value& data = document["data"];
if (operation == Request::Operation::CREATE_ORDER || operation == Request::Operation::CANCEL_ORDER || operation == Request::Operation::GET_ORDER) {
const rj::Value& data = document["data"];
Element element;
this->extractOrderInfo(element, data, extractionFieldNameMap);
elementList.emplace_back(std::move(element));
} else if (operation == Request::Operation::GET_OPEN_ORDERS) {
const rj::Value& data = document["data"]["entrustedList"];
for (const auto& x : data.GetArray()) {
Element element;
this->extractOrderInfo(element, x, extractionFieldNameMap);
elementList.emplace_back(std::move(element));
}
} else if (operation == Request::Operation::CANCEL_OPEN_ORDERS) {
const rj::Value& successList = document["data"]["successList"];
for (const auto& x : successList.GetArray()) {
Element element;
this->extractOrderInfo(element, x, extractionFieldNameMap);
elementList.emplace_back(std::move(element));
}
const rj::Value& failureList = document["data"]["failureList"];
for (const auto& x : failureList.GetArray()) {
Element element;
this->extractOrderInfo(element, x, extractionFieldNameMap);
elementList.emplace_back(std::move(element));
}
}
}
void extractAccountInfoFromRequest(std::vector<Element>& elementList, const Request& request, const Request::Operation operation,
Expand All @@ -242,7 +255,7 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
for (const auto& x : document["data"].GetArray()) {
Element element;
element.insert(CCAPI_EM_ASSET, x["marginCoin"].GetString());
std::string available = x["crossMaxAvailable"].GetString();
std::string available = x["crossedMaxAvailable"].GetString();
element.insert(CCAPI_EM_QUANTITY_AVAILABLE_FOR_TRADING, available);
std::string locked = x["locked"].GetString();
element.insert(CCAPI_EM_QUANTITY_TOTAL, (Decimal(available).add(Decimal(locked))).toString());
Expand All @@ -256,8 +269,9 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
element.insert(CCAPI_MARGIN_ASSET, x["marginCoin"].GetString());
element.insert(CCAPI_EM_POSITION_SIDE, x["holdSide"].GetString());
element.insert(CCAPI_EM_POSITION_QUANTITY, x["total"].GetString());
element.insert(CCAPI_EM_POSITION_ENTRY_PRICE, x["averageOpenPrice"].GetString());
element.insert(CCAPI_EM_POSITION_ENTRY_PRICE, x["openPriceAvg"].GetString());
element.insert(CCAPI_EM_POSITION_LEVERAGE, x["leverage"].GetString());
element.insert(CCAPI_EM_UNREALIZED_PNL, x["unrealizedPL"].GetString());
elementList.emplace_back(std::move(element));
}
} break;
Expand All @@ -269,8 +283,8 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
const std::map<std::string, std::function<std::string(const std::string&)>> conversionMap = {}) override {
ExecutionManagementService::extractOrderInfo(element, x, extractionFieldNameMap);
{
auto it1 = x.FindMember("accFillSz");
auto it2 = x.FindMember("avgPx");
auto it1 = x.FindMember("accBaseVolume");
auto it2 = x.FindMember("priceAvg");
if (it1 != x.MemberEnd() && it2 != x.MemberEnd()) {
auto it1Str = std::string(it1->value.GetString());
auto it2Str = std::string(it2->value.GetString());
Expand Down Expand Up @@ -332,17 +346,27 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
const auto& instrumentSet = subscription.getInstrumentSet();
const auto& instrumentType = subscription.getInstrumentType();
for (const auto& field : fieldSet) {
std::string channel;
if (fieldSet.find(CCAPI_EM_ORDER_UPDATE) != fieldSet.end() || fieldSet.find(CCAPI_EM_PRIVATE_TRADE) != fieldSet.end()) {
channel = "orders";
}
for (const auto& instrument : instrumentSet) {
rj::Value arg(rj::kObjectType);
arg.AddMember("channel", rj::Value(channel.c_str(), allocator).Move(), allocator);
arg.AddMember("instId", rj::Value(instrument.c_str(), allocator).Move(), allocator);
arg.AddMember("instType", rj::Value(instrumentType.c_str(), allocator).Move(), allocator);
args.PushBack(arg, allocator);
}
if (field == CCAPI_EM_ORDER_UPDATE || field == CCAPI_EM_PRIVATE_TRADE) {
for (const auto& instrument : instrumentSet) {
rj::Value arg(rj::kObjectType);
arg.AddMember("channel", rj::Value("orders", allocator).Move(), allocator);
arg.AddMember("instId", rj::Value(instrument.c_str(), allocator).Move(), allocator);
arg.AddMember("instType", rj::Value(instrumentType.c_str(), allocator).Move(), allocator);
args.PushBack(arg, allocator);
}
} else if (field == CCAPI_EM_POSITION_UPDATE) {
rj::Value arg(rj::kObjectType);
arg.AddMember("channel", rj::Value("positions", allocator).Move(), allocator);
arg.AddMember("instId", rj::Value("default", allocator).Move(), allocator);
arg.AddMember("instType", rj::Value(instrumentType.c_str(), allocator).Move(), allocator);
args.PushBack(arg, allocator);
} else if (field == CCAPI_EM_BALANCE_UPDATE) {
rj::Value arg(rj::kObjectType);
arg.AddMember("channel", rj::Value("account", allocator).Move(), allocator);
arg.AddMember("coin", rj::Value("default", allocator).Move(), allocator);
arg.AddMember("instType", rj::Value(instrumentType.c_str(), allocator).Move(), allocator);
args.PushBack(arg, allocator);
}
}
document.AddMember("args", args, allocator);
rj::StringBuffer stringBufferSubscribe;
Expand Down Expand Up @@ -390,8 +414,9 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
const rj::Value& arg = document["arg"];
std::string channel = std::string(arg["channel"].GetString());
event.setType(Event::Type::SUBSCRIPTION_DATA);
std::string instrument = arg["instId"].GetString();
if (instrumentSet.empty() || instrumentSet.find(instrument) != instrumentSet.end()) {
std::string instId = (channel == "account") ? "coin" : "instId";
std::string instrument = arg[instId.c_str()].GetString();
if (instrumentSet.empty() || instrument == "default" || instrumentSet.find(instrument) != instrumentSet.end()) {
if (channel == "orders") {
if (fieldSet.find(CCAPI_EM_PRIVATE_TRADE) != fieldSet.end()) {
const rj::Value& data = document["data"];
Expand All @@ -407,15 +432,19 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
std::vector<Element> elementList;
Element element;
element.insert(CCAPI_TRADE_ID, tradeId);
element.insert(CCAPI_EM_ORDER_LAST_EXECUTED_PRICE, std::string(x["fillPx"].GetString()));
element.insert(CCAPI_EM_ORDER_LAST_EXECUTED_SIZE, std::string(x["fillSz"].GetString()));
element.insert(CCAPI_EM_ORDER_LAST_EXECUTED_PRICE, std::string(x["fillPrice"].GetString()));
element.insert(CCAPI_EM_ORDER_LAST_EXECUTED_SIZE, std::string(x["baseVolume"].GetString()));
element.insert(CCAPI_EM_ORDER_SIDE, std::string(x["side"].GetString()) == "buy" ? CCAPI_EM_ORDER_SIDE_BUY : CCAPI_EM_ORDER_SIDE_SELL);
element.insert(CCAPI_IS_MAKER, std::string(x["execType"].GetString()) == "M" ? "1" : "0");
element.insert(CCAPI_EM_ORDER_ID, std::string(x["ordId"].GetString()));
element.insert(CCAPI_EM_CLIENT_ORDER_ID, std::string(x["clOrdId"].GetString()));
element.insert(CCAPI_IS_MAKER, std::string(x["tradeScope"].GetString()) == "M" ? "1" : "0");
element.insert(CCAPI_EM_ORDER_ID, std::string(x["orderId"].GetString()));
auto itClientOId = x.FindMember("clientOId");
std::string clientOId = itClientOId != x.MemberEnd() ? itClientOId->value.GetString() : "";
if(!clientOId.empty()){
element.insert(CCAPI_EM_CLIENT_ORDER_ID, clientOId);
}
element.insert(CCAPI_EM_ORDER_INSTRUMENT, instrument);
element.insert(CCAPI_EM_ORDER_FEE_QUANTITY, std::string(x["fillFee"].GetString()));
element.insert(CCAPI_EM_ORDER_FEE_ASSET, std::string(x["fillFeeCcy"].GetString()));
element.insert(CCAPI_EM_ORDER_FEE_ASSET, std::string(x["fillFeeCoin"].GetString()));
elementList.emplace_back(std::move(element));
message.setElementList(elementList);
messageList.emplace_back(std::move(message));
Expand All @@ -431,12 +460,12 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
message.setTime(UtilTime::makeTimePointFromMilliseconds(std::stoll(std::string(x["uTime"].GetString()))));
message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_ORDER_UPDATE);
const std::map<std::string, std::pair<std::string, JsonDataType>>& extractionFieldNameMap = {
{CCAPI_EM_ORDER_ID, std::make_pair("ordId", JsonDataType::STRING)},
{CCAPI_EM_CLIENT_ORDER_ID, std::make_pair("clOrdId", JsonDataType::STRING)},
{CCAPI_EM_ORDER_ID, std::make_pair("orderId", JsonDataType::STRING)},
{CCAPI_EM_CLIENT_ORDER_ID, std::make_pair("clientOId", JsonDataType::STRING)},
{CCAPI_EM_ORDER_SIDE, std::make_pair("side", JsonDataType::STRING)},
{CCAPI_EM_ORDER_LIMIT_PRICE, std::make_pair("px", JsonDataType::STRING)},
{CCAPI_EM_ORDER_QUANTITY, std::make_pair("sz", JsonDataType::STRING)},
{CCAPI_EM_ORDER_CUMULATIVE_FILLED_QUANTITY, std::make_pair("accFillSz", JsonDataType::STRING)},
{CCAPI_EM_ORDER_LIMIT_PRICE, std::make_pair("price", JsonDataType::STRING)},
{CCAPI_EM_ORDER_QUANTITY, std::make_pair("size", JsonDataType::STRING)},
{CCAPI_EM_ORDER_CUMULATIVE_FILLED_QUANTITY, std::make_pair("accBaseVolume", JsonDataType::STRING)},
{CCAPI_EM_ORDER_STATUS, std::make_pair("status", JsonDataType::STRING)},
};
Element info;
Expand All @@ -448,6 +477,42 @@ class ExecutionManagementServiceBitgetFutures : public ExecutionManagementServic
messageList.emplace_back(std::move(message));
}
}
} else if (channel == "positions"){
const rj::Value& data = document["data"];
for (const auto& x : data.GetArray()) {
auto time = TimePoint(std::chrono::milliseconds(std::stoll(x["uTime"].GetString())));
Message message;
message.setTimeReceived(timeReceived);
message.setCorrelationIdList({subscription.getCorrelationId()});
message.setTime(time);
message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_POSITION_UPDATE);
std::vector<Element> elementList;
Element element;
element.insert(CCAPI_INSTRUMENT, x["instId"].GetString());
element.insert(CCAPI_EM_POSITION_SIDE, x["holdSide"].GetString());
element.insert(CCAPI_EM_POSITION_QUANTITY, x["total"].GetString());
element.insert(CCAPI_EM_POSITION_ENTRY_PRICE, x["openPriceAvg"].GetString());
element.insert(CCAPI_EM_POSITION_LEVERAGE, x["leverage"].GetString());
elementList.emplace_back(std::move(element));
message.setElementList(elementList);
messageList.emplace_back(std::move(message));
}
} else if (channel == "account"){
const rj::Value& data = document["data"];
for (const auto& x : data.GetArray()) {
Message message;
message.setTimeReceived(timeReceived);
message.setCorrelationIdList({subscription.getCorrelationId()});
message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_BALANCE_UPDATE);
std::vector<Element> elementList;
Element element;
element.insert(CCAPI_EM_ASSET, x["marginCoin"].GetString());
element.insert(CCAPI_EM_QUANTITY_TOTAL, x["equity"].GetString());
element.insert(CCAPI_EM_QUANTITY_AVAILABLE_FOR_TRADING, x["available"].GetString());
elementList.emplace_back(std::move(element));
message.setElementList(elementList);
messageList.emplace_back(std::move(message));
}
}
}
} else if (eventStr == "subscribe") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class ExecutionManagementServiceBitmart : public ExecutionManagementService {
case Request::Operation::CREATE_ORDER: {
req.method(http::verb::post);
req.target(this->createOrderTarget);
req.set("X-BM-BROKER-ID", CCAPI_BITMART_BROKER_ID);
const std::map<std::string, std::string> param = request.getFirstParamWithDefault();
rj::Document document;
document.SetObject();
Expand Down

0 comments on commit 9c957b5

Please sign in to comment.