Skip to content

Commit

Permalink
Merge pull request #29 from crypto-chassis/execution_management
Browse files Browse the repository at this point in the history
Execution management
  • Loading branch information
cryptochassis authored Dec 15, 2020
2 parents 1dc5b9c + 5386328 commit 31c72b1
Show file tree
Hide file tree
Showing 31 changed files with 1,081 additions and 863 deletions.
57 changes: 26 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
* Example CMake: example/CMakeLists.txt.
* Require C++14 and OpenSSL.
* Definitions in the compiler command line:
* Define service enablement macro ENABLE_SERVICE_MARKET_DATA and exchange enablement macros such as ENABLE_EXCHANGE_COINBASE, etc. These macros can be found at the top of include/ccapi_cpp/ccapi_session.h.
* If your OpenSSL version is older than 1.1, define macro OPENSSL_VERSION_MAJOR and OPENSSL_VERSION_MINOR (e.g. for OpenSSL 1.0.2s, define OPENSSL_VERSION_MAJOR to be 1 and OPENSSL_VERSION_MINOR to be 0).
* Define service enablement macro `ENABLE_SERVICE_MARKET_DATA` and exchange enablement macros such as `ENABLE_EXCHANGE_COINBASE`, etc. These macros can be found at the top of `include/ccapi_cpp/ccapi_session.h`.
* If your OpenSSL version is older than 1.1, define macro `OPENSSL_VERSION_MAJOR` and `OPENSSL_VERSION_MINOR` (e.g. for OpenSSL 1.0.2s, define `OPENSSL_VERSION_MAJOR` to be 1 and `OPENSSL_VERSION_MINOR` to be 0).
* Include directories:
* include
* dependency/websocketpp
Expand All @@ -55,11 +55,11 @@
* OpenSSL: libcrypto
* If you need huobi or okex, also link ZLIB.
* Troubleshoot:
* "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR (missing: OPENSSL_INCLUDE_DIR)": try cmake -DOPENSSL_ROOT_DIR=...(e.g. /usr/local/opt/openssl)
* "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR (missing: OPENSSL_INCLUDE_DIR)": try `cmake -DOPENSSL_ROOT_DIR=...`. On macOS, you might be missing headers for OpenSSL. `brew install openssl` and `cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl`.
* "No such file or directory" for thread-related headers if Windows MinGW without posix threads is used: please enable it (https://stackoverflow.com/questions/17242516/mingw-w64-threads-posix-vs-win32) or use Boost (so that e.g. boost/thread.hpp can be found).

## Constants
include/ccapi_cpp/ccapi_macro.h
`include/ccapi_cpp/ccapi_macro.h`

## Examples
[Source](example)
Expand Down Expand Up @@ -118,21 +118,21 @@ Best bid and ask at 2020-07-27T23:56:51.935993000Z are:
### Advanced
#### Specify market depth

Instantiate Subscription with option MARKET_DEPTH_MAX set to be the desired market depth.
Instantiate `Subscription` with option `MARKET_DEPTH_MAX` set to be the desired market depth.
```
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "MARKET_DEPTH_MAX=10");
```

#### Specify correlation id

Instantiate Subscription with the desired correlationId.
Instantiate `Subscription` with the desired correlationId.
```
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "", "cool correlation id");
```

#### Normalize instrument name

Instantiate SessionConfigs with a map mapping the exchange name and the normalized instrument name to the instrument's symbol on the exchange.
Instantiate `SessionConfigs` with a map mapping the exchange name and the normalized instrument name to the instrument's symbol on the exchange.
```
std::map<std::string, std::map<std::string, std::string> > exchangeInstrumentSymbolMap;
std::string coolName = "btc_usd";
Expand All @@ -144,7 +144,7 @@ Subscription subscription("coinbase", coolName, "MARKET_DEPTH");

#### Multiple exchanges and/or instruments

Subscribe a std::vector<Subscription>.
Subscribe a `std::vector<Subscription>`.
```
std::vector<Subscription> subscriptionList;
Subscription subscription_1("coinbase", "BTC-USD", "MARKET_DEPTH", "", "coinbase|btc_usd");
Expand All @@ -156,29 +156,30 @@ session.subscribe(subscriptionList);

#### Receive events at periodic intervals

Instantiate Subscription with option CONFLATE_INTERVAL_MILLISECONDS set to be the desired interval.
Instantiate `Subscription` with option `CONFLATE_INTERVAL_MILLISECONDS` set to be the desired interval.
```
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "CONFLATE_INTERVAL_MILLISECONDS=1000");
```

#### Receive events at periodic intervals including when the market depth snapshot hasn't changed

Instantiate Subscription with option CCAPI_EXCHANGE_NAME_CONFLATE_INTERVAL_MILLISECONDS set to be the desired interval and CCAPI_EXCHANGE_NAME_CONFLATE_GRACE_PERIOD_MILLISECONDS to be your network latency.
Instantiate `Subscription` with option `CCAPI_EXCHANGE_NAME_CONFLATE_INTERVAL_MILLISECONDS` set to be the desired interval and `CCAPI_EXCHANGE_NAME_CONFLATE_GRACE_PERIOD_MILLISECONDS` to be your network latency.
```
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "CONFLATE_INTERVAL_MILLISECONDS=1000&CONFLATE_GRACE_PERIOD_MILLISECONDS=0");
```

#### Dispatch events to multiple threads

Instantiate EventDispatcher with numDispatcherThreads set to be the desired number.
Instantiate `EventDispatcher` with
`numDispatcherThreads` set to be the desired number.
```
EventDispatcher eventDispatcher(2);
Session session(sessionOptions, sessionConfigs, &eventHandler, &eventDispatcher);
```

#### Handle Events Synchronously

Instantiate Session without EventHandler, then obtain the events to be processed by calling session.eventQueue.purge().
Instantiate `Session` without `EventHandler`, then obtain the events to be processed by calling `session.eventQueue.purge()`.
```
Session session(sessionOptions, sessionConfigs);
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH");
Expand All @@ -189,29 +190,23 @@ std::vector<Event> eventList = session.eventQueue.purge();

#### Enable library logging

Add one of the following macros in the compiler command line: ENABLE_LOG_TRACE, ENABLE_LOG_DEBUG, ENABLE_LOG_INFO, ENABLE_LOG_WARN, ENABLE_LOG_ERROR, ENABLE_LOG_FATAL. Extend a subclass, e.g. MyLogger, from class Logger and override method logMessage. Assign a MyLogger pointer to Logger::logger.
Extend a subclass, e.g. `MyLogger`, from class `Logger` and override method `logMessage`. Assign a `MyLogger` pointer to `Logger::logger`. Add one of the following macros in the compiler command line: `ENABLE_LOG_TRACE`, `ENABLE_LOG_DEBUG`, `ENABLE_LOG_INFO`, `ENABLE_LOG_WARN`, `ENABLE_LOG_ERROR`, `ENABLE_LOG_FATAL`.
```
namespace ccapi {
Logger* Logger::logger = nullptr; // This line is needed.
class MyLogger final: public Logger {
public:
virtual void logMessage(Logger::Severity severity, std::thread::id threadId,
std::chrono::system_clock::time_point time,
std::string fileName, int lineNumber,
std::string message) override {
std::cout << threadId << ": [" << UtilTime::getISOTimestamp(time) << "] {"
<< fileName << ":" << lineNumber << "} "
<< Logger::severityToString(severity) << std::string(8, ' ') << message
<< std::endl;
}
};
}
...
using namespace ccapi;
class MyLogger final: public Logger {
public:
virtual void logMessage(Logger::Severity severity, std::thread::id threadId,
std::chrono::system_clock::time_point time,
std::string fileName, int lineNumber,
std::string message) override {
...
}
};
MyLogger myLogger;
Logger::logger = &myLogger;
Logger* Logger::logger = &myLogger;
}
```

Add one of the following macros in the compiler command line: `ENABLE_LOG_TRACE`, `ENABLE_LOG_DEBUG`, `ENABLE_LOG_INFO`, `ENABLE_LOG_WARN`, `ENABLE_LOG_ERROR`, `ENABLE_LOG_FATAL`.
### Contributing
* (Required) Submit a pull request to the master branch.
* (Required) Pass Github checks: https://docs.github.com/en/rest/reference/checks.
Expand Down
49 changes: 29 additions & 20 deletions example/src/execution_management_simple/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace ccapi {
Logger* Logger::logger = nullptr; // This line is needed.
class MyEventHandler : public EventHandler {
public:
bool processEvent(const Event& event, Session *session) override {
std::cout << "Received an event: " + toString(event) << std::endl;
return true;
Expand All @@ -19,66 +20,74 @@ int main(int argc, char** argv) {
std::string mode(argv[1]);
std::string key = UtilSystem::getEnvAsString("BINANCE_US_API_KEY");
if (key.empty()) {
std::cerr << "Please provide environment variable BINANCE_US_API_KEY" << std::endl;
std::cerr << "Please set environment variable BINANCE_US_API_KEY" << std::endl;
return EXIT_FAILURE;
}
std::string secret = UtilSystem::getEnvAsString("BINANCE_US_API_SECRET");
if (secret.empty()) {
std::cerr << "Please provide environment variable BINANCE_US_API_SECRET" << std::endl;
std::cerr << "Please set environment variable BINANCE_US_API_SECRET" << std::endl;
return EXIT_FAILURE;
}
std::map<std::string, std::string> credential = { { CCAPI_BINANCE_US_API_KEY, key }, { CCAPI_BINANCE_US_API_SECRET,
secret } };
SessionOptions sessionOptions;
SessionConfigs sessionConfigs;
MyEventHandler eventHandler;
Session session(sessionOptions, sessionConfigs, &eventHandler);
Queue<Event> eventQueue;
if (mode == "create_order") {
if (argc != 6) {
std::cerr << "Usage: <program name> create_order <symbol> <buy or sell> <order quantity> <limit price>\n"
<< "Example:\n" << " main create_order BTCUSD buy 0.0005 20000" << std::endl;
session.stop();
return EXIT_FAILURE;
}
Request request(Request::Operation::CREATE_ORDER, credential, "binance-us", argv[2]);
request.setParam("SIDE", strcmp(argv[3], "buy") == 0 ? "BUY" : "SELL");
request.setParam("QUANTITY", argv[4]);
request.setParam("LIMIT_PRICE", argv[5]);
session.sendRequest(request, &eventQueue);
Request request(Request::Operation::CREATE_ORDER, "binance-us", argv[2]);
request.appendParam({
{"SIDE", strcmp(argv[3], "buy") == 0 ? "BUY" : "SELL"},
{"QUANTITY", argv[4]},
{"LIMIT_PRICE", argv[5]}
});
session.sendRequest(request);
} else if (mode == "cancel_order") {
if (argc != 4) {
std::cerr << "Usage: <program name> cancel_order <symbol> <order id>\n" << "Example:\n"
<< " main cancel_order BTCUSD 4" << std::endl;
session.stop();
return EXIT_FAILURE;
}
Request request(Request::Operation::CANCEL_ORDER, credential, "binance-us", argv[2]);
request.setParam("ORDER_ID", argv[3]);
session.sendRequest(request, &eventQueue);
Request request(Request::Operation::CANCEL_ORDER, "binance-us", argv[2]);
request.appendParam({
{"ORDER_ID", argv[3]}
});
session.sendRequest(request);
} else if (mode == "get_order") {
if (argc != 4) {
std::cerr << "Usage: <program name> get_order <symbol> <order id>\n" << "Example:\n"
<< " main get_order BTCUSD 4" << std::endl;
session.stop();
return EXIT_FAILURE;
}
Request request(Request::Operation::GET_ORDER, credential, "binance-us", argv[2]);
request.setParam("ORDER_ID", argv[3]);
session.sendRequest(request, &eventQueue);
Request request(Request::Operation::GET_ORDER, "binance-us", argv[2]);
request.appendParam({
{"ORDER_ID", argv[3]}
});
session.sendRequest(request);
} else if (mode == "get_open_orders") {
if (argc != 3) {
std::cerr << "Usage: <program name> get_open_orders <symbol>\n" << "Example:\n"
<< " main get_open_orders BTCUSD" << std::endl;
session.stop();
return EXIT_FAILURE;
}
Request request(Request::Operation::GET_OPEN_ORDERS, credential, "binance-us", argv[2]);
session.sendRequest(request, &eventQueue);
Request request(Request::Operation::GET_OPEN_ORDERS, "binance-us", argv[2]);
session.sendRequest(request);
} else if (mode == "cancel_open_orders") {
if (argc != 3) {
std::cerr << "Usage: <program name> cancel_open_orders <symbol>\n" << "Example:\n"
<< " main cancel_open_orders BTCUSD" << std::endl;
session.stop();
return EXIT_FAILURE;
}
Request request(Request::Operation::CANCEL_OPEN_ORDERS, credential, "binance-us", argv[2]);
session.sendRequest(request, &eventQueue);
Request request(Request::Operation::CANCEL_OPEN_ORDERS, "binance-us", argv[2]);
session.sendRequest(request);
}
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
Expand Down
28 changes: 15 additions & 13 deletions example/src/sample_market_making/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,14 @@ int main(int argc, char **argv) {
std::string orderQuantity = argv[2];
std::string key = UtilSystem::getEnvAsString("BINANCE_US_API_KEY");
if (key.empty()) {
std::cerr << "Please provide environment variable BINANCE_US_API_KEY" << std::endl;
std::cerr << "Please set environment variable BINANCE_US_API_KEY" << std::endl;
return EXIT_FAILURE;
}
std::string secret = UtilSystem::getEnvAsString("BINANCE_US_API_SECRET");
if (secret.empty()) {
std::cerr << "Please provide environment variable BINANCE_US_API_SECRET" << std::endl;
std::cerr << "Please set environment variable BINANCE_US_API_SECRET" << std::endl;
return EXIT_FAILURE;
}
std::map<std::string, std::string> credential = { { CCAPI_BINANCE_US_API_KEY, key }, { CCAPI_BINANCE_US_API_SECRET,
secret } };
SessionOptions sessionOptions;
SessionConfigs sessionConfigs;
MyEventHandler eventHandler;
Expand All @@ -67,7 +65,7 @@ int main(int argc, char **argv) {
session.subscribe(subscription);
while (true) {
// https://github.com/binance-us/binance-official-api-docs/blob/master/rest-api.md#signed-endpoint-examples-for-post-apiv3order: All symbols for REST are uppercase
Request requestCancel(Request::Operation::CANCEL_OPEN_ORDERS, credential, "binance-us", "BTCUSD");
Request requestCancel(Request::Operation::CANCEL_OPEN_ORDERS, "binance-us", "BTCUSD");
session.sendRequest(requestCancel);
std::cout << "Cancel all open orders" << std::endl;
auto bbo = eventHandler.getBBO();
Expand All @@ -77,15 +75,19 @@ int main(int argc, char **argv) {
std::string buyPrice = regularizePrice(midPrice * (1 - spreadPercentage / 100));
std::string sellPrice = regularizePrice(midPrice * (1 + spreadPercentage / 100));
std::vector<Request> requestList;
Request requestBuy(Request::Operation::CREATE_ORDER, credential, "binance-us", "BTCUSD");
requestBuy.setParam("SIDE", "BUY");
requestBuy.setParam("QUANTITY", orderQuantity);
requestBuy.setParam("LIMIT_PRICE", buyPrice);
Request requestBuy(Request::Operation::CREATE_ORDER, "binance-us", "BTCUSD");
requestBuy.appendParam({
{"SIDE", "BUY"},
{"QUANTITY", orderQuantity},
{"LIMIT_PRICE", buyPrice}
});
requestList.push_back(requestBuy);
Request requestSell(Request::Operation::CREATE_ORDER, credential, "binance-us", "BTCUSD");
requestSell.setParam("SIDE", "SELL");
requestSell.setParam("QUANTITY", orderQuantity);
requestSell.setParam("LIMIT_PRICE", sellPrice);
Request requestSell(Request::Operation::CREATE_ORDER, "binance-us", "BTCUSD");
requestSell.appendParam({
{"SIDE", "SELL"},
{"QUANTITY", orderQuantity},
{"LIMIT_PRICE", sellPrice}
});
requestList.push_back(requestSell);
session.sendRequest(requestList);
std::cout << "Buy " + orderQuantity + " BTCUSD at price " + buyPrice << std::endl;
Expand Down
42 changes: 36 additions & 6 deletions include/ccapi_cpp/ccapi_macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,6 @@
#ifndef CCAPI_EXECUTION_MANAGEMENT
#define CCAPI_EXECUTION_MANAGEMENT "execution_management"
#endif
#ifndef CCAPI_BINANCE_US_API_KEY
#define CCAPI_BINANCE_US_API_KEY "BINANCE_US_API_KEY"
#endif
#ifndef CCAPI_BINANCE_US_API_SECRET
#define CCAPI_BINANCE_US_API_SECRET "BINANCE_US_API_SECRET"
#endif
#define CCAPI_EM_ORDER "ORDER"
#ifndef CCAPI_EM_ORDER_SIDE
#define CCAPI_EM_ORDER_SIDE "SIDE"
Expand Down Expand Up @@ -180,4 +174,40 @@
#ifndef CCAPI_CORRELATION_ID_GENERATED_LENGTH
#define CCAPI_CORRELATION_ID_GENERATED_LENGTH 32
#endif
#ifndef CCAPI_BINANCE_US_URL_REST_BASE
#define CCAPI_BINANCE_US_URL_REST_BASE "https://api.binance.us"
#endif
#ifndef CCAPI_BINANCE_US_CREATE_ORDER_TARGET
#define CCAPI_BINANCE_US_CREATE_ORDER_TARGET "/api/v3/order"
#endif
#ifndef CCAPI_BINANCE_URL_REST_BASE
#define CCAPI_BINANCE_URL_REST_BASE "https://api.binance.com"
#endif
#ifndef CCAPI_BINANCE_CREATE_ORDER_TARGET
#define CCAPI_BINANCE_CREATE_ORDER_TARGET "/api/v3/order"
#endif
#ifndef CCAPI_BINANCE_FUTURES_URL_REST_BASE
#define CCAPI_BINANCE_FUTURES_URL_REST_BASE "https://fapi.binance.com"
#endif
#ifndef CCAPI_BINANCE_FUTURES_CREATE_ORDER_TARGET
#define CCAPI_BINANCE_FUTURES_CREATE_ORDER_TARGET "/fapi/v1/order"
#endif
#ifndef CCAPI_BINANCE_US_API_KEY
#define CCAPI_BINANCE_US_API_KEY "BINANCE_US_API_KEY"
#endif
#ifndef CCAPI_BINANCE_US_API_SECRET
#define CCAPI_BINANCE_US_API_SECRET "BINANCE_US_API_SECRET"
#endif
#ifndef CCAPI_BINANCE_API_KEY
#define CCAPI_BINANCE_API_KEY "BINANCE_API_KEY"
#endif
#ifndef CCAPI_BINANCE_API_SECRET
#define CCAPI_BINANCE_API_SECRET "BINANCE_API_SECRET"
#endif
#ifndef CCAPI_BINANCE_FUTURES_API_KEY
#define CCAPI_BINANCE_FUTURES_API_KEY "BINANCE_FUTURES_API_KEY"
#endif
#ifndef CCAPI_BINANCE_FUTURES_API_SECRET
#define CCAPI_BINANCE_FUTURES_API_SECRET "BINANCE_FUTURES_API_SECRET"
#endif
#endif // INCLUDE_CCAPI_CPP_CCAPI_MACRO_H_
Loading

0 comments on commit 31c72b1

Please sign in to comment.