11# Some breaking changes introduced
2- * Please update boost version to at least 1.87.0.
3- * When a subscription fails due to the underlying websocket connection fails to open, the emitted message type is SUBSCRIPTION_FAILURE_DUE_TO_CONNECTION_FAILURE instead of SUBSCRIPTION_FAILURE.
4- * Removed the spot market making application and the single order execution application.
2+ * We made a change on how to "Send request by Websocket API".
53
64<!-- START doctoc generated TOC please keep comment here to allow auto update -->
7- <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
8- ** Table of Contents** * generated with [ DocToc] ( https://github.com/thlorenz/doctoc ) *
9-
10- - [ ccapi] ( #ccapi )
11- - [ Branches] ( #branches )
12- - [ Build] ( #build )
13- - [ C++] ( #c )
14- - [ non-C++] ( #non-c )
15- - [ Constants] ( #constants )
16- - [ Examples] ( #examples )
17- - [ Documentations] ( #documentations )
18- - [ Simple Market Data] ( #simple-market-data )
19- - [ Advanced Market Data] ( #advanced-market-data )
20- - [ Complex request parameters] ( #complex-request-parameters )
21- - [ Specify subscription market depth] ( #specify-subscription-market-depth )
22- - [ Specify correlation id] ( #specify-correlation-id )
23- - [ Multiple exchanges and/or instruments] ( #multiple-exchanges-andor-instruments )
24- - [ Receive subscription events at periodic intervals] ( #receive-subscription-events-at-periodic-intervals )
25- - [ Receive subscription events at periodic intervals including when the market depth snapshot hasn't changed] ( #receive-subscription-events-at-periodic-intervals-including-when-the-market-depth-snapshot-hasnt-changed )
26- - [ Receive subscription market depth updates] ( #receive-subscription-market-depth-updates )
27- - [ Receive subscription trade events] ( #receive-subscription-trade-events )
28- - [ Receive subscription calculated-candlestick events at periodic intervals] ( #receive-subscription-calculated-candlestick-events-at-periodic-intervals )
29- - [ Receive subscription exchange-provided-candlestick events at periodic intervals] ( #receive-subscription-exchange-provided-candlestick-events-at-periodic-intervals )
30- - [ Send generic public requests] ( #send-generic-public-requests )
31- - [ Make generic public subscriptions] ( #make-generic-public-subscriptions )
32- - [ Send generic private requests] ( #send-generic-private-requests )
33- - [ Simple Execution Management] ( #simple-execution-management )
34- - [ Advanced Execution Management] ( #advanced-execution-management )
35- - [ Specify correlation id] ( #specify-correlation-id-1 )
36- - [ Multiple exchanges and/or instruments] ( #multiple-exchanges-andor-instruments-1 )
37- - [ Multiple subscription fields] ( #multiple-subscription-fields )
38- - [ Make Session::sendRequest blocking] ( #make-sessionsendrequest-blocking )
39- - [ Provide API credentials for an exchange] ( #provide-api-credentials-for-an-exchange )
40- - [ Override exchange urls] ( #override-exchange-urls )
41- - [ Complex request parameters] ( #complex-request-parameters-1 )
42- - [ Send request by Websocket API] ( #send-request-by-websocket-api )
43- - [ Specify instrument type] ( #specify-instrument-type )
44- - [ FIX API] ( #fix-api )
45- - [ More Advanced Topics] ( #more-advanced-topics )
46- - [ Handle events in "immediate" vs. "batching" mode] ( #handle-events-in-immediate-vs-batching-mode )
47- - [ Thread safety] ( #thread-safety )
48- - [ Enable library logging] ( #enable-library-logging )
49- - [ Set timer] ( #set-timer )
50- - [ Performance Tuning] ( #performance-tuning )
51- - [ Known Issues and Workarounds] ( #known-issues-and-workarounds )
52- - [ Contributing] ( #contributing )
5+
6+ ** Table of Contents** * generated with [ DocToc] ( https://github.com/ktechhub/doctoc ) *
7+
8+ <!-- -toc start-->
9+
10+ * [ Some breaking changes introduced] ( #some-breaking-changes-introduced )
11+ * [ ccapi] ( #ccapi )
12+ * [ Branches] ( #branches )
13+ * [ Build] ( #build )
14+ * [ C++] ( #c )
15+ * [ non-C++] ( #non-c )
16+ * [ Constants] ( #constants )
17+ * [ Examples] ( #examples )
18+ * [ Documentations] ( #documentations )
19+ * [ Simple Market Data] ( #simple-market-data )
20+ * [ Advanced Market Data] ( #advanced-market-data )
21+ * [ Complex request parameters] ( #complex-request-parameters )
22+ * [ Specify subscription market depth] ( #specify-subscription-market-depth )
23+ * [ Specify correlation id] ( #specify-correlation-id )
24+ * [ Multiple exchanges and/or instruments] ( #multiple-exchanges-andor-instruments )
25+ * [ Receive subscription events at periodic intervals] ( #receive-subscription-events-at-periodic-intervals )
26+ * [ Receive subscription events at periodic intervals including when the market depth snapshot hasn't changed] ( #receive-subscription-events-at-periodic-intervals-including-when-the-market-depth-snapshot-hasnt-changed )
27+ * [ Receive subscription market depth updates] ( #receive-subscription-market-depth-updates )
28+ * [ Receive subscription trade events] ( #receive-subscription-trade-events )
29+ * [ Receive subscription calculated-candlestick events at periodic intervals] ( #receive-subscription-calculated-candlestick-events-at-periodic-intervals )
30+ * [ Receive subscription exchange-provided-candlestick events at periodic intervals] ( #receive-subscription-exchange-provided-candlestick-events-at-periodic-intervals )
31+ * [ Send generic public requests] ( #send-generic-public-requests )
32+ * [ Make generic public subscriptions] ( #make-generic-public-subscriptions )
33+ * [ Send generic private requests] ( #send-generic-private-requests )
34+ * [ Simple Execution Management] ( #simple-execution-management )
35+ * [ Advanced Execution Management] ( #advanced-execution-management )
36+ * [ Specify correlation id] ( #specify-correlation-id-1 )
37+ * [ Multiple exchanges and/or instruments] ( #multiple-exchanges-andor-instruments-1 )
38+ * [ Multiple subscription fields] ( #multiple-subscription-fields )
39+ * [ Make Session::sendRequest blocking] ( #make-sessionsendrequest-blocking )
40+ * [ Provide API credentials for an exchange] ( #provide-api-credentials-for-an-exchange )
41+ * [ Override exchange urls] ( #override-exchange-urls )
42+ * [ Complex request parameters] ( #complex-request-parameters-1 )
43+ * [ Send request by Websocket API] ( #send-request-by-websocket-api )
44+ * [ Specify instrument type] ( #specify-instrument-type )
45+ * [ FIX API] ( #fix-api )
46+ * [ More Advanced Topics] ( #more-advanced-topics )
47+ * [ Handle events in "immediate" vs. "batching" mode] ( #handle-events-in-immediate-vs-batching-mode )
48+ * [ Thread safety] ( #thread-safety )
49+ * [ Enable library logging] ( #enable-library-logging )
50+ * [ Set timer] ( #set-timer )
51+ * [ Performance Tuning] ( #performance-tuning )
52+ * [ Known Issues and Workarounds] ( #known-issues-and-workarounds )
53+ * [ Contributing] ( #contributing )
54+
55+ <!-- -toc end-->
5356
5457<!-- END doctoc generated TOC please keep comment here to allow auto update -->
58+
59+
5560# ccapi
5661* 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).
5762* Bindings for other languages such as Python, Java, C#, Go, and Javascript are provided.
@@ -220,7 +225,7 @@ Logger* Logger::logger = nullptr; // This line is needed.
220225
221226class MyEventHandler : public EventHandler {
222227 public:
223- bool processEvent(const Event& event, Session* session ) override {
228+ bool processEvent(const Event& event, Session* sessionPtr ) override {
224229 std::cout << "Received an event:\n" + event.toStringPretty(2, 2) << std::endl;
225230 return true;
226231 }
@@ -297,7 +302,7 @@ Logger* Logger::logger = nullptr; // This line is needed.
297302
298303class MyEventHandler : public EventHandler {
299304 public:
300- bool processEvent(const Event& event, Session* session ) override {
305+ bool processEvent(const Event& event, Session* sessionPtr ) override {
301306 if (event.getType() == Event::Type::SUBSCRIPTION_STATUS) {
302307 std::cout << "Received an event of type SUBSCRIPTION_STATUS:\n" + event.toStringPretty(2, 2) << std::endl;
303308 } else if (event.getType() == Event::Type::SUBSCRIPTION_DATA) {
@@ -386,13 +391,15 @@ Request request_1(Request::Operation::GET_RECENT_TRADES, "okx", "BTC-USDT", "coo
386391request_1.appendParam(...);
387392Request request_2(Request::Operation::GET_RECENT_TRADES, "binance", "ETH-USDT", "cool correlation id for ETH");
388393request_2.appendParam(...);
389- session.sendRequest({request_1, request_2});
394+ std::vector<ccapi::Request> requests = {request_1, request_2};
395+ session.sendRequest(requests);
390396```
391397Subscribe a ` std::vector<Subscription> ` .
392398```
393399Subscription subscription_1("okx", "BTC-USDT", "MARKET_DEPTH", "", "cool correlation id for okx BTC-USDT");
394400Subscription subscription_2("binance", "ETH-USDT", "MARKET_DEPTH", "", "cool correlation id for binance ETH-USDT");
395- session.subscribe({subscription_1, subscription_2});
401+ std::vector<ccapi::Subscription> subscriptions = {subscription_1, subscription_2};
402+ session.subscribe(subscriptions);
396403```
397404
398405#### Receive subscription events at periodic intervals
@@ -434,7 +441,7 @@ Subscription subscription("okx", "BTC-USDT", "TRADE", "CONFLATE_INTERVAL_MILLISE
434441
435442Instantiate ` Subscription ` with field ` CANDLESTICK ` and option ` CANDLESTICK_INTERVAL_SECONDS ` set to be the desired interval.
436443```
437- Subscription subscription("okx", "BTC-USDTT ", "CANDLESTICK", "CANDLESTICK_INTERVAL_SECONDS=60");
444+ Subscription subscription("okx", "BTC-USDT ", "CANDLESTICK", "CANDLESTICK_INTERVAL_SECONDS=60");
438445```
439446
440447#### Send generic public requests
@@ -487,7 +494,7 @@ Logger* Logger::logger = nullptr; // This line is needed.
487494
488495class MyEventHandler : public EventHandler {
489496 public:
490- bool processEvent(const Event& event, Session* session ) override {
497+ bool processEvent(const Event& event, Session* sessionPtr ) override {
491498 std::cout << "Received an event:\n" + event.toStringPretty(2, 2) << std::endl;
492499 return true;
493500 }
@@ -585,7 +592,7 @@ Logger* Logger::logger = nullptr; // This line is needed.
585592
586593class MyEventHandler : public EventHandler {
587594 public:
588- bool processEvent(const Event& event, Session* session ) override {
595+ bool processEvent(const Event& event, Session* sessionPtr ) override {
589596 if (event.getType() == Event::Type::SUBSCRIPTION_STATUS) {
590597 std::cout << "Received an event of type SUBSCRIPTION_STATUS:\n" + event.toStringPretty(2, 2) << std::endl;
591598 auto message = event.getMessageList().at(0);
@@ -597,7 +604,7 @@ class MyEventHandler : public EventHandler {
597604 {"QUANTITY", "0.001"},
598605 {"CLIENT_ORDER_ID", "6d4eb0fb"},
599606 });
600- session ->sendRequest(request);
607+ sessionPtr ->sendRequest(request);
601608 }
602609 } else if (event.getType() == Event::Type::SUBSCRIPTION_DATA) {
603610 std::cout << "Received an event of type SUBSCRIPTION_DATA:\n" + event.toStringPretty(2, 2) << std::endl;
@@ -712,7 +719,8 @@ Request request_1(Request::Operation::CREATE_ORDER, "okx", "BTC-USDT", "cool cor
712719request_1.appendParam(...);
713720Request request_2(Request::Operation::CREATE_ORDER, "okx", "ETH-USDT", "cool correlation id for ETH");
714721request_2.appendParam(...);
715- session.sendRequest({request_1, request_2});
722+ std::vector<ccapi::Request> requests = {request_1, request_2};
723+ session.sendRequest(requests);
716724```
717725Subscribe one ` Subscription ` per exchange with a comma separated string of instruments.
718726```
@@ -774,23 +782,41 @@ request.appendParam({
774782```
775783
776784#### Send request by Websocket API
785+ For okx:
777786```
778- Subscription subscription("okx", "BTC-USDTT", "ORDER_UPDATE", "", "same correlation id for subscription and request");
787+ std::string websocketOrderEntrySubscriptionCorrelationId("any");
788+ Subscription subscription("okx", "", "ORDER_UPDATE", "", websocketOrderEntrySubscriptionCorrelationId);
779789session.subscribe(subscription);
780790...
781- Request request(Request::Operation::CREATE_ORDER, "okx", "BTC-USDTT", "same correlation id for subscription and request");
791+ Request request(Request::Operation::CREATE_ORDER, "okx", "BTC-USDT");
792+ request.appendParam({
793+ {"SIDE", "BUY"},
794+ {"LIMIT_PRICE", "20000"},
795+ {"QUANTITY", "0.001"},
796+ });
797+ session.sendRequestByWebsocket(websocketOrderEntrySubscriptionCorrelationId, request);
798+ ```
799+ For bybit:
800+ ```
801+ std::string websocketOrderEntrySubscriptionCorrelationId("any");
802+ Subscription subscription_1("bybit", "", "ORDER_UPDATE");
803+ Subscription subscription_2("bybit", "", "WEBSOCKET_ORDER_ENTRY", "", websocketOrderEntrySubscriptionCorrelationId);
804+ std::vector<ccapi::Subscription> subscriptions = {subscription_1, subscription_2};
805+ session.subscribe(subscriptions);
806+ ...
807+ Request request(Request::Operation::CREATE_ORDER, "bybit", "BTCUSDT");
782808request.appendParam({
783809 {"SIDE", "BUY"},
784810 {"LIMIT_PRICE", "20000"},
785811 {"QUANTITY", "0.001"},
786812});
787- session.sendRequestByWebsocket(request);
813+ session.sendRequestByWebsocket(websocketOrderEntrySubscriptionCorrelationId, request);
788814```
789815
790816#### Specify instrument type
791817Some exchanges (i.e. bybit) might need instrument type for ` Subscription ` . Use ` Subscription ` 's ` setInstrumentType ` method.
792818```
793- Subscription subscription("bybit", "BTCUSDTT ", "MARKET_DEPTH");
819+ Subscription subscription("bybit", "BTCUSDT ", "MARKET_DEPTH");
794820subscription.setInstrumentType("spot");
795821session.subscribe(subscription);
796822```
@@ -810,7 +836,7 @@ namespace ccapi {
810836Logger* Logger::logger = nullptr; // This line is needed.
811837class MyEventHandler : public EventHandler {
812838 public:
813- bool processEvent(const Event& event, Session* session ) override {
839+ bool processEvent(const Event& event, Session* sessionPtr ) override {
814840 if (event.getType() == Event::Type::AUTHORIZATION_STATUS) {
815841 std::cout << "Received an event of type AUTHORIZATION_STATUS:\n" + event.toStringPretty(2, 2) << std::endl;
816842 auto message = event.getMessageList().at(0);
@@ -826,7 +852,7 @@ class MyEventHandler : public EventHandler {
826852 {40, "2"},
827853 {59, "1"},
828854 });
829- session ->sendRequestByFix(request);
855+ sessionPtr ->sendRequestByFix(request);
830856 }
831857 } else if (event.getType() == Event::Type::FIX) {
832858 std::cout << "Received an event of type FIX:\n" + event.toStringPretty(2, 2) << std::endl;
@@ -975,7 +1001,7 @@ Logger* Logger::logger = &myLogger;
9751001
9761002To perform an asynchronous wait, use the utility method ` setTimer ` in class ` Session ` . The handlers are invoked in the same threads as the ` processEvent ` method in the ` EventHandler ` class. The ` id ` of the timer should be unique. ` delayMilliseconds ` can be 0.
9771003```
978- session ->setTimer(
1004+ sessionPtr ->setTimer(
9791005 "id", 1000,
9801006 [](const boost::system::error_code&) {
9811007 std::cout << std::string("Timer error handler is triggered at ") + UtilTime::getISOTimestamp(UtilTime::now()) << std::endl;
0 commit comments