Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
# Notice
* Small breaking change: renamed `toStringPretty` to `toPrettyString`.
* Added FIX API support for binance.

<!-- START doctoc generated TOC please keep comment here to allow auto update -->

**Table of Contents** *generated with [DocToc](https://github.com/ktechhub/doctoc)*

<!---toc start-->

* [Notice](#notice)
* [ccapi](#ccapi)
* [Branches](#branches)
* [Build](#build)
Expand Down Expand Up @@ -57,12 +52,11 @@

<!-- END doctoc generated TOC please keep comment here to allow auto update -->


# ccapi
* A header-only C++ library for streaming market data and executing trades directly from cryptocurrency exchanges (i.e. the connections are between your server and the exchange server without anything in-between).
* Bindings for other languages such as Python, Java, C#, Go, and Javascript are provided.
* Code closely follows Bloomberg's API: https://www.bloomberg.com/professional/support/api-library/.
* It is ultra fast thanks to very careful optimizations: move semantics, regex optimization, locality of reference, lock contention minimization, etc.
* It is ultra fast thanks to very careful optimizations.
* Supported exchanges:
* Market Data: ascendex, [binance](https://www.marketwebb.net/activity/referral-entry/CPA?ref=CPA_00WFM0HU96), [binance-usds-futures](https://www.marketwebb.net/activity/referral-entry/CPA?ref=CPA_00WFM0HU96), [binance-coin-futures](https://www.marketwebb.net/activity/referral-entry/CPA?ref=CPA_00WFM0HU96), bitfinex, bitget, bitget-futures, bitmart, bitmex, bitstamp, [bybit](https://www.bybit.com/invite?ref=XNYP2K), coinbase, [cryptocom](https://crypto.com/exch/tqj4b8x48w), deribit, erisx (Cboe Digital), [gateio](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), [gateio-perpetual-futures](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), gemini, huobi, huobi-usdt-swap, huobi-coin-swap, kraken, kraken-futures, kucoin, kucoin-futures, mexc, mexc-futures, [okx](https://www.okx.com/join/47636709), whitebit.
* Execution Management: ascendex, [binance](https://www.marketwebb.net/activity/referral-entry/CPA?ref=CPA_00WFM0HU96), [binance-usds-futures](https://www.marketwebb.net/activity/referral-entry/CPA?ref=CPA_00WFM0HU96), [binance-coin-futures](https://www.marketwebb.net/activity/referral-entry/CPA?ref=CPA_00WFM0HU96), bitfinex, bitget, bitget-futures, bitmart, bitmex, bitstamp, [bybit](https://www.bybit.com/invite?ref=XNYP2K), coinbase, [cryptocom](https://crypto.com/exch/tqj4b8x48w), deribit, erisx (Cboe Digital), [gateio](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), [gateio-perpetual-futures](https://www.gate.com/signup/VLUQXVFWAW?ref_type=103), gemini, huobi, huobi-usdt-swap, huobi-coin-swap, kraken, kraken-futures, kucoin, kucoin-futures, mexc, [okx](https://www.okx.com/join/47636709).
Expand Down Expand Up @@ -610,7 +604,7 @@ class MyEventHandler : public EventHandler {
{"SIDE", "BUY"},
{"LIMIT_PRICE", "20000"},
{"QUANTITY", "0.001"},
{"CLIENT_ORDER_ID", "6d4eb0fb"},
{"CLIENT_ORDER_ID", request.generateNextClientOrderId()},
});
sessionPtr->sendRequest(request);
}
Expand Down Expand Up @@ -703,7 +697,7 @@ Received an event of type SUBSCRIPTION_DATA:
]
Bye
```
* Subscription fields: `ORDER_UPDATE`, `PRIVATE_TRADE`, `BALANCE_UPDATE`, `POSITION_UPDATE`.
* Subscription fields: `ORDER_UPDATE`, `PRIVATE_TRADE`, `PRIVATE_TRADE_LITE`, `BALANCE_UPDATE`, `POSITION_UPDATE`.

### Advanced Execution Management

Expand Down
16 changes: 9 additions & 7 deletions example/src/execution_management_simple_subscription/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,25 @@ Logger* Logger::logger = nullptr; // This line is needed.
class MyEventHandler : public EventHandler {
public:
void processEvent(const Event& event, Session* sessionPtr) override {
if (event.getType() == Event::Type::SUBSCRIPTION_STATUS) {
std::cout << "Received an event of type SUBSCRIPTION_STATUS:\n" + event.toPrettyString(2, 2) << std::endl;
auto message = event.getMessageList().at(0);
if (message.getType() == Message::Type::SUBSCRIPTION_STARTED) {
std::cout << "Received an event:\n" + event.toPrettyString(2, 2) << std::endl;
if (!willSendRequest) {
sessionPtr->setTimer("id", 1000, nullptr, [this, sessionPtr]() {
Request request(Request::Operation::CREATE_ORDER, "okx", "BTC-USDT");
request.appendParam({
{"SIDE", "BUY"},
{"LIMIT_PRICE", "20000"},
{"QUANTITY", "0.001"},
{"CLIENT_ORDER_ID", request.generateNextClientOrderId()},
});
std::cout << "About to send a request:\n" + request.toString() << std::endl;
sessionPtr->sendRequest(request);
}
} else if (event.getType() == Event::Type::SUBSCRIPTION_DATA) {
std::cout << "Received an event of type SUBSCRIPTION_DATA:\n" + event.toPrettyString(2, 2) << std::endl;
});
willSendRequest = true;
}
}

private:
bool willSendRequest{};
};

} /* namespace ccapi */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,34 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
const auto& fieldSet = subscription.getFieldSet();
const auto& instrumentSet = subscription.getInstrumentSet();
std::string type = document["e"].GetString();
if (type == (this->isDerivatives ? "ORDER_TRADE_UPDATE" : "executionReport")) {
if (type == "TRADE_LITE") {
event.setType(Event::Type::SUBSCRIPTION_DATA);
const rj::Value& data = document;
std::string instrument = data["s"].GetString();
if (instrumentSet.empty() || instrumentSet.find(UtilString::toUpper(instrument)) != instrumentSet.end() ||
instrumentSet.find(UtilString::toLower(instrument)) != instrumentSet.end()) {
if (fieldSet.find(CCAPI_EM_PRIVATE_TRADE_LITE) != fieldSet.end()) {
Message message;
message.setTimeReceived(timeReceived);
message.setCorrelationIdList({subscription.getCorrelationId()});
message.setTime(TimePoint(std::chrono::milliseconds(std::stoll(data["E"].GetString()))));
message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE_LITE);
std::vector<Element> elementList;
Element element;
element.insert(CCAPI_TRADE_ID, data["t"].GetString());
element.insert(CCAPI_EM_ORDER_LAST_EXECUTED_PRICE, data["L"].GetString());
element.insert(CCAPI_EM_ORDER_LAST_EXECUTED_SIZE, data["l"].GetString());
element.insert(CCAPI_EM_ORDER_SIDE, std::string_view(data["S"].GetString()) == "BUY" ? CCAPI_EM_ORDER_SIDE_BUY : CCAPI_EM_ORDER_SIDE_SELL);
element.insert(CCAPI_IS_MAKER, data["m"].GetBool() ? "1" : "0");
element.insert(CCAPI_EM_ORDER_ID, data["i"].GetString());
element.insert(CCAPI_EM_CLIENT_ORDER_ID, data["c"].GetString());
element.insert(CCAPI_EM_ORDER_INSTRUMENT, instrument);
elementList.emplace_back(std::move(element));
message.setElementList(elementList);
messageList.emplace_back(std::move(message));
}
}
} else if (type == (this->isDerivatives ? "ORDER_TRADE_UPDATE" : "executionReport")) {
event.setType(Event::Type::SUBSCRIPTION_DATA);
const rj::Value& data = this->isDerivatives ? document["o"] : document;
std::string executionType = data["x"].GetString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,8 @@ class ExecutionManagementServiceBybit : public ExecutionManagementService {
message.setTimeReceived(timeReceived);
message.setCorrelationIdList({subscription.getCorrelationId()});
message.setTime(time);
message.setType(Message::Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE);
message.setType(topic.rfind("execution.fast", 0) == 0 ? Message::Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE_LITE
: Message::Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE);
std::vector<Element> elementList;
Element element;
element.insert(CCAPI_TRADE_ID, x["execId"].GetString());
Expand Down Expand Up @@ -551,6 +552,9 @@ class ExecutionManagementServiceBybit : public ExecutionManagementService {
if (fieldSet.find(CCAPI_EM_PRIVATE_TRADE) != fieldSet.end()) {
args.PushBack(rj::Value((instrumentType.empty() ? "execution" : "execution." + instrumentType).c_str(), allocator).Move(), allocator);
}
if (fieldSet.find(CCAPI_EM_PRIVATE_TRADE_LITE) != fieldSet.end()) {
args.PushBack(rj::Value((instrumentType.empty() ? "execution.fast" : "execution.fast." + instrumentType).c_str(), allocator).Move(), allocator);
}
if (fieldSet.find(CCAPI_EM_POSITION_UPDATE) != fieldSet.end() && subscription.getInstrumentType() != "spot") {
args.PushBack(rj::Value((instrumentType.empty() ? "position" : "position." + instrumentType).c_str(), allocator).Move(), allocator);
}
Expand Down