Skip to content

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;
        }
    }
}