SimpleMakerStrategy
This examples shows a simple maker strategy with order management system: quote on both bid and ask side.
#include <SimpleMakerStrategy.h>
#include <stdlib.h>
#include <algorithm>
using namespace aats;
using namespace std;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using std::chrono::system_clock;
void SimpleMakerStrategy::init(){
cout << "init derivedStrategy" << endl;
}
SimpleMakerStrategy::~SimpleMakerStrategy(){}
void SimpleMakerStrategy::on_notify(NotifyType type){
if(type == NT_BOOK){
double bid_tgt_px = _symbols[_trade_cid]->bid_px * (1-0.0001);
double ask_tgt_px = _symbols[_trade_cid]->ask_px * (1+0.0001);
maintain_order("buy", bid_tgt_px);
maintain_order("sell", ask_tgt_px);
}
}
void SimpleMakerStrategy::on_ping(){
// order status check
cout << "pending buy: " << _pending_orders["buy"].size()
<< " pending sell: " << _pending_orders["sell"].size()
<< " active buy: " << _active_orders["buy"].size()
<< " active sell: " << _active_orders["sell"].size() << endl;
if(_cancelling_order_ids.size() >= 1){
for(auto &id:_cancelling_order_ids){
cout << "cancelling order id: " << id << endl;
}
}
}
void SimpleMakerStrategy::maintain_order(string side, double qpx){
if(_active_orders[side].size() >= 1){
LOrder* order = _active_orders[side].front();
double opx = order->px;
// cout << "MAINTRAIN_ORDER side " << side << " qpx " << qpx << " opx " << opx << " diff_spread " << abs(qpx/opx-1) << endl;
if(abs(qpx/opx-1)>0.0001){
// cout << "MAINTRAIN_ORDER side " << side << " qpx " << qpx << " opx " << opx << endl;
if (find(_cancelling_order_ids.begin(), _cancelling_order_ids.end(), order->order_id) == _cancelling_order_ids.end()){
// _cancelling_order_ids.push_back(order->order_id);
cancel_order(order);
}
}
}else if(_pending_orders[side].size() == 0){
double size = 100 / qpx;
send_order(_trade_exchange, _trade_symbol, qpx, size, side, "pos");
}
}
void SimpleMakerStrategy::send_order(std::string exchange, std::string symbol, double price, double size, string side, std::string tif){
LOrder *ord = new LOrder();
ord->exchange = exchange;
ord->symbol = symbol;
ord->order_id = _order_id;
ord->px = price;
ord->qty = size;
ord->side = side;
ord->tif = tif;
_pending_orders[side].push_back(ord);
place_order(ord);
_order_id += 1;
}
void SimpleMakerStrategy::cancel_order(LOrder* order){
_cancelling_order_ids.push_back(order->order_id);
BaseStrategy::cancel_order(order);
}
void SimpleMakerStrategy::onOrderCreated(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_pending_orders[side]){
if(order->order_id == order_id){
order->status = "ADD";
_active_orders[side].push_back(order);
// _pending_orders[side].remove(order);
order->get_order_info();
return;
}
}
}
void SimpleMakerStrategy::onOrderAcked(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
order->status = "ACK";
order->get_order_info();
for(auto &order: _pending_orders[side]){
if(order->order_id == order_id){
_pending_orders[side].remove(order);
return;
}
}
}
}
}
void SimpleMakerStrategy::onOrderRejected(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
order->status = "RJD";
order->get_order_info();
for(auto &order: _pending_orders[side]){
if(order->order_id == order_id){
_pending_orders[side].remove(order);
return;
}
}
}
}
}
void SimpleMakerStrategy::onOrderCancelCreated(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
order->status = "CXL";
order->get_order_info();
return;
}
}
}
void SimpleMakerStrategy::onOrderCancelAcked(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
order->status = "CAK";
order->get_order_info();
return;
}
}
}
void SimpleMakerStrategy::onOrderCancelRejected(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
// remove order from active order list if crj count is more than 3
if(order->crj_cnt >= 3){
_cancelling_order_ids.remove(order_id);
_active_orders[side].remove(order);
cout << "remove order due to CRJ: id " << order->order_id << endl;
return;
}
order->status = "CRJ";
order->crj_cnt += 1;
order->get_order_info();
return;
}
}
}
void SimpleMakerStrategy::onOrderExec(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
string tmp = data.at("fill_size");
double fill_size = atof(tmp.c_str());
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
order->fill_qty += fill_size;
if (abs(order->fill_qty - order->qty)<=1e-8){
order->status = "EXE";
order->get_order_info();
_active_orders[side].remove(order);
_cancelling_order_ids.remove(order_id);
return;
}
order->status = "EXE";
order->get_order_info();
return;
}
}
}
void SimpleMakerStrategy::onOrderCanceled(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
order->status = "CXD";
_cancelling_order_ids.remove(order_id);
_active_orders[side].remove(order);
order->get_order_info();
return;
}
}
}
void SimpleMakerStrategy::onOrderClosed(string msg){
json data = json::parse(msg).at("order");
int order_id = data.at("order_id");
string side = data.at("side");
for(auto &order:_active_orders[side]){
if(order->order_id == order_id){
order->status = "CLD";
_active_orders[side].remove(order);
_cancelling_order_ids.remove(order_id);
order->get_order_info();
return;
}
}
}