Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66ad51280f | ||
|
|
029edd8a86 | ||
|
|
dfdcbab2a0 | ||
|
|
6d7c0702f0 | ||
|
|
86eaddea93 |
No files matched your search
@@ -39,6 +39,7 @@ SPARKD__CONFIG_DIR=src/server/sparkd/configurations/dev
|
|||||||
# Defaults to a volume named "sparkd_<config_port>" (e.g., sparkd_8000).
|
# Defaults to a volume named "sparkd_<config_port>" (e.g., sparkd_8000).
|
||||||
# SPARKD__DATA_DIR=/home/bts/sparkdata/data
|
# SPARKD__DATA_DIR=/home/bts/sparkdata/data
|
||||||
SPARKD__SOURCE_DIR=install/sparkd-release-gcc
|
SPARKD__SOURCE_DIR=install/sparkd-release-gcc
|
||||||
|
SPARKD__RUNTIME_CONF_DIR=/home/ubuntu/8000/sparkdata/conf/
|
||||||
SPARKD__CONFIG_PORT=8000
|
SPARKD__CONFIG_PORT=8000
|
||||||
SPARKD__QUICKBUS_PORT=8001
|
SPARKD__QUICKBUS_PORT=8001
|
||||||
SPARKD__SIM_FIX_PORT=8002
|
SPARKD__SIM_FIX_PORT=8002
|
||||||
|
|||||||
Vendored
+1
-1
@@ -326,4 +326,4 @@
|
|||||||
"description": "Test to run",
|
"description": "Test to run",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -33,6 +33,43 @@ services:
|
|||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: "${SPARKD__MEMORY:-4gb}"
|
memory: "${SPARKD__MEMORY:-4gb}"
|
||||||
|
sparkd-symbols:
|
||||||
|
volumes:
|
||||||
|
- ${SPARKD__DATA_DIR:-sparkd_data}:/home/bts/sparkdata/data
|
||||||
|
- ${SPARKD__RUNTIME_CONF_DIR:-sparkd_conf}:/home/bts/sparkdata/conf
|
||||||
|
build:
|
||||||
|
dockerfile: src/server/sparkd/Dockerfile
|
||||||
|
args:
|
||||||
|
- IMAGE=${SPARKD__IMAGE}
|
||||||
|
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
|
||||||
|
- CONFIG_DIR=${SPARKD__CONFIG_DIR}
|
||||||
|
shm_size: "${SPARKD__SHM_SIZE:-512mb}"
|
||||||
|
command: >
|
||||||
|
sh -c "
|
||||||
|
echo bts | sudo -S chown -R bts:bts /home/bts/sparkdata/data
|
||||||
|
if [ -e "/home/bts/sparkdata/data/logging.sparkd/log" ]; then
|
||||||
|
mv "/home/bts/sparkdata/data/logging.sparkd/log" "/home/bts/sparkdata/data/logging.sparkd/log_$(date '+%Y%m%d-%H%M')"
|
||||||
|
fi
|
||||||
|
ls -alh /home/bts/sparkdata/conf/
|
||||||
|
cat /home/bts/sparkdata/conf/.env.local
|
||||||
|
if [ -e "/home/bts/sparkdata/conf/.env.local" ]; then
|
||||||
|
echo 'Sourcing /home/bts/sparkdata/conf/.env.local'
|
||||||
|
set -a
|
||||||
|
. /home/bts/sparkdata/conf/.env.local
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
./sparkd run"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
- ${SPARKD__CONFIG_DIR}/.env
|
||||||
|
ports:
|
||||||
|
- "${SPARKD__CONFIG_PORT}:${SPARKD__CONFIG_PORT}"
|
||||||
|
- "${SPARKD__QUICKBUS_PORT}:${SPARKD__QUICKBUS_PORT}"
|
||||||
|
- "${SPARKD__SIM_FIX_PORT}:${SPARKD__SIM_FIX_PORT}"
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "${SPARKD__MEMORY:-4gb}"
|
||||||
|
|
||||||
sparkd-tail:
|
sparkd-tail:
|
||||||
image: bluetradingsystems/linux_dotnet7
|
image: bluetradingsystems/linux_dotnet7
|
||||||
|
|||||||
@@ -55,24 +55,24 @@ OkxExecutionGateway::~OkxExecutionGateway() {}
|
|||||||
enum class OkxExecutionState { OFF, STARTED, LOGGED_IN, SUBSCIRBED };
|
enum class OkxExecutionState { OFF, STARTED, LOGGED_IN, SUBSCIRBED };
|
||||||
void OkxExecutionGateway::send_msgs(
|
void OkxExecutionGateway::send_msgs(
|
||||||
std::vector<OrderMsg> const &msgs, trace::CorID) {
|
std::vector<OrderMsg> const &msgs, trace::CorID) {
|
||||||
LOG(OrderMan,Info,"ExecutionGateway::send_msgs" );
|
LOG(OrderMan, Info, "ExecutionGateway::send_msgs");
|
||||||
for (const auto &msg : msgs) {
|
for (const auto &msg : msgs) {
|
||||||
std::visit(
|
std::visit(
|
||||||
[this](auto &&order) {
|
[this](auto &&order) {
|
||||||
using T = std::decay_t<decltype(order)>;
|
using T = std::decay_t<decltype(order)>;
|
||||||
if constexpr (std::is_same_v<T, CreateOrderMsg>) {
|
if constexpr (std::is_same_v<T, CreateOrderMsg>) {
|
||||||
LOG(OrderMan,Warn,"ExecutionGateway::CreateOrderMsg" );
|
LOG(OrderMan, Warn, "ExecutionGateway::CreateOrderMsg");
|
||||||
launch_new_order(order);
|
launch_new_order(order);
|
||||||
|
|
||||||
} else if constexpr (std::is_same_v<T, CancelOrderMsg>) {
|
} else if constexpr (std::is_same_v<T, CancelOrderMsg>) {
|
||||||
LOG(OrderMan,Warn,"ExecutionGateway::CancelOrderMsg" );
|
LOG(OrderMan, Warn, "ExecutionGateway::CancelOrderMsg");
|
||||||
cancel_order(order);
|
cancel_order(order);
|
||||||
} else if constexpr (std::is_same_v<T, CancelReplaceOrderMsg>) {
|
} else if constexpr (std::is_same_v<T, CancelReplaceOrderMsg>) {
|
||||||
LOG(OrderMan,Warn,"ExecutionGateway::CancelReplaceOrderMsg" );
|
LOG(OrderMan, Warn, "ExecutionGateway::CancelReplaceOrderMsg");
|
||||||
modify_order(order);
|
modify_order(order);
|
||||||
} else if constexpr (std::is_same_v<T, RFQMsg>) {
|
} else if constexpr (std::is_same_v<T, RFQMsg>) {
|
||||||
// Handle RFQMsg if necessary
|
// Handle RFQMsg if necessary
|
||||||
// adapter->handle_rfq(order); // Example placeholder
|
// adapter->handle_rfq(order); // Example placeholder
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
msg);
|
msg);
|
||||||
@@ -94,7 +94,8 @@ struct OkxExecutionGateway::PImpl {
|
|||||||
const std::string passphrase = config::get<config::OkxExeCfg>().passphrase();
|
const std::string passphrase = config::get<config::OkxExeCfg>().passphrase();
|
||||||
const std::string url =
|
const std::string url =
|
||||||
config::get<config::OkxExeCfg>().ws_url() + "/ws/v5/private";
|
config::get<config::OkxExeCfg>().ws_url() + "/ws/v5/private";
|
||||||
const bool simulated_trading = config::get<config::OkxExeCfg>().simulated_trading();
|
const bool simulated_trading =
|
||||||
|
config::get<config::OkxExeCfg>().simulated_trading();
|
||||||
const std::string tdmode = config::get<config::OkxExeCfg>().tdmode();
|
const std::string tdmode = config::get<config::OkxExeCfg>().tdmode();
|
||||||
const core::TimeSpan connect_timeout = core::TimeSpan::from_seconds(0);
|
const core::TimeSpan connect_timeout = core::TimeSpan::from_seconds(0);
|
||||||
const core::TimeSpan pong_timeout = core::TimeSpan::from_seconds(
|
const core::TimeSpan pong_timeout = core::TimeSpan::from_seconds(
|
||||||
@@ -124,7 +125,8 @@ struct OkxExecutionGateway::PImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dummy(std::shared_ptr<const ExecutionReport>, const trace::CorID &) {
|
static void dummy(
|
||||||
|
std::shared_ptr<const ExecutionReport>, const trace::CorID &) {
|
||||||
LOG(OrderMan, Error, "OnixFixListener::Dummy fired");
|
LOG(OrderMan, Error, "OnixFixListener::Dummy fired");
|
||||||
}
|
}
|
||||||
void setCallback(const OnExeReport &callback) {
|
void setCallback(const OnExeReport &callback) {
|
||||||
@@ -185,7 +187,7 @@ struct OkxExecutionGateway::PImpl {
|
|||||||
Price(std::stod(order.at("lastPx").get<std::string>()));
|
Price(std::stod(order.at("lastPx").get<std::string>()));
|
||||||
report.avg_price = Price(std::stod(order.at("avgPx").get<std::string>()));
|
report.avg_price = Price(std::stod(order.at("avgPx").get<std::string>()));
|
||||||
report.last_shares = Quantity::create_new(
|
report.last_shares = Quantity::create_new(
|
||||||
std::stod(order.at("fillSz").get<std::string>()));
|
std::stod(order.at("fillSz").get<std::string>()));
|
||||||
|
|
||||||
//there are algos, like spreader
|
//there are algos, like spreader
|
||||||
// that are super sensitive to messages and cancel themselves. To avoid
|
// that are super sensitive to messages and cancel themselves. To avoid
|
||||||
@@ -195,29 +197,28 @@ struct OkxExecutionGateway::PImpl {
|
|||||||
// Alternatively we can change the spreader to not do that. Right not this
|
// Alternatively we can change the spreader to not do that. Right not this
|
||||||
// seems to be the better choice
|
// seems to be the better choice
|
||||||
if (!(order.at("code").get<std::string>() == "0")) {
|
if (!(order.at("code").get<std::string>() == "0")) {
|
||||||
report.msg = order.at("msg").get<std::string>();
|
report.msg = order.at("msg").get<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//report can be new order, cancel order, order filled, replace order, and partial fill or errror
|
||||||
|
//new order, cancelled and order filled dont need special handling, error gets handled above
|
||||||
|
//for other three we will look for fields that are only specific to the respectives types
|
||||||
|
// if (!(order.at("cancelSource").get<std::string>() == "")) {
|
||||||
|
|
||||||
//report can be new order, cancel order, order filled, replace order, and partial fill or errror
|
// }
|
||||||
//new order, cancelled and order filled dont need special handling, error gets handled above
|
|
||||||
//for other three we will look for fields that are only specific to the respectives types
|
|
||||||
// if (!(order.at("cancelSource").get<std::string>() == "")) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
if (!(order.at("amendSource").get<std::string>() == "")) {
|
if (!(order.at("amendSource").get<std::string>() == "")) {
|
||||||
if((order.at("amendResult").get<std::string>() == "0"))
|
if ((order.at("amendResult").get<std::string>() == "0"))
|
||||||
report.exec_type = api::orderman::ExecType::EXEC_TYPE_REPLACED;
|
report.exec_type = api::orderman::ExecType::EXEC_TYPE_REPLACED;
|
||||||
else{
|
else {
|
||||||
LOG(OrderMan, Warn, "order:{} replace rejected", report.order_key);
|
LOG(OrderMan, Warn, "order:{} replace rejected", report.order_key);
|
||||||
report.msg = order.at("msg").get<std::string>();
|
report.msg = order.at("msg").get<std::string>();
|
||||||
}
|
}
|
||||||
} else if (!(order.at("fillSz").get<std::string>() == "0")) {
|
} else if (!(order.at("fillSz").get<std::string>() == "0")) {
|
||||||
utils::Uuid guid;
|
utils::Uuid guid;
|
||||||
std::string fill_id = guid.to_text_string();
|
std::string fill_id = guid.to_text_string();
|
||||||
to_array(fill_id, &report.exchange_fill_id.value());
|
to_array(fill_id, &report.exchange_fill_id.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
// report.transact_time = ExchangeTimeStampVar(std::stoll(order.at("uTime").get<std::string>()));
|
// report.transact_time = ExchangeTimeStampVar(std::stoll(order.at("uTime").get<std::string>()));
|
||||||
ExchangeTimeStamp64 now = ExchangeTimeStamp64(datetime::unix_nano_now());
|
ExchangeTimeStamp64 now = ExchangeTimeStamp64(datetime::unix_nano_now());
|
||||||
report.transact_time = now;
|
report.transact_time = now;
|
||||||
@@ -228,14 +229,14 @@ struct OkxExecutionGateway::PImpl {
|
|||||||
bts_assert_msgf(
|
bts_assert_msgf(
|
||||||
false, "Websocket stream client disconnected. {}", ec.message());
|
false, "Websocket stream client disconnected. {}", ec.message());
|
||||||
}
|
}
|
||||||
// fills execution report form basic_json and writes it to
|
// fills execution report form basic_json and writes it to
|
||||||
// buffered_exec_reps, which is picked up from the other thread
|
// buffered_exec_reps, which is picked up from the other thread
|
||||||
// and passed over to the order infrastructure
|
// and passed over to the order infrastructure
|
||||||
void _push_execution_report(const nlohmann::basic_json<> &order) {
|
void _push_execution_report(const nlohmann::basic_json<> &order) {
|
||||||
ExecutionReport er;
|
ExecutionReport er;
|
||||||
get_exe_report(order, er);
|
get_exe_report(order, er);
|
||||||
buffered_exec_reps.push(std::make_shared<ExecutionReport>(std::move(er)));
|
buffered_exec_reps.push(std::make_shared<ExecutionReport>(std::move(er)));
|
||||||
}
|
}
|
||||||
void on_message(const std::string &msg_str) {
|
void on_message(const std::string &msg_str) {
|
||||||
LOG(OrderMan, Info, "okxlistener::on_message. {}", msg_str);
|
LOG(OrderMan, Info, "okxlistener::on_message. {}", msg_str);
|
||||||
nlohmann::json msg;
|
nlohmann::json msg;
|
||||||
@@ -279,21 +280,22 @@ struct OkxExecutionGateway::PImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto &data = msg.at("data");
|
const auto &data = msg.at("data");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (const nlohmann::basic_json<> &order : data) {
|
for (const nlohmann::basic_json<> &order : data) {
|
||||||
int orderkey = 0;
|
int orderkey = 0;
|
||||||
try {
|
try {
|
||||||
int temp = std::stoi(order.at("clOrdId").get<std::string>());
|
int temp = std::stoi(order.at("clOrdId").get<std::string>());
|
||||||
orderkey = temp;
|
orderkey = temp;
|
||||||
}catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
if(orderkey ==0){
|
if (orderkey == 0) {
|
||||||
LOG(OrderMan, Error, "okxlistener::on_message GOT ER FOR ORDER NOT ENTERED FROM SYSTEM. {}", msg_str);
|
LOG(OrderMan, Error,
|
||||||
|
"okxlistener::on_message GOT ER FOR ORDER NOT ENTERED FROM "
|
||||||
|
"SYSTEM. {}",
|
||||||
|
msg_str);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_push_execution_report(order);
|
_push_execution_report(order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void start() {
|
void start() {
|
||||||
@@ -456,8 +458,8 @@ struct OkxExecutionGateway::PImpl {
|
|||||||
};
|
};
|
||||||
void OkxExecutionGateway::start() { me_->start(); }
|
void OkxExecutionGateway::start() { me_->start(); }
|
||||||
OnGwStatusChange &OkxExecutionGateway::on_gw_status_change() {
|
OnGwStatusChange &OkxExecutionGateway::on_gw_status_change() {
|
||||||
return me_->on_gw_status_change;
|
return me_->on_gw_status_change;
|
||||||
}
|
}
|
||||||
void OkxExecutionGateway::modify_order(
|
void OkxExecutionGateway::modify_order(
|
||||||
const CancelReplaceOrderMsg &msg) { //confirm will have everything
|
const CancelReplaceOrderMsg &msg) { //confirm will have everything
|
||||||
try {
|
try {
|
||||||
@@ -474,7 +476,7 @@ void OkxExecutionGateway::modify_order(
|
|||||||
std::to_string(msg.create_fields.quantity.full_value()));
|
std::to_string(msg.create_fields.quantity.full_value()));
|
||||||
auto headers = OkxUtils::createHeaders(
|
auto headers = OkxUtils::createHeaders(
|
||||||
me_->api_key, me_->passphrase, me_->secret_key, "POST", REQUEST_PATH,
|
me_->api_key, me_->passphrase, me_->secret_key, "POST", REQUEST_PATH,
|
||||||
me_->simulated_trading,body);
|
me_->simulated_trading, body);
|
||||||
// Generate and log the curl command
|
// Generate and log the curl command
|
||||||
std::string curlCommand = OkxUtils::generateCurlCommand(
|
std::string curlCommand = OkxUtils::generateCurlCommand(
|
||||||
config::get<config::OkxExeCfg>().rest_url() + REQUEST_PATH, headers,
|
config::get<config::OkxExeCfg>().rest_url() + REQUEST_PATH, headers,
|
||||||
@@ -488,7 +490,8 @@ void OkxExecutionGateway::modify_order(
|
|||||||
if (suc) {
|
if (suc) {
|
||||||
LOG(md, Info, "Http get succeeded {}", res.body);
|
LOG(md, Info, "Http get succeeded {}", res.body);
|
||||||
} else {
|
} else {
|
||||||
LOG(md, Info, "Http get failed code: {}, errors: {}, body: {}", res.code, res.errors, res.body);
|
LOG(md, Info, "Http get failed code: {}, errors: {}, body: {}",
|
||||||
|
res.code, res.errors, res.body);
|
||||||
}
|
}
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
const std::string err = ex.what();
|
const std::string err = ex.what();
|
||||||
@@ -496,17 +499,17 @@ void OkxExecutionGateway::modify_order(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void OkxExecutionGateway::dispatch_incoming_fix_messages() {
|
void OkxExecutionGateway::dispatch_incoming_fix_messages() {
|
||||||
if (me_->buffered_exec_reps.empty()) {
|
if (me_->buffered_exec_reps.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::shared_ptr<ExecutionReport> er;
|
std::shared_ptr<ExecutionReport> er;
|
||||||
while (me_->buffered_exec_reps.try_pop(er)) {
|
while (me_->buffered_exec_reps.try_pop(er)) {
|
||||||
trace::CorID cid = {};
|
trace::CorID cid = {};
|
||||||
LOG(OrderMan, Info,
|
LOG(OrderMan, Info,
|
||||||
"OkxExecutionGateway::dispatch_incoming_fix_messages er: {} ",
|
"OkxExecutionGateway::dispatch_incoming_fix_messages er: {} ",
|
||||||
er->to_string());
|
er->to_string());
|
||||||
me_->cb(std::move(er), cid);
|
me_->cb(std::move(er), cid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OnExeReport &OkxExecutionGateway::on_exe_report() { return me_->cb; }
|
OnExeReport &OkxExecutionGateway::on_exe_report() { return me_->cb; }
|
||||||
OnCancelReject &OkxExecutionGateway::on_cancel_reject() {
|
OnCancelReject &OkxExecutionGateway::on_cancel_reject() {
|
||||||
@@ -538,12 +541,12 @@ void OkxExecutionGateway::launch_new_order(const CreateOrderMsg &msg) {
|
|||||||
const std::string ord_type =
|
const std::string ord_type =
|
||||||
FIX::string_toLower(ord_full_name.substr(pos + suffix.size()));
|
FIX::string_toLower(ord_full_name.substr(pos + suffix.size()));
|
||||||
const std::string body = fmt::format(
|
const std::string body = fmt::format(
|
||||||
body_template, msg.security->okx().security_desc(),me_->tdmode, side, ord_type,
|
body_template, msg.security->okx().security_desc(), me_->tdmode, side,
|
||||||
price, quantity, msg.key);
|
ord_type, price, quantity, msg.key);
|
||||||
http::HttpResponse res;
|
http::HttpResponse res;
|
||||||
auto headers = OkxUtils::createHeaders(
|
auto headers = OkxUtils::createHeaders(
|
||||||
me_->api_key, me_->passphrase, me_->secret_key, "POST", REQUEST_PATH,
|
me_->api_key, me_->passphrase, me_->secret_key, "POST", REQUEST_PATH,
|
||||||
me_->simulated_trading,body);
|
me_->simulated_trading, body);
|
||||||
// Generate and log the curl command
|
// Generate and log the curl command
|
||||||
std::string curlCommand = OkxUtils::generateCurlCommand(
|
std::string curlCommand = OkxUtils::generateCurlCommand(
|
||||||
config::get<config::OkxExeCfg>().rest_url() + REQUEST_PATH, headers,
|
config::get<config::OkxExeCfg>().rest_url() + REQUEST_PATH, headers,
|
||||||
@@ -556,30 +559,33 @@ void OkxExecutionGateway::launch_new_order(const CreateOrderMsg &msg) {
|
|||||||
const auto &[suc, top_msg] = OkxUtils::orderAccepted(res.body);
|
const auto &[suc, top_msg] = OkxUtils::orderAccepted(res.body);
|
||||||
|
|
||||||
if (suc) {
|
if (suc) {
|
||||||
LOG(md, Info, "Http get succeeded {}", res.body);
|
LOG(md, Info, "Http get succeeded {}", res.body);
|
||||||
// er.exec_type = api::orderman::ExecType::EXEC_TYPE_PENDING_NEW;
|
// er.exec_type = api::orderman::ExecType::EXEC_TYPE_PENDING_NEW;
|
||||||
// er.order_status = api::orderman::NATIVE_ORDER_STATUS_PENDING_NEW;
|
// er.order_status = api::orderman::NATIVE_ORDER_STATUS_PENDING_NEW;
|
||||||
} else {
|
} else {
|
||||||
LOG(md, Info, "Http get failed code: {}, errors: {}, body: {}", res.code, res.errors, res.body);
|
LOG(md, Info, "Http get failed code: {}, errors: {}, body: {}",
|
||||||
OkxUtils::populateCreateOrderFields(er, msg);
|
res.code, res.errors, res.body);
|
||||||
er.price = msg.price;
|
OkxUtils::populateCreateOrderFields(er, msg);
|
||||||
er.quantity = msg.quantity;
|
er.price = msg.price;
|
||||||
er.filled_quantity = 0;
|
er.quantity = msg.quantity;
|
||||||
er.last_shares = 0;
|
er.filled_quantity = 0;
|
||||||
er.leg_security = nullptr;
|
er.last_shares = 0;
|
||||||
er.avg_price = Price(0);
|
er.leg_security = nullptr;
|
||||||
ExchangeTimeStamp64 now = ExchangeTimeStamp64(datetime::unix_nano_now());
|
er.avg_price = Price(0);
|
||||||
er.transact_time = now;
|
ExchangeTimeStamp64 now =
|
||||||
er.order_key = msg.key;
|
ExchangeTimeStamp64(datetime::unix_nano_now());
|
||||||
const auto &[id, ts, ex_msg] = OkxUtils::extractOrderInfo(res.body);
|
er.transact_time = now;
|
||||||
er.exchange_order_id = ExchangeOrderID{OkxUtils::stringToFixedArray(id)};
|
er.order_key = msg.key;
|
||||||
er.exec_type = api::orderman::ExecType::EXEC_TYPE_REJECTED;
|
const auto &[id, ts, ex_msg] = OkxUtils::extractOrderInfo(res.body);
|
||||||
er.order_status = api::orderman::NATIVE_ORDER_STATUS_REJECTED;
|
er.exchange_order_id =
|
||||||
er.msg = ex_msg + " " + top_msg;
|
ExchangeOrderID{OkxUtils::stringToFixedArray(id)};
|
||||||
me_->buffered_exec_reps.push(
|
er.exec_type = api::orderman::ExecType::EXEC_TYPE_REJECTED;
|
||||||
std::make_shared<ExecutionReport>(std::move(er)));
|
er.order_status = api::orderman::NATIVE_ORDER_STATUS_REJECTED;
|
||||||
|
er.msg = ex_msg + " " + top_msg;
|
||||||
|
me_->buffered_exec_reps.push(
|
||||||
|
std::make_shared<ExecutionReport>(std::move(er)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Shut down all reactors if they exist.
|
// Shut down all reactors if they exist.
|
||||||
catch (const std::exception &ex) {
|
catch (const std::exception &ex) {
|
||||||
const std::string err = ex.what();
|
const std::string err = ex.what();
|
||||||
@@ -605,7 +611,7 @@ void OkxExecutionGateway::cancel_order(const CancelOrderMsg &msg) {
|
|||||||
body_template, msg.security->okx().security_desc(), msg.key);
|
body_template, msg.security->okx().security_desc(), msg.key);
|
||||||
auto headers = OkxUtils::createHeaders(
|
auto headers = OkxUtils::createHeaders(
|
||||||
me_->api_key, me_->passphrase, me_->secret_key, "POST", REQUEST_PATH,
|
me_->api_key, me_->passphrase, me_->secret_key, "POST", REQUEST_PATH,
|
||||||
me_->simulated_trading,body);
|
me_->simulated_trading, body);
|
||||||
// Generate and log the curl command
|
// Generate and log the curl command
|
||||||
std::string curlCommand = OkxUtils::generateCurlCommand(
|
std::string curlCommand = OkxUtils::generateCurlCommand(
|
||||||
config::get<config::OkxExeCfg>().rest_url() + REQUEST_PATH, headers,
|
config::get<config::OkxExeCfg>().rest_url() + REQUEST_PATH, headers,
|
||||||
@@ -630,7 +636,8 @@ void OkxExecutionGateway::cancel_order(const CancelOrderMsg &msg) {
|
|||||||
// er.exec_type = api::orderman::ExecType::EXEC_TYPE_PENDING_CANCEL;
|
// er.exec_type = api::orderman::ExecType::EXEC_TYPE_PENDING_CANCEL;
|
||||||
// er.order_status = api::orderman::NATIVE_ORDER_STATUS_PENDING_CANCEL;
|
// er.order_status = api::orderman::NATIVE_ORDER_STATUS_PENDING_CANCEL;
|
||||||
} else {
|
} else {
|
||||||
LOG(md, Info, "Http get failed code: {}, errors: {}, body: {}", res.code, res.errors, res.body);
|
LOG(md, Info, "Http get failed code: {}, errors: {}, body: {}",
|
||||||
|
res.code, res.errors, res.body);
|
||||||
// er.exec_type = api::orderman::ExecType::EXEC_TYPE_REJECTED;
|
// er.exec_type = api::orderman::ExecType::EXEC_TYPE_REJECTED;
|
||||||
// er.order_status = api::orderman::NATIVE_ORDER_STATUS_REJECTED;
|
// er.order_status = api::orderman::NATIVE_ORDER_STATUS_REJECTED;
|
||||||
// er.msg = ex_msg + " " + top_msg;
|
// er.msg = ex_msg + " " + top_msg;
|
||||||
@@ -643,8 +650,7 @@ void OkxExecutionGateway::cancel_order(const CancelOrderMsg &msg) {
|
|||||||
OkxUtils::handleOkException("Cacnel order", err);
|
OkxUtils::handleOkException("Cacnel order", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace bts::orderman::okxexe
|
} // namespace bts::orderman
|
||||||
|
|
||||||
|
|
||||||
// ExecutionReport OkxExecutionAdapter::fire_dummy_modify_order_report(CancelReplaceOrderMsg msg) {
|
// ExecutionReport OkxExecutionAdapter::fire_dummy_modify_order_report(CancelReplaceOrderMsg msg) {
|
||||||
// ExecutionReport *er_p = me_->create_exe_ptr();
|
// ExecutionReport *er_p = me_->create_exe_ptr();
|
||||||
|
|||||||
@@ -156,23 +156,15 @@ void SpreaderOrder::_on_time(const bts::mercury::TimerEvent &t_event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SpreaderOrder::_on_book_update(const BookUpdateEvent &book_event) {
|
void SpreaderOrder::_on_book_update(const BookUpdateEvent &book_event) {
|
||||||
if (book_event.key() == _bookkeeping_data().spread_sec_key()) {
|
|
||||||
// TODO, update spread book
|
|
||||||
_bookkeeping_data().spread_book = book_event.book;
|
|
||||||
LOG(OrderMan, Info,
|
|
||||||
"SpreaderOrder::_on_book_update spread book udpate, skey: {} "
|
|
||||||
"bid: {}/{} a: {}/{}",
|
|
||||||
book_event.key(), book_event.book.bid().at(0).price(),
|
|
||||||
book_event.book.bid().at(0).size(),
|
|
||||||
book_event.book.ask().at(0).price(),
|
|
||||||
book_event.book.ask().at(0).size());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG(OrderMan, Diag,
|
LOG(OrderMan, Diag,
|
||||||
"SpreaderOrder::_on_book_update skey: {} bid: {}/{} a: {}/{}",
|
"SpreaderOrder::_on_book_update skey: {} bid: {}/{} a: {}/{}",
|
||||||
book_event.key(), book_event.book.bid().at(0).price(),
|
book_event.key(), book_event.book.bid().at(0).price(),
|
||||||
book_event.book.bid().at(0).size(), book_event.book.ask().at(0).price(),
|
book_event.book.bid().at(0).size(), book_event.book.ask().at(0).price(),
|
||||||
book_event.book.ask().at(0).size());
|
book_event.book.ask().at(0).size());
|
||||||
|
if (book_event.key() == _bookkeeping_data().spread_sec_key()) {
|
||||||
|
_bookkeeping_data().spread_book = book_event.book;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!_active)
|
if (!_active)
|
||||||
return;
|
return;
|
||||||
auto scoped = _order_services->log_scope(
|
auto scoped = _order_services->log_scope(
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class SpreaderOrder : public Order, public ISpreaderManager {
|
|||||||
public:
|
public:
|
||||||
// inherited function to return the OrderDefinition. asserts
|
// inherited function to return the OrderDefinition. asserts
|
||||||
// if on_init_new has not been called yet
|
// if on_init_new has not been called yet
|
||||||
const api::orderman::OrderDefinition &definition() const;
|
const api::orderman::OrderDefinition &definition() const override;
|
||||||
// this is the construction, can be slow
|
// this is the construction, can be slow
|
||||||
void on_init_new(
|
void on_init_new(
|
||||||
const bts::api::orderman::OrderDefinition &order_def,
|
const bts::api::orderman::OrderDefinition &order_def,
|
||||||
@@ -137,7 +137,11 @@ class SpreaderOrder : public Order, public ISpreaderManager {
|
|||||||
bts::orderman::OrderKey spreader_order_key() const override { return key(); }
|
bts::orderman::OrderKey spreader_order_key() const override { return key(); }
|
||||||
bts::TimeStamp current_time() const override { return _curr_timestamp; }
|
bts::TimeStamp current_time() const override { return _curr_timestamp; }
|
||||||
const bts::orderman::Book &get_book(size_t leg_index) const override {
|
const bts::orderman::Book &get_book(size_t leg_index) const override {
|
||||||
return _bookkeeping_data().get_leg_data(leg_index).book();
|
const SpreaderLegData &leg_data =
|
||||||
|
_bookkeeping_data().get_leg_data(leg_index);
|
||||||
|
const auto &rv = leg_data.book();
|
||||||
|
return rv;
|
||||||
|
//return _bookkeeping_data().get_leg_data(leg_index).book();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bts::orderman::Book &get_spread_book() const override {
|
const bts::orderman::Book &get_spread_book() const override {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "SpreaderFractionalQtyHelper.h"
|
#include "SpreaderFractionalQtyHelper.h"
|
||||||
|
#include "lib/api/services/OrderService.pb.h"
|
||||||
#include "lib/domain_model/SecurityKey.h"
|
#include "lib/domain_model/SecurityKey.h"
|
||||||
#include "lib/domain_model/common.h"
|
#include "lib/domain_model/common.h"
|
||||||
#include "lib/orderman/ChildOrder.h"
|
#include "lib/orderman/ChildOrder.h"
|
||||||
@@ -20,6 +21,10 @@ class IAlternateOrderGateway;
|
|||||||
// ii. create new quoter order
|
// ii. create new quoter order
|
||||||
class ISpreaderManager {
|
class ISpreaderManager {
|
||||||
public:
|
public:
|
||||||
|
// definition() was added when we expanded the spreader to add reverse hedging and sniper.
|
||||||
|
// that needed spreader sid etc, which is all in the definition. Also spreader_order_key() can
|
||||||
|
// retired
|
||||||
|
virtual const api::orderman::OrderDefinition &definition() const = 0;
|
||||||
virtual bts::orderman::OrderKey spreader_order_key() const = 0;
|
virtual bts::orderman::OrderKey spreader_order_key() const = 0;
|
||||||
virtual bts::TimeStamp current_time() const = 0;
|
virtual bts::TimeStamp current_time() const = 0;
|
||||||
// this is a reference to the original book structure
|
// this is a reference to the original book structure
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "LegPropertyData.h"
|
#include "LegPropertyData.h"
|
||||||
#include "ISpreaderManager.h"
|
#include "ISpreaderManager.h"
|
||||||
#include "SpreaderUtils.h"
|
#include "SpreaderUtils.h"
|
||||||
|
#include "lib/sparkproto/SparkProtos.pb.h"
|
||||||
|
#include "lib/utils/bts_assert.h"
|
||||||
|
|
||||||
namespace bts {
|
namespace bts {
|
||||||
namespace orderman {
|
namespace orderman {
|
||||||
@@ -10,11 +12,35 @@ LegPropertyData::LegPropertyData(
|
|||||||
const bts::api::ContractLeg &leg_contract,
|
const bts::api::ContractLeg &leg_contract,
|
||||||
const bts::spark::LegSpreaderParams &leg_params,
|
const bts::spark::LegSpreaderParams &leg_params,
|
||||||
api::Side trading_side,
|
api::Side trading_side,
|
||||||
|
bts::spark::ExecutionStrategy::SpreaderType spreader_quoting_type,
|
||||||
bts::api::SyntheticContract::PriceCalc price_calc,
|
bts::api::SyntheticContract::PriceCalc price_calc,
|
||||||
double qty_tick_size)
|
double qty_tick_size)
|
||||||
: _leg_index(leg_index), _leg_contract(leg_contract),
|
: _leg_index(leg_index), _leg_contract(leg_contract),
|
||||||
_leg_params(leg_params), _trading_side(trading_side),
|
_leg_params(leg_params), _trading_side(trading_side),
|
||||||
|
|
||||||
_price_calc(price_calc), _qty_tick_size(qty_tick_size) {
|
_price_calc(price_calc), _qty_tick_size(qty_tick_size) {
|
||||||
|
switch (spreader_quoting_type) {
|
||||||
|
case bts::spark::ExecutionStrategy::SpreaderType::
|
||||||
|
ExecutionStrategy_SpreaderType_REQUOTE: {
|
||||||
|
_is_active_quoting = leg_params.has_quote_params();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bts::spark::ExecutionStrategy::SpreaderType::
|
||||||
|
ExecutionStrategy_SpreaderType_REVERSE_HEDGE: {
|
||||||
|
_is_active_quoting = leg_params.has_reverse_hedge_quote_params();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case bts::spark::ExecutionStrategy::SpreaderType::
|
||||||
|
ExecutionStrategy_SpreaderType_SNIPER: {
|
||||||
|
_is_active_quoting = leg_params.has_sniper_quote_params();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
bts_assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG(OrderMan, Info,
|
LOG(OrderMan, Info,
|
||||||
"LegPropertyData.cons leg_idx: "
|
"LegPropertyData.cons leg_idx: "
|
||||||
"{} sec_key: {} side: {}",
|
"{} sec_key: {} side: {}",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class LegPropertyData {
|
|||||||
const api::Side _trading_side;
|
const api::Side _trading_side;
|
||||||
const bts::api::SyntheticContract::PriceCalc _price_calc;
|
const bts::api::SyntheticContract::PriceCalc _price_calc;
|
||||||
const double _qty_tick_size = 1.0;
|
const double _qty_tick_size = 1.0;
|
||||||
|
bool _is_active_quoting;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LegPropertyData(
|
LegPropertyData(
|
||||||
@@ -26,6 +27,9 @@ class LegPropertyData {
|
|||||||
const bts::api::ContractLeg &leg_contract,
|
const bts::api::ContractLeg &leg_contract,
|
||||||
const bts::spark::LegSpreaderParams &leg_params,
|
const bts::spark::LegSpreaderParams &leg_params,
|
||||||
api::Side trading_side,
|
api::Side trading_side,
|
||||||
|
bts::spark::ExecutionStrategy::SpreaderType spreader_quoting_type =
|
||||||
|
bts::spark::ExecutionStrategy::SpreaderType::
|
||||||
|
ExecutionStrategy_SpreaderType_REQUOTE,
|
||||||
bts::api::SyntheticContract::PriceCalc price_calc =
|
bts::api::SyntheticContract::PriceCalc price_calc =
|
||||||
bts::api::SyntheticContract::PRICECALC_STANDARD,
|
bts::api::SyntheticContract::PRICECALC_STANDARD,
|
||||||
double qty_tick_size = 1.0);
|
double qty_tick_size = 1.0);
|
||||||
@@ -52,11 +56,7 @@ class LegPropertyData {
|
|||||||
double qty_tick_size() const { return _qty_tick_size; }
|
double qty_tick_size() const { return _qty_tick_size; }
|
||||||
// TODO: is_quoting
|
// TODO: is_quoting
|
||||||
//bool is_active_quoting() const { return _leg_params.is_active_quoting(); }
|
//bool is_active_quoting() const { return _leg_params.is_active_quoting(); }
|
||||||
bool is_active_quoting() const {
|
bool is_active_quoting() const { return _is_active_quoting; }
|
||||||
return _leg_params.has_quote_params() ||
|
|
||||||
_leg_params.has_reverse_hedge_quote_params() ||
|
|
||||||
_leg_params.has_sniper_quote_params();
|
|
||||||
}
|
|
||||||
bool is_net_change() const {
|
bool is_net_change() const {
|
||||||
return _price_calc == bts::api::SyntheticContract::PRICECALC_NET_CHANGE;
|
return _price_calc == bts::api::SyntheticContract::PRICECALC_NET_CHANGE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,7 +273,9 @@ void SingleLegQuoter::_transform_to_WAITING_FOR_IOC() {
|
|||||||
_switch_state(&_waiting_for_ioc_worker);
|
_switch_state(&_waiting_for_ioc_worker);
|
||||||
}
|
}
|
||||||
void SingleLegQuoter::_transform_to_WAITING_FOR_FIRST_ACK_CANCELLED() {
|
void SingleLegQuoter::_transform_to_WAITING_FOR_FIRST_ACK_CANCELLED() {
|
||||||
bts_assert(_worker->state() == QuoterState::WAITING_FOR_FIRST_ACK);
|
bts_assert(
|
||||||
|
_worker->state() == QuoterState::WAITING_FOR_FIRST_ACK ||
|
||||||
|
_worker->state() == QuoterState::WAITING_FOR_IOC);
|
||||||
_switch_state(&_waiting_for_first_ack_cancelled_state_worker);
|
_switch_state(&_waiting_for_first_ack_cancelled_state_worker);
|
||||||
}
|
}
|
||||||
void SingleLegQuoter::_transform_to_WORKING() {
|
void SingleLegQuoter::_transform_to_WORKING() {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "lib/orderman/orders/spreader_orders/spreader/LegPropertyData.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/LegPropertyData.h"
|
||||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderFractionalQtyHelper.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderFractionalQtyHelper.h"
|
||||||
#include "lib/os/os.h"
|
#include "lib/os/os.h"
|
||||||
|
#include "lib/utils/PBUtils.h"
|
||||||
|
|
||||||
namespace bts {
|
namespace bts {
|
||||||
namespace orderman {
|
namespace orderman {
|
||||||
@@ -41,6 +42,11 @@ SpreaderBookkeepingData::SpreaderBookkeepingData(
|
|||||||
_leg_data.emplace_back(
|
_leg_data.emplace_back(
|
||||||
spreader_pao_services, spreader_order_key, _n_legs, spreader_manager,
|
spreader_pao_services, spreader_order_key, _n_legs, spreader_manager,
|
||||||
quoter_ord_defs[i], hedger_ord_defs[i], leg_property_data);
|
quoter_ord_defs[i], hedger_ord_defs[i], leg_property_data);
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"SpreaderBookkeepingData::cons leg_idx: {} quoter_ord_def: {} "
|
||||||
|
"hedger_ord_defs: {}",
|
||||||
|
i, utils::pb::to_string(quoter_ord_defs[i]),
|
||||||
|
utils::pb::to_string(hedger_ord_defs[i]));
|
||||||
bts_assert(
|
bts_assert(
|
||||||
_sec_key_to_index.find(leg_property_data.security_key()) ==
|
_sec_key_to_index.find(leg_property_data.security_key()) ==
|
||||||
_sec_key_to_index.end());
|
_sec_key_to_index.end());
|
||||||
|
|||||||
@@ -96,7 +96,10 @@ class SpreaderLegData {
|
|||||||
bts_assert(_is_quoting);
|
bts_assert(_is_quoting);
|
||||||
return *_quoter;
|
return *_quoter;
|
||||||
}
|
}
|
||||||
const bts::orderman::Book &book() const { return _book; }
|
const bts::orderman::Book &book() const {
|
||||||
|
// book
|
||||||
|
return _book;
|
||||||
|
}
|
||||||
Price settlement_price() const { return Price(_settlement_price.price()); }
|
Price settlement_price() const { return Price(_settlement_price.price()); }
|
||||||
bool settlement_populated() const {
|
bool settlement_populated() const {
|
||||||
return !os::is_nan(_settlement_price.price());
|
return !os::is_nan(_settlement_price.price());
|
||||||
@@ -162,6 +165,11 @@ class SpreaderLegData {
|
|||||||
book, _settlement_price, _leg_property_data.tick_size(),
|
book, _settlement_price, _leg_property_data.tick_size(),
|
||||||
_leg_property_data.md_type(),
|
_leg_property_data.md_type(),
|
||||||
bts::api::SyntheticContract::PRICECALC_STANDARD, _book);
|
bts::api::SyntheticContract::PRICECALC_STANDARD, _book);
|
||||||
|
// LOG(OrderMan, Info,
|
||||||
|
// "SpreaderLegData::update_book index: {} lpd_key: {} book: {} book "
|
||||||
|
// "key: {}",
|
||||||
|
// _leg_property_data.leg_index(), _leg_property_data.security_key(),
|
||||||
|
// book, book.security_key());
|
||||||
}
|
}
|
||||||
void update_settlement_price(md::IntPrice price) {
|
void update_settlement_price(md::IntPrice price) {
|
||||||
_settlement_price = price;
|
_settlement_price = price;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "SpreaderUtils.h"
|
#include "SpreaderUtils.h"
|
||||||
#include "lib/domain_model/common.h"
|
#include "lib/domain_model/common.h"
|
||||||
|
#include "lib/logging/logging.h"
|
||||||
#include "lib/md/PriceSize.h"
|
#include "lib/md/PriceSize.h"
|
||||||
#include "lib/orderman/events/BookUpdateEvent.h"
|
#include "lib/orderman/events/BookUpdateEvent.h"
|
||||||
#include "lib/orderman/orderman_utils/Book.h"
|
#include "lib/orderman/orderman_utils/Book.h"
|
||||||
@@ -7,6 +8,7 @@
|
|||||||
#include "lib/orderman/orders/spreader_orders/spreader/external_interfacing/SpreaderOrderBuilder.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/external_interfacing/SpreaderOrderBuilder.h"
|
||||||
#include "lib/orderman/orders/spreader_orders/spreader/external_interfacing/SpreaderPreActivationOrderServices.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/external_interfacing/SpreaderPreActivationOrderServices.h"
|
||||||
#include "lib/sparkproto/SparkProtos.pb.h"
|
#include "lib/sparkproto/SparkProtos.pb.h"
|
||||||
|
#include "lib/utils/PBUtils.h"
|
||||||
#include "lib/utils/bts_assert.h"
|
#include "lib/utils/bts_assert.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
namespace bts {
|
namespace bts {
|
||||||
@@ -67,6 +69,8 @@ bool SpreaderUtils::resolve_synthetic_spread(
|
|||||||
std::vector<bts::api::orderman::OrderDefinition> &out_quoter_defs,
|
std::vector<bts::api::orderman::OrderDefinition> &out_quoter_defs,
|
||||||
std::vector<bts::api::orderman::OrderDefinition> &out_hedger_defs,
|
std::vector<bts::api::orderman::OrderDefinition> &out_hedger_defs,
|
||||||
bool resolve_synthetic) {
|
bool resolve_synthetic) {
|
||||||
|
LOG(OrderMan, Info, "g/ {}",
|
||||||
|
utils::pb::to_string(order_def));
|
||||||
auto get_quote_time_enforce =
|
auto get_quote_time_enforce =
|
||||||
[&](const spark::ExecutionStrategy &exec_strat,
|
[&](const spark::ExecutionStrategy &exec_strat,
|
||||||
const spark::LegSpreaderParams &q_leg_params) {
|
const spark::LegSpreaderParams &q_leg_params) {
|
||||||
@@ -150,31 +154,32 @@ bool SpreaderUtils::resolve_synthetic_spread(
|
|||||||
->mutable_limit()
|
->mutable_limit()
|
||||||
->MergeFrom(api::orderman::LimitOrderDefinition());
|
->MergeFrom(api::orderman::LimitOrderDefinition());
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (leg_params.quote_params().has_quote_hidden())
|
|
||||||
// quoter_order_def.set_time_in_force(
|
|
||||||
// bts::api::orderman::TimeInForce::TIME_IN_FORCE_IOC);
|
|
||||||
// else
|
|
||||||
// quoter_order_def.set_time_in_force(
|
|
||||||
// order_def.time_in_force());
|
|
||||||
auto tif =
|
auto tif =
|
||||||
get_quote_time_enforce(execution_strategy, leg_params);
|
get_quote_time_enforce(execution_strategy, leg_params);
|
||||||
quoter_order_def.set_time_in_force(tif);
|
quoter_order_def.set_time_in_force(tif);
|
||||||
|
|
||||||
// hedger order def
|
// hedger order def
|
||||||
api::orderman::OrderDefinition hedger_order_def =
|
api::orderman::OrderDefinition hedger_order_def =
|
||||||
quoter_order_def;
|
quoter_order_def;
|
||||||
hedger_order_def.mutable_custom_def()
|
hedger_order_def.mutable_custom_def()
|
||||||
->mutable_limit()
|
->mutable_limit()
|
||||||
->MergeFrom(api::orderman::LimitOrderDefinition());
|
->MergeFrom(api::orderman::LimitOrderDefinition());
|
||||||
quoter_order_def.set_time_in_force(order_def.time_in_force());
|
//quoter_order_def.set_time_in_force(order_def.time_in_force());
|
||||||
hedger_order_def.set_sub_type(
|
hedger_order_def.set_sub_type(
|
||||||
bts::api::orderman::OrderSubType::
|
bts::api::orderman::OrderSubType::
|
||||||
ORDER_SUB_TYPE_HEDGING_LEG);
|
ORDER_SUB_TYPE_HEDGING_LEG);
|
||||||
LegPropertyData leg_property_data(
|
LegPropertyData leg_property_data(
|
||||||
leg_idx, leg, leg_params, leg_order_side,
|
leg_idx, leg, leg_params, leg_order_side,
|
||||||
|
order_def.custom_def()
|
||||||
|
.spreader()
|
||||||
|
.execution_strategy()
|
||||||
|
.spreader_type(),
|
||||||
sec.synthetic().price_calc());
|
sec.synthetic().price_calc());
|
||||||
out_resolved.push_back(leg_property_data);
|
out_resolved.push_back(leg_property_data);
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"SpreaderUtils::resolve_synthetic_spread idx: {} "
|
||||||
|
"quoter_order_def: {}",
|
||||||
|
out_quoter_defs.size(),
|
||||||
|
utils::pb::to_string(quoter_order_def));
|
||||||
out_quoter_defs.push_back(quoter_order_def);
|
out_quoter_defs.push_back(quoter_order_def);
|
||||||
out_hedger_defs.push_back(hedger_order_def);
|
out_hedger_defs.push_back(hedger_order_def);
|
||||||
leg_idx++;
|
leg_idx++;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "lib/domain_model/Security.pb.h"
|
#include "lib/domain_model/Security.pb.h"
|
||||||
#include "lib/domain_model/common.h"
|
#include "lib/domain_model/common.h"
|
||||||
#include "lib/jetfix/codec/FieldDefinitions.h"
|
#include "lib/jetfix/codec/FieldDefinitions.h"
|
||||||
|
#include "lib/logging/logging.h"
|
||||||
#include "lib/md/IntPrice.h"
|
#include "lib/md/IntPrice.h"
|
||||||
#include "lib/md/PriceSize.h"
|
#include "lib/md/PriceSize.h"
|
||||||
#include "lib/md/Shm/MDStructure.h"
|
#include "lib/md/Shm/MDStructure.h"
|
||||||
@@ -469,6 +470,12 @@ class SpreaderUtils {
|
|||||||
api::Side order_side,
|
api::Side order_side,
|
||||||
double tick_size,
|
double tick_size,
|
||||||
const Book &book) {
|
const Book &book) {
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"SpreaderUtils::book_through_order_price_nticks: order_price: {} "
|
||||||
|
"order_side: {} tick_size: {} -- bid: {}/{} ask: {}/{}",
|
||||||
|
order_price, static_cast<int>(order_side), tick_size,
|
||||||
|
book.bid().at(0).price(), book.bid().at(0).size(),
|
||||||
|
book.ask().at(0).price(), book.ask().at(0).size());
|
||||||
if (order_side == api::SIDE_BUY) {
|
if (order_side == api::SIDE_BUY) {
|
||||||
const md::PriceSize &top_ask = book.ask()[0];
|
const md::PriceSize &top_ask = book.ask()[0];
|
||||||
if (top_ask.size() == 0)
|
if (top_ask.size() == 0)
|
||||||
@@ -487,20 +494,35 @@ class SpreaderUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Price compute_order_price_through_book(
|
static Price compute_order_price_through_book(
|
||||||
const Book &book, api::Side order_side, int n_ticks) {
|
const Book &book, api::Side order_side, double tick_size, int n_ticks) {
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"SpreaderUtils::compute_order_price_through_book tick_size: {} "
|
||||||
|
"n_ticks: {}",
|
||||||
|
tick_size, n_ticks);
|
||||||
switch (order_side) {
|
switch (order_side) {
|
||||||
case api::Side::SIDE_BUY: {
|
case api::Side::SIDE_BUY: {
|
||||||
if (n_ticks >= 0) {
|
if (n_ticks >= 0) {
|
||||||
return Price(book.ask()[n_ticks].price());
|
double top_ask = book.ask()[0].price();
|
||||||
|
return Price(top_ask + tick_size * n_ticks);
|
||||||
|
//return Price(book.ask()[n_ticks].price());
|
||||||
} else {
|
} else {
|
||||||
return Price(book.bid()[std::abs(n_ticks)].price());
|
double top_bid = book.bid()[0].price();
|
||||||
|
return Price(top_bid - tick_size * n_ticks);
|
||||||
|
//return Price(book.bid()[std::abs(n_ticks)].price());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case api::Side::SIDE_SELL: {
|
case api::Side::SIDE_SELL: {
|
||||||
if (n_ticks >= 0) {
|
if (n_ticks >= 0) {
|
||||||
return Price(book.bid()[n_ticks].price());
|
double top_bid = book.bid()[0].price();
|
||||||
|
double rv = top_bid - tick_size * n_ticks;
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"SpreaderUtils::compute_order_price_through_book top_bid: {} "
|
||||||
|
"rv: {}",
|
||||||
|
top_bid, rv);
|
||||||
|
return Price(rv);
|
||||||
} else {
|
} else {
|
||||||
return Price(book.ask()[std::abs(n_ticks)].price());
|
double top_ask = book.ask()[0].price();
|
||||||
|
return Price(top_ask + tick_size * n_ticks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
+36
-15
@@ -1,7 +1,9 @@
|
|||||||
#include "lib/orderman/orders/spreader_orders/spreader/quoter/quoter_states/QuoterWaitingForSizeStateWorker.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/quoter/quoter_states/QuoterWaitingForSizeStateWorker.h"
|
||||||
#include "lib/domain_model/Security.pb.h"
|
#include "lib/domain_model/Security.pb.h"
|
||||||
#include "lib/domain_model/common.h"
|
#include "lib/domain_model/common.h"
|
||||||
|
#include "lib/logging/logging.h"
|
||||||
#include "lib/md/PriceSize.h"
|
#include "lib/md/PriceSize.h"
|
||||||
|
#include "lib/orderman/orderman_utils/Book.h"
|
||||||
#include "lib/orderman/orders/spreader_orders/spreader/ISpreaderManager.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/ISpreaderManager.h"
|
||||||
#include "lib/orderman/orders/spreader_orders/spreader/LegPropertyData.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/LegPropertyData.h"
|
||||||
#include "lib/orderman/orders/spreader_orders/spreader/SingleLegQuoter.h"
|
#include "lib/orderman/orders/spreader_orders/spreader/SingleLegQuoter.h"
|
||||||
@@ -63,13 +65,6 @@ void QuoterWaitingForSizeStateWorker::_longpath_analyze_and_act() {
|
|||||||
_quoter->_transform_to_END();
|
_quoter->_transform_to_END();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (_quoter->_this_leg_data.leg_params()
|
|
||||||
.has_reverse_hedge_quote_params()) {
|
|
||||||
}
|
|
||||||
if (_quoter->_this_leg_data.leg_params().has_sniper_quote_params()) {
|
|
||||||
|
|
||||||
} else if (_quoter->_this_leg_data.leg_params().has_quote_params()) {
|
|
||||||
}
|
|
||||||
auto spreader_q_type = _quoter->_spreader.get_spreader_quoting_type();
|
auto spreader_q_type = _quoter->_spreader.get_spreader_quoting_type();
|
||||||
switch (spreader_q_type) {
|
switch (spreader_q_type) {
|
||||||
case bts::spark::ExecutionStrategy::SpreaderType::
|
case bts::spark::ExecutionStrategy::SpreaderType::
|
||||||
@@ -81,7 +76,7 @@ void QuoterWaitingForSizeStateWorker::_longpath_analyze_and_act() {
|
|||||||
// only applicable for > 2 legged spreads
|
// only applicable for > 2 legged spreads
|
||||||
_quoter->_commit_drivers(out_price);
|
_quoter->_commit_drivers(out_price);
|
||||||
LOG(OrderMan, Info,
|
LOG(OrderMan, Info,
|
||||||
"QuoterWaitingForSizeStateWorker sending order "
|
"QuoterWaitingForSizeStateWorker (requoting) sending order "
|
||||||
"key:{} price:{} quantity:{}",
|
"key:{} price:{} quantity:{}",
|
||||||
_quoter->_key(), out_price, out_quantity);
|
_quoter->_key(), out_price, out_quantity);
|
||||||
// this is the only place where a quoter order is entered
|
// this is the only place where a quoter order is entered
|
||||||
@@ -92,18 +87,27 @@ void QuoterWaitingForSizeStateWorker::_longpath_analyze_and_act() {
|
|||||||
}
|
}
|
||||||
case bts::spark::ExecutionStrategy::SpreaderType::
|
case bts::spark::ExecutionStrategy::SpreaderType::
|
||||||
ExecutionStrategy_SpreaderType_REVERSE_HEDGE: {
|
ExecutionStrategy_SpreaderType_REVERSE_HEDGE: {
|
||||||
|
auto is_book_populated = [&](const Book &leg_book, api::Side bs) {
|
||||||
|
const auto &book_side = leg_book.side(bs);
|
||||||
|
return !os::is_nan(book_side.at(0).price());
|
||||||
|
};
|
||||||
const LegPropertyData &leg_data = _quoter->_this_leg_data;
|
const LegPropertyData &leg_data = _quoter->_this_leg_data;
|
||||||
bts_assert(_quoter->_this_leg_data.leg_params()
|
bts_assert(leg_data.leg_params().has_reverse_hedge_quote_params());
|
||||||
.has_reverse_hedge_quote_params());
|
|
||||||
const auto &rev_hedge_qparams =
|
const auto &rev_hedge_qparams =
|
||||||
_quoter->_this_leg_data.leg_params().reverse_hedge_quote_params();
|
leg_data.leg_params().reverse_hedge_quote_params();
|
||||||
int n_ticks = rev_hedge_qparams.n_ticks();
|
int n_ticks = rev_hedge_qparams.n_ticks();
|
||||||
const Book &spread_book = _quoter->_spreader.get_spread_book();
|
const Book &spread_book = _quoter->_spreader.get_spread_book();
|
||||||
auto leg_qside = leg_data.trading_side();
|
auto spread_side = _quoter->_spreader.definition().side();
|
||||||
int book_through_ticks =
|
int book_through_ticks =
|
||||||
SpreaderUtils::book_through_order_price_nticks(
|
SpreaderUtils::book_through_order_price_nticks(
|
||||||
_quoter->_price_quantity_state.out_price(), leg_qside,
|
_quoter->_price_quantity_state.target_spread_price(),
|
||||||
_quoter->_this_leg_data.tick_size(), spread_book);
|
// TODO (get it from the spread synth sec)
|
||||||
|
spread_side, 0.1, spread_book);
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"QuoterWaitingForSizeStateWorker::_longpath_analyze_and_act("
|
||||||
|
"reverse hedge) "
|
||||||
|
"n_ticks: {} book_through_ticks: {}",
|
||||||
|
n_ticks, book_through_ticks);
|
||||||
if (book_through_ticks >= n_ticks) {
|
if (book_through_ticks >= n_ticks) {
|
||||||
// qty, shoot full size? (can min it by max available on hedge leg)
|
// qty, shoot full size? (can min it by max available on hedge leg)
|
||||||
//auto spr_qty = _quoter->_price_quantity_state.out_quantity();
|
//auto spr_qty = _quoter->_price_quantity_state.out_quantity();
|
||||||
@@ -117,8 +121,25 @@ void QuoterWaitingForSizeStateWorker::_longpath_analyze_and_act() {
|
|||||||
// price: (nticks into the opposite market)
|
// price: (nticks into the opposite market)
|
||||||
const Book &leg_book =
|
const Book &leg_book =
|
||||||
_quoter->_spreader.get_book(leg_data.leg_index());
|
_quoter->_spreader.get_book(leg_data.leg_index());
|
||||||
|
bool leg_book_populated = is_book_populated(
|
||||||
|
leg_book, SpreaderUtils::invert_side(leg_data.trading_side()));
|
||||||
|
if (!leg_book_populated) {
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"QuoterWaitingForSizeStateWorker::_longpath_analyze_and_act "
|
||||||
|
"(RH), quoting leg book is empty, not firing order");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"QuoterWaitingForSizeStateWorker::_longpath_analyze_and_act "
|
||||||
|
"leg_book: {} k: {}",
|
||||||
|
leg_book, leg_book.security_key());
|
||||||
Price order_price = SpreaderUtils::compute_order_price_through_book(
|
Price order_price = SpreaderUtils::compute_order_price_through_book(
|
||||||
leg_book, leg_data.trading_side(), n_ticks);
|
leg_book, leg_data.trading_side(), leg_data.tick_size(),
|
||||||
|
n_ticks);
|
||||||
|
LOG(OrderMan, Info,
|
||||||
|
"QuoterWaitingForSizeStateWorker sending order in reverse "
|
||||||
|
"hedging mode key: {} price: {} quantity: {}",
|
||||||
|
_quoter->_key(), order_price, order_qty);
|
||||||
_quoter->_place_order(order_price, order_qty);
|
_quoter->_place_order(order_price, order_qty);
|
||||||
_quoter->_transform_to_WAITING_FOR_IOC();
|
_quoter->_transform_to_WAITING_FOR_IOC();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ class SpreaderManagerForTest : public ISpreaderManager {
|
|||||||
return _bookkeeping_data.spread_book.value();
|
return _bookkeeping_data.spread_book.value();
|
||||||
//return get_book(0);
|
//return get_book(0);
|
||||||
}
|
}
|
||||||
|
const api::orderman::OrderDefinition &definition() const override {
|
||||||
|
return _bookkeeping_data.order_def();
|
||||||
|
}
|
||||||
// the caller can keep a reference to the returned type forever. the
|
// the caller can keep a reference to the returned type forever. the
|
||||||
// data in the returned type is all const, so nothing will change
|
// data in the returned type is all const, so nothing will change
|
||||||
// beneath it
|
// beneath it
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ message LegSpreaderParams
|
|||||||
}
|
}
|
||||||
/// Legs can be quoted actively, or sent in reponse
|
/// Legs can be quoted actively, or sent in reponse
|
||||||
/// to fills
|
/// to fills
|
||||||
bool is_active_quoting = 20;
|
bool is_active_quoting = 20;
|
||||||
bool enable_hedging = 30;
|
bool enable_hedging = 30;
|
||||||
QuoteParams quote_params = 40;
|
QuoteParams quote_params = 40;
|
||||||
ReverseHedgeQuoteParams reverse_hedge_quote_params = 43;
|
ReverseHedgeQuoteParams reverse_hedge_quote_params = 43;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
SPARKD__CONFIG_DIR=src/server/sparkd/configurations/alphaworx_prod
|
SPARKD__CONFIG_DIR=src/server/sparkd/configurations/alphaworx_prod
|
||||||
SPARKD__SHM_SIZE=8gb
|
SPARKD__SHM_SIZE=8gb
|
||||||
SPARKD__MEMORY=8gb
|
SPARKD__MEMORY=8gb
|
||||||
|
SPARKD__RUNTIME_CONF_DIR=/home/ubuntu/8000/sparkdata/conf/
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
SPARKD__CONFIG_DIR=src/server/sparkd/configurations/alphaworx_zen_hk_live
|
||||||
|
SPARKD__SHM_SIZE=8gb
|
||||||
|
SPARKD__MEMORY=8gb
|
||||||
|
SPARKD__RUNTIME_CONF_DIR=/home/bts/8000/sparkdata/conf/
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
* Connects to Binance and Okx PRODUCTION sites for market data and execution
|
||||||
|
* Api keys NOT included
|
||||||
|
* Configured for Alphaworx
|
||||||
|
|
||||||
|
To retrieve api keys, run "python init_env.py". It should dump them to a file
|
||||||
|
called ".env.local".
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"api_key": "${BINANCE_API_KEY}",
|
||||||
|
"secret_key": "${BINANCE_SECRET_KEY}",
|
||||||
|
"account": "PROD",
|
||||||
|
"rest_endpoint": "https://api.binance.com",
|
||||||
|
"ws_endpoint": "wss://ws-api.binance.com:443/ws-api/v3",
|
||||||
|
"ws_stream_endpoint": "wss://stream.binance.com:9443",
|
||||||
|
"use_cross_margin_api": true
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"api_key": "${BINANCE_API_KEY}",
|
||||||
|
"secret_key": "${BINANCE_SECRET_KEY}",
|
||||||
|
"account": "PROD",
|
||||||
|
"rest_endpoint": "https://fapi.binance.com",
|
||||||
|
"ws_endpoint": "wss://ws-fapi.binance.com/ws-fapi/v1",
|
||||||
|
"ws_stream_endpoint": "wss://fstream.binance.com",
|
||||||
|
"use_cross_margin_api": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import botocore
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from boto3.session import Session
|
||||||
|
from botocore.exceptions import ClientError
|
||||||
|
from fileinput import FileInput
|
||||||
|
|
||||||
|
|
||||||
|
def update_env_file(path, env_vars: dict):
|
||||||
|
"""Update or add vars in a .env file in place."""
|
||||||
|
if not os.path.exists(path):
|
||||||
|
with open(path, "w") as file:
|
||||||
|
for k, v in env_vars.items():
|
||||||
|
file.write(f"{k}={v}\n")
|
||||||
|
return
|
||||||
|
|
||||||
|
with FileInput(path, inplace=True) as file:
|
||||||
|
for line in file:
|
||||||
|
if not line.startswith("#"):
|
||||||
|
stripped: str = line.lstrip()
|
||||||
|
key_len = stripped.find("=")
|
||||||
|
if key_len >= 0:
|
||||||
|
k = stripped[0:key_len]
|
||||||
|
if k in env_vars:
|
||||||
|
print(f"{k}={env_vars[k]}")
|
||||||
|
del env_vars[k]
|
||||||
|
continue
|
||||||
|
print(line, end="")
|
||||||
|
|
||||||
|
if len(env_vars) > 0:
|
||||||
|
with open(path, "a") as file:
|
||||||
|
for k, v in env_vars.items():
|
||||||
|
file.write(f"{k}={v}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def get_secret():
|
||||||
|
secret_name = "alphaworx-binance-api-keys"
|
||||||
|
region_name = "ap-northeast-1"
|
||||||
|
profile_name = "AdministratorAccess-849458505639"
|
||||||
|
session = Session(profile_name=profile_name)
|
||||||
|
client = session.client(
|
||||||
|
service_name="secretsmanager",
|
||||||
|
region_name=region_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_token_error(e: Exception):
|
||||||
|
print(f"""
|
||||||
|
Failed to get secret value. {e}
|
||||||
|
Verify you are logged in to aws, then try again.
|
||||||
|
|
||||||
|
aws sso login --profile {profile_name}
|
||||||
|
|
||||||
|
If this error persists, verify you have access to these api keys.
|
||||||
|
For more help or information, talk to John.
|
||||||
|
""")
|
||||||
|
|
||||||
|
try:
|
||||||
|
get_secret_value_response = client.get_secret_value(
|
||||||
|
SecretId=secret_name)
|
||||||
|
except ClientError as e:
|
||||||
|
print(f"Failed to get secret value.\n{e}")
|
||||||
|
raise e
|
||||||
|
except botocore.exceptions.SSOTokenLoadError as tl_err:
|
||||||
|
on_token_error(tl_err)
|
||||||
|
return None
|
||||||
|
except botocore.exceptions.TokenRetrievalError as tr_err:
|
||||||
|
on_token_error(tr_err)
|
||||||
|
return None
|
||||||
|
return get_secret_value_response["SecretString"]
|
||||||
|
|
||||||
|
|
||||||
|
def _run():
|
||||||
|
this_dir = os.path.dirname(__file__)
|
||||||
|
secret_str = get_secret()
|
||||||
|
if secret_str is None:
|
||||||
|
exit(1)
|
||||||
|
secret = json.loads(secret_str)
|
||||||
|
env_vars = {}
|
||||||
|
if "api-key" in secret:
|
||||||
|
env_vars["BINANCE_API_KEY"] = secret["api-key"]
|
||||||
|
if "secret-key" in secret:
|
||||||
|
env_vars["BINANCE_SECRET_KEY"] = secret["secret-key"]
|
||||||
|
update_env_file(f"{this_dir}/.env.local", env_vars)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
_run()
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
QuickbusCfg {
|
||||||
|
value {
|
||||||
|
node {
|
||||||
|
reconnect_period_secs: 1
|
||||||
|
hb_period_msecs: 15000
|
||||||
|
max_missed_hbs: 5
|
||||||
|
parent_host: ""
|
||||||
|
parent_port: 0
|
||||||
|
my_port: 0
|
||||||
|
}
|
||||||
|
client {
|
||||||
|
reconnect_period_secs: 1
|
||||||
|
hb_period_msecs: 15000
|
||||||
|
max_missed_hbs: 5
|
||||||
|
parent_host: @SystemConfig.config_ip
|
||||||
|
parent_port: @Ports.qbus_port
|
||||||
|
my_port: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JetFIX {
|
||||||
|
value {
|
||||||
|
connection {
|
||||||
|
name: "binance_1"
|
||||||
|
venue: VENUE_BINANCE
|
||||||
|
max_order_msgs_per_window: 300
|
||||||
|
window_duration_msecs: 1000
|
||||||
|
}
|
||||||
|
connection {
|
||||||
|
name: "binance_usds_futures_1"
|
||||||
|
venue: VENUE_BINANCE_USDS_FUTURES
|
||||||
|
max_order_msgs_per_window: 300
|
||||||
|
window_duration_msecs: 1000
|
||||||
|
}
|
||||||
|
connection {
|
||||||
|
name: "okx_1"
|
||||||
|
venue: VENUE_OKX
|
||||||
|
max_order_msgs_per_window: 300
|
||||||
|
window_duration_msecs: 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MarketDataConfig {
|
||||||
|
value {
|
||||||
|
binance {
|
||||||
|
num_depth_levels: 5
|
||||||
|
url_rest_base: "https://api.binance.com"
|
||||||
|
url_ws_base: "wss://stream.binance.com:9443"
|
||||||
|
security_criteria {
|
||||||
|
clauses {
|
||||||
|
security_types: SECURITY_TYPE_SPOT
|
||||||
|
symbols: @SymbolLists.list[Binance].symbol
|
||||||
|
name_regexps: "USDC|USDT$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binance_usds_futures {
|
||||||
|
num_depth_levels: 5
|
||||||
|
url_rest_base: "https://fapi.binance.com"
|
||||||
|
url_ws_base: "wss://fstream.binance.com"
|
||||||
|
security_criteria {
|
||||||
|
clauses {
|
||||||
|
security_types: SECURITY_TYPE_FUTURE
|
||||||
|
symbols: @SymbolLists.list[BinanceUsdsFutures].symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
okx {
|
||||||
|
num_depth_levels: 5
|
||||||
|
url_rest_base: "https://aws.okx.com"
|
||||||
|
url_ws_base: "wss://wsaws.okx.com:8443"
|
||||||
|
security_criteria {
|
||||||
|
clauses {
|
||||||
|
security_types: SECURITY_TYPE_SPOT
|
||||||
|
symbols: @SymbolLists.list[OkxSpots].symbol
|
||||||
|
}
|
||||||
|
clauses {
|
||||||
|
security_types: SECURITY_TYPE_FUTURE
|
||||||
|
symbols: @SymbolLists.list[OkxFutures].symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_application_ping_pong_enabled: true
|
||||||
|
application_ping_interval_ms: 20000
|
||||||
|
application_pong_timeout_ms: 10000
|
||||||
|
is_protocol_ping_pong_enabled: true
|
||||||
|
protocol_ping_interval_ms: 60000
|
||||||
|
protocol_pong_timeout_ms: 30000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NotSimExecution {
|
||||||
|
value {
|
||||||
|
entries {
|
||||||
|
venue: VENUE_BINANCE
|
||||||
|
}
|
||||||
|
entries {
|
||||||
|
venue: VENUE_BINANCE_USDS_FUTURES
|
||||||
|
}
|
||||||
|
entries {
|
||||||
|
venue: VENUE_OKX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OkxExeCfg {
|
||||||
|
value {
|
||||||
|
account: "PROD"
|
||||||
|
ops_id: "op_id_bts"
|
||||||
|
secret_key: "240038D7A28D7F9461247CFCB8E43710"
|
||||||
|
api_key: "dc188532-c74c-4d40-affe-3c6bf4d0ca9a"
|
||||||
|
passphrase: ":,7i%tA%ivfj%SCbX?Ut"
|
||||||
|
ws_url: "wss://wsaws.okx.com:8443"
|
||||||
|
rest_url: "https://www.okx.com"
|
||||||
|
ws_ping_timeout_seconds: 10
|
||||||
|
ws_ping_interval_seconds: 25
|
||||||
|
ws_reconnect_interval_seconds: 5
|
||||||
|
ws_reconnect_max_count: 5
|
||||||
|
simulated_trading: false
|
||||||
|
tdmode: "cross"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
SymbolLists {
|
||||||
|
value {
|
||||||
|
list {
|
||||||
|
key: "Binance"
|
||||||
|
symbol: "ADA"
|
||||||
|
symbol: "APT"
|
||||||
|
symbol: "AVAX"
|
||||||
|
symbol: "BCH"
|
||||||
|
symbol: "BNB"
|
||||||
|
symbol: "BTC"
|
||||||
|
symbol: "DOGE"
|
||||||
|
symbol: "DOT"
|
||||||
|
symbol: "ETH"
|
||||||
|
symbol: "HBAR"
|
||||||
|
symbol: "LINK"
|
||||||
|
symbol: "LTC"
|
||||||
|
symbol: "OM"
|
||||||
|
symbol: "PAXG"
|
||||||
|
symbol: "PEPE"
|
||||||
|
symbol: "S"
|
||||||
|
symbol: "SHIB"
|
||||||
|
symbol: "SOL"
|
||||||
|
symbol: "SUI"
|
||||||
|
symbol: "TAO"
|
||||||
|
symbol: "TRUMP"
|
||||||
|
symbol: "USDC"
|
||||||
|
symbol: "XRP"
|
||||||
|
}
|
||||||
|
list {
|
||||||
|
key: "BinanceUsdsFutures"
|
||||||
|
symbol: "1000PEPE"
|
||||||
|
symbol: "1000SHIB"
|
||||||
|
symbol: "ADA"
|
||||||
|
symbol: "APT"
|
||||||
|
symbol: "AVAX"
|
||||||
|
symbol: "BCH"
|
||||||
|
symbol: "BNB"
|
||||||
|
symbol: "BTC"
|
||||||
|
symbol: "DOGE"
|
||||||
|
symbol: "DOT"
|
||||||
|
symbol: "ETH"
|
||||||
|
symbol: "HBAR"
|
||||||
|
symbol: "LINK"
|
||||||
|
symbol: "LTC"
|
||||||
|
symbol: "OM"
|
||||||
|
symbol: "S"
|
||||||
|
symbol: "SOL"
|
||||||
|
symbol: "SUI"
|
||||||
|
symbol: "TAO"
|
||||||
|
symbol: "TRUMP"
|
||||||
|
symbol: "USDC"
|
||||||
|
symbol: "XRP"
|
||||||
|
}
|
||||||
|
list {
|
||||||
|
key: "OkxSpots"
|
||||||
|
symbol: "ADA"
|
||||||
|
symbol: "APT"
|
||||||
|
symbol: "AVAX"
|
||||||
|
symbol: "BCH"
|
||||||
|
symbol: "BETH"
|
||||||
|
symbol: "BNB"
|
||||||
|
symbol: "BTC"
|
||||||
|
symbol: "DOGE"
|
||||||
|
symbol: "DOT"
|
||||||
|
symbol: "ETH"
|
||||||
|
symbol: "HBAR"
|
||||||
|
symbol: "LINK"
|
||||||
|
symbol: "LTC"
|
||||||
|
symbol: "OM"
|
||||||
|
symbol: "PEPE"
|
||||||
|
symbol: "S"
|
||||||
|
symbol: "SHIB"
|
||||||
|
symbol: "SOL"
|
||||||
|
symbol: "SUI"
|
||||||
|
symbol: "TRUMP"
|
||||||
|
symbol: "USDC"
|
||||||
|
symbol: "USDT"
|
||||||
|
symbol: "XRP"
|
||||||
|
}
|
||||||
|
list {
|
||||||
|
key: "OkxFutures"
|
||||||
|
symbol: "ADA"
|
||||||
|
symbol: "APT"
|
||||||
|
symbol: "AVAX"
|
||||||
|
symbol: "BCH"
|
||||||
|
symbol: "BNB"
|
||||||
|
symbol: "BTC"
|
||||||
|
symbol: "DOGE"
|
||||||
|
symbol: "DOT"
|
||||||
|
symbol: "ETH"
|
||||||
|
symbol: "HBAR"
|
||||||
|
symbol: "LINK"
|
||||||
|
symbol: "LTC"
|
||||||
|
symbol: "OM"
|
||||||
|
symbol: "PEPE"
|
||||||
|
symbol: "S"
|
||||||
|
symbol: "SHIB"
|
||||||
|
symbol: "SOL"
|
||||||
|
symbol: "SUI"
|
||||||
|
symbol: "TAO"
|
||||||
|
symbol: "TRUMP"
|
||||||
|
symbol: "USDC"
|
||||||
|
symbol: "XRP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbols {
|
||||||
|
value {
|
||||||
|
venues {
|
||||||
|
name: "VENUE_BINANCE"
|
||||||
|
spot: @SymbolLists.list[Binance].symbol
|
||||||
|
}
|
||||||
|
venues {
|
||||||
|
name: "VENUE_BINANCE_USDS_FUTURES"
|
||||||
|
future: @SymbolLists.list[BinanceUsdsFutures].symbol
|
||||||
|
}
|
||||||
|
venues {
|
||||||
|
name: "VENUE_OKX"
|
||||||
|
spot: @SymbolLists.list[OkxSpots].symbol
|
||||||
|
future: @SymbolLists.list[OkxFutures].symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -47,7 +47,7 @@ def _get_arg_parser():
|
|||||||
)
|
)
|
||||||
# TODO: add more services (api-server, pubsub, dsqa web server, etc.)
|
# TODO: add more services (api-server, pubsub, dsqa web server, etc.)
|
||||||
all_services = ["sparkd"]
|
all_services = ["sparkd"]
|
||||||
parser.add_argument("services", nargs="*")
|
parser.add_argument("services", help="this selects services defined in compose.yaml", nargs="*")
|
||||||
parser.set_defaults(
|
parser.set_defaults(
|
||||||
configuration="release",
|
configuration="release",
|
||||||
services=all_services,
|
services=all_services,
|
||||||
@@ -70,7 +70,7 @@ def _get_env_files(services, profile):
|
|||||||
add(root.joinpath(".env"))
|
add(root.joinpath(".env"))
|
||||||
add(root.joinpath(".env.local"))
|
add(root.joinpath(".env.local"))
|
||||||
if profile is not None:
|
if profile is not None:
|
||||||
if "sparkd" in services:
|
if "sparkd" in services or "sparkd-symbols" in services:
|
||||||
profile_dir=root.joinpath("src/server/sparkd/configurations", profile)
|
profile_dir=root.joinpath("src/server/sparkd/configurations", profile)
|
||||||
add(profile_dir.joinpath(".env"))
|
add(profile_dir.joinpath(".env"))
|
||||||
add(profile_dir.joinpath(".env.local"))
|
add(profile_dir.joinpath(".env.local"))
|
||||||
|
|||||||
Reference in new issue
Block a user