multithreaded bot for algo trading on crypto exchanges
sudo apt-get install cmake
sudo apt-get install python3-dev
sudo apt-get install libboost1.83-all-dev
sudo apt-get install libssl-dev
set (PROJECT_NAME test_reading)
project(${PROJECT_NAME})
file(GLOB SRC "*.cpp" )
add_executable (${PROJECT_NAME} ${SRC} )
target_link_libraries(${PROJECT_NAME} aot concurrentqueue::concurrentqueue Python::Python ${Boost_LIBRARIES} unordered_dense::unordered_dense )
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 23)
1. For Binance launch trade engine + generator bid/ask events service. check update BBO and BBODouble
```c++
#include <aot/WS.h>
#include <boost/beast/core.hpp>
#include <cmath>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include "aot/Binance.h"
#include "aot/Bybit.h"
#include "aot/Logger.h"
#include "aot/Predictor.h"
#include "aot/common/types.h"
#include "aot/order_gw/order_gw.h"
#include "aot/strategy/kline.h"
#include "aot/strategy/market_order_book.h"
#include "aot/strategy/trade_engine.h"
#include "aot/third_party/emhash/hash_table7.hpp"
#include "aot/launcher_predictor.h"
#include "moodycamel/concurrentqueue.h"
int main() {
fmtlog::setLogLevel(fmtlog::INF);
using namespace binance;
Exchange::EventLFQueue event_queue;//this queue contains bids and asks from the bid ask generator
Exchange::RequestNewLimitOrderLFQueue request_new_order;//this queue contains requests for new limit order
Exchange::RequestCancelOrderLFQueue request_cancel_order;//this queue contains requests for cancel order by id
Exchange::ClientResponseLFQueue response;//this queue contains response from exchange when you send new order or send request cancel order
OHLCVILFQueue ohlcv_queue;//this queue contains klines from exchange. in this example this queue always empty
DiffDepthStream::ms100 interval;
TickerInfo info{2, 5};//set manual price precission and qty precission for ticker
Symbol btcusdt("BTC", "USDT");
Ticker ticker(&btcusdt, info);
GeneratorBidAskService generator(&event_queue, ticker, &interval,
TypeExchange::TESTNET);
generator.Start();
Trading::TradeEngine trade_engine_service(&event_queue,
&request_new_order, &request_cancel_order, &response, &ohlcv_queue, ticker, nullptr);
trade_engine_service.Start();
while (trade_engine_service.GetDownTimeInS() < 120) {
logd("Waiting till no activity, been silent for {} seconds...",
generator.GetDownTimeInS());
using namespace std::literals::chrono_literals;
std::this_thread::sleep_for(30s);
}
}
#include <aot/WS.h>
int main(int argc, char** argv) { fmtlog::setLogLevel(fmtlog::DBG);
using namespace binance;
hmac_sha256::Keys keys{argv[2], argv[3]};//set api key and secret key
hmac_sha256::Signer signer(keys); //init hmac_sha256 signer
auto type = TypeExchange::TESTNET;
OrderNewLimit new_order(&signer, type);//init executor for send new order limit
CancelOrder executor_cancel_order(&signer, type);//init executor for cancel order by id
using namespace Trading;
Exchange::RequestNewLimitOrderLFQueue requests_new_order;
Exchange::RequestCancelOrderLFQueue requests_cancel_order;
Exchange::ClientResponseLFQueue client_responses;
Exchange::RequestNewOrder request_new_order;//start init manual request new order
request_new_order.ticker = "BTCUSDT";
request_new_order.order_id = 6;
request_new_order.side = common::Side::BUY;
request_new_order.price = 40000;
request_new_order.qty = 0.001;
requests_new_order.enqueue(request_new_order);
OrderGateway gw(&new_order, &executor_cancel_order, &requests_new_order,
&requests_cancel_order,
&client_responses);
gw.start();//start order gateway for process RequestNewOrder
while (gw.GetDownTimeInS() < 7) {
logd("Waiting till no activity, been silent for {} seconds...",
gw.GetDownTimeInS());
using namespace std::literals::chrono_literals;
std::this_thread::sleep_for(3s);
}
Exchange::MEClientResponse response[50];
size_t count_new_order = client_responses.try_dequeue_bulk(response, 50);
for (int i = 0; i < count_new_order; i++) {
logd("{}", response[i].ToString());//check response on new order
}
return 0;
}
![Alt Text](/doc/ForREADME/check_response.png)
3. For Binance test add and cancel order
```c++
#include <aot/WS.h>
#include <boost/beast/core.hpp>
#include <cmath>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include "aot/Binance.h"
#include "aot/Bybit.h"
#include "aot/Logger.h"
#include "aot/Predictor.h"
#include "aot/common/types.h"
#include "aot/order_gw/order_gw.h"
#include "aot/strategy/kline.h"
#include "aot/strategy/market_order_book.h"
#include "aot/strategy/trade_engine.h"
#include "aot/third_party/emhash/hash_table7.hpp"
#include "aot/launcher_predictor.h"
#include "moodycamel/concurrentqueue.h"
int main(int argc, char** argv) {
hmac_sha256::Keys keys{argv[2], argv[3]};
hmac_sha256::Signer signer(keys);
auto type = TypeExchange::TESTNET;
fmtlog::setLogLevel(fmtlog::DBG);
using namespace binance;
OrderNewLimit new_order(&signer, type);
CancelOrder executor_cancel_order(&signer, type);
using namespace Trading;
Exchange::RequestNewLimitOrderLFQueue requests_new_order;
Exchange::RequestCancelOrderLFQueue requests_cancel_order;
Exchange::ClientResponseLFQueue client_responses;
Exchange::RequestNewOrder request_new_order;
request_new_order.ticker = "BTCUSDT";
request_new_order.order_id = 6;//set manual unique id for new buy order
request_new_order.side = common::Side::BUY;
request_new_order.price = 40000;
request_new_order.qty = 0.001;
requests_new_order.enqueue(request_new_order);
Exchange::RequestCancelOrder order_for_cancel;
order_for_cancel.ticker = "BTCUSDT";
order_for_cancel.order_id = 6;//cancel order by manual id
requests_cancel_order.enqueue(order_for_cancel);
OrderGateway gw(&new_order, &executor_cancel_order, &requests_new_order,
&requests_cancel_order, &client_responses);
gw.start();
while (gw.GetDownTimeInS() < 7) {
logd("Waiting till no activity, been silent for {} seconds...",
gw.GetDownTimeInS());
using namespace std::literals::chrono_literals;
std::this_thread::sleep_for(3s);
}
Exchange::MEClientResponse response[50]; /
size_t count_new_order = client_responses.try_dequeue_bulk(response, 50);
for (int i = 0; i < count_new_order; i++) {
logd("{}", response[i].ToString());
}
return 0;
}
#include <aot/WS.h>
int main(int argc, char** argv) { hmac_sha256::Keys keys{argv[2], argv[3]}; hmac_sha256::Signer signer(keys); auto type = TypeExchange::TESTNET; fmtlog::setLogLevel(fmtlog::INF); using namespace binance; Exchange::EventLFQueue event_queue; Exchange::RequestNewLimitOrderLFQueue requests_new_order; Exchange::RequestCancelOrderLFQueue requests_cancel_order; Exchange::ClientResponseLFQueue client_responses; OHLCVILFQueue ohlcv_queue; OrderNewLimit new_order(&signer, type); CancelOrder executor_cancel_order(&signer, type); DiffDepthStream::ms100 interval; TickerInfo info{2, 5}; Symbol btcusdt("BTC", "USDT"); Ticker ticker(&btcusdt, info);
GeneratorBidAskService generator_bid_ask_service(
&event_queue, ticker, &interval, TypeExchange::TESTNET);
generator_bid_ask_service.Start();
Trading::OrderGateway gw(&new_order, &executor_cancel_order,
&requests_new_order, &requests_cancel_order,
&client_responses);
gw.start();
auto chart_interval = binance::m1();
binance::OHLCVI fetcher(&btcusdt, &chart_interval, TypeExchange::TESTNET);
KLineService kline_service(&fetcher, &ohlcv_queue);
kline_service.start();
// init python predictor
const auto python_path = argv[1];
std::string path_where_models =
"/home/linoxoidunix/Programming/cplusplus/cryptobot";//init path where exist folder models, that generated from aot/python/prepare_model_for_bot.py
base_strategy::Strategy predictor(python_path, path_where_models,
"strategy.py", "Predictor", "predict");
Trading::TradeEngine trade_engine_service(
&event_queue, &requests_new_order, &requests_cancel_order,
&client_responses, &ohlcv_queue, ticker, &predictor);
trade_engine_service.Start();
while (trade_engine_service.GetDownTimeInS() < 120) {
logd("Waiting till no activity, been silent for {} seconds...",
trade_engine_service.GetDownTimeInS());
using namespace std::literals::chrono_literals;
std::this_thread::sleep_for(30s);
}
}
![Alt Text](/doc/ForREADME/check_full_work.gif)
# TODO
1. for order manager need consider riskmanager
# Acknowledgment
* https://martin.ankerl.com/2022/08/27/hashmap-bench-01/