Limit Order book Mgmt System in C++ !
In modern financial markets, market makers (dealers) are agents who stand ready to buy and sell securities. Market makers are remunerated for their services by being able to “buy low and sell high”. Instead of a single price at which any trade can occur, dealers quote two prices – a “bid” (dealer’s purchase, customer’s sale) and an “ask” (dealer’s sale, customer’s purchase). The ask price is higher than the bid price, and the difference between the two is called the spread – the dealer’s source of revenue.
An electronic exchange uses limit orders and employs no designated middlemen. All liquidity comes from customers’ limit orders that are arranged in order books (essentially two priority queues ordered by price) as shown in following figure (a) (limit price – number of shares). Priority is given to those participants who placed their order first.
To make it clear, I drew a picture of the logic behind the transcation process:
The main body of our orderbook system is two list--- the list contains outstanding selling orders and the list contian outstanding buying orders. Each time an order comes in, it has to through the process shown in the picture above.
For programming part, I seperate the whole program into 3 parts:
#1. Orderbook class: saves the order-book (buy and sell list ) in its private data structure, perform the transaction process abve and call the function of message class.
#2. Message class: each time an operation is made, such as order received from a broker, an transaction is made with a counterparty, order is returned due to some reason, an notification is sent.
#3. Main body: receives the order, call the order class.
#4. Order class: contain the information of an order like amount, bid/offer price, counter party name, etc and being able to change its amount after a transaction.
Now, I am going to talk about these 3 parts:
#1 Order class:
*******************************************************************************************
#ifndef STRUCTURE_H #define STRUCTURE_H #include<string> #include<map> #include<vector> #include"message.h" class Orderbook{ public: void input_order(message marketMessage, order readinOrder); void showSellOrders(); void showbuyOrders(); private: map<double, vector<order>> sellOrders; map<double, vector<order>> buyOrders; }; #endif
This is the header file of the orderbook class, there are 3 public functions--input_order, showsellorders, showbuyorders and two private map---sellorders and buyorders. The "input_order" fucntion is the core part of this class, it carries the duty to prcess the logic and to call the message fucntions. the show functions are used in the mainbody to present the current result.
Now I am going to paste the code of input_order function. It is little bit long, but the logic is very clear------I will explain again below!
************************************************************************************************
void Orderbook::input_order(message marketMessage, order readinOrder){ double inputMark = 0; if (readinOrder.showSide() == "B") { marketMessage.received(readinOrder); if ((sellOrders.empty())) { if (readinOrder.showType() == "limit") { buyOrders[readinOrder.showPrice()].push_back(readinOrder); inputMark = 1; } else marketMessage.returned(readinOrder); } else{ if (readinOrder.showType() == "market") { while (1) { map<double, vector<order>>::iterator sell_iter = sellOrders.begin(); if (sell_iter == sellOrders.end()) break; else { for (int i = 0; i <= (sell_iter->second).size() - 1; i++) { if (((sell_iter->second)[i]).showQuantity() >= readinOrder.showQuantity()) { marketMessage.deal(((sell_iter->second)[i]), readinOrder); ((sell_iter->second)[i]).change_volume(readinOrder.showQuantity()); readinOrder.change_volume(readinOrder.showQuantity()); } else { marketMessage.deal(readinOrder, ((sell_iter->second)[i])); readinOrder.change_volume(((sell_iter->second)[i]).showQuantity()); ((sell_iter->second)[i]).change_volume(((sell_iter->second)[i]).showQuantity()); } } while (1) { vector<order>::iterator temp = (sell_iter->second).begin(); if (temp == (sell_iter->second).end()) break; else if ((*temp).showQuantity() == 0) (sell_iter->second).erase(temp); else break; }
if ((sell_iter->second).size() == 0) sellOrders.erase(sell_iter); else break; } } } if (readinOrder.showType() == "limit") { while (1) { map<double, vector<order>>::iterator sell_iter = sellOrders.begin(); if ((sellOrders.size() == 0)) break; else if ((sell_iter->first) > readinOrder.showPrice()) { marketMessage.complete(readinOrder); break; } else { for (int i = 0; i <= (sell_iter->second).size() - 1; i++) { if (((sell_iter->second)[i]).showQuantity() >= readinOrder.showQuantity()) { marketMessage.deal(((sell_iter->second)[i]), readinOrder); ((sell_iter->second)[i]).change_volume(readinOrder.showQuantity()); readinOrder.change_volume(readinOrder.showQuantity()); } else { marketMessage.deal(readinOrder, ((sell_iter->second)[i])); readinOrder.change_volume(((sell_iter->second)[i]).showQuantity()); ((sell_iter->second)[i]).change_volume(((sell_iter->second)[i]).showQuantity()); } } while (1) { vector<order>::iterator temp = (sell_iter->second).begin(); if (temp == (sell_iter->second).end()) break; else if ((*temp).showQuantity() == 0) (sell_iter->second).erase(temp); else break; }
if ((sell_iter->second).size() == 0) sellOrders.erase(sell_iter); else break; } } } }
} else { if ((buyOrders.empty())) { if (readinOrder.showType() == "limit") { sellOrders[readinOrder.showPrice()].push_back(readinOrder); marketMessage.complete(readinOrder); inputMark = 1; } else marketMessage.returned(readinOrder); } else{ if (readinOrder.showType() == "market") { while (1) { map<double, vector<order>>::iterator buy_iter = buyOrders.end(); if (buyOrders.empty()) break; else { buy_iter--; int xx = 0; for (int i = 0; i <= (buy_iter->second).size() - 1; i++, xx++) { if (((buy_iter->second)[i]).showQuantity() >= readinOrder.showQuantity()) { marketMessage.deal(((buy_iter->second)[i]), readinOrder); ((buy_iter->second)[i]).change_volume(readinOrder.showQuantity()); readinOrder.change_volume(readinOrder.showQuantity()); } else { marketMessage.deal(readinOrder, ((buy_iter->second)[i])); readinOrder.change_volume(((buy_iter->second)[i]).showQuantity()); ((buy_iter->second)[i]).change_volume(((buy_iter->second)[i]).showQuantity()); } } while (1) {
vector<order>::iterator temp = (buy_iter->second).begin(); if (temp == (buy_iter->second).end()) break; else if ((*temp).showQuantity() == 0) (buy_iter->second).erase(temp); else break; } if ((buy_iter->second).size() == 0) buyOrders.erase(buy_iter); else break; } } } //~~~~~~~~~~ if (readinOrder.showType() == "limit") { while (1) { map<double, vector<order>>::iterator buy_iter = buyOrders.end(); if ((buyOrders.size() == 0)) break; else { buy_iter--; if ((buy_iter->first) < readinOrder.showPrice()) { marketMessage.complete(readinOrder); break; } else { for (int i = 0; i <= (buy_iter->second).size() - 1; i++) { if (((buy_iter->second)[i]).showQuantity() >= readinOrder.showQuantity()) { marketMessage.deal(((buy_iter->second)[i]), readinOrder); ((buy_iter->second)[i]).change_volume(readinOrder.showQuantity()); readinOrder.change_volume(readinOrder.showQuantity()); } else { marketMessage.deal(readinOrder, ((buy_iter->second)[i])); readinOrder.change_volume(((buy_iter->second)[i]).showQuantity()); ((buy_iter->second)[i]).change_volume(((buy_iter->second)[i]).showQuantity()); } } { vector<order>::iterator temp = (buy_iter->second).begin(); if (temp == (buy_iter->second).end()) break; else if ((*temp).showQuantity() == 0) (buy_iter->second).erase(temp); else break; } if ((buy_iter->second).size() == 0) buyOrders.erase(buy_iter); else break; } } } } } } if (readinOrder.showQuantity() != 0) { if (readinOrder.showType() == "limit")
{ if ((readinOrder.showSide() == "B") && inputMark == 0) buyOrders[readinOrder.showPrice()].push_back(readinOrder); else if ((readinOrder.showSide() == "S") && inputMark == 0) sellOrders[readinOrder.showPrice()].push_back(readinOrder); marketMessage.partin(readinOrder); } } else{
}
}
Actually only half of the code is meaningful, as I suggested in the picture, processing a selling order is nothing different than processing buying order but only involving changing the counterparty type from "selling" to "buying" and preferring higher price than lower price (> ~ <).
If you read the code with the picture above, it will become very easy.
There might be some confusion regarding this block of code in the function. This block of code is used to judge wheather the counterparty's list is exhausted. This is little bit technical.....
while (1) { vector<order>::iterator temp = (sell_iter->second).begin(); if (temp == (sell_iter->second).end()) break; else if ((*temp).showQuantity() == 0) (sell_iter->second).erase(temp); else break; }
if ((sell_iter->second).size() == 0) sellOrders.erase(sell_iter);
Another thing to be noticed is that every time an operation is made, this program will call the function from class "marketMessage", which will take an order type as input, and produces the relative information regarding this order. We are going to introduce this below.
#2 Message Class
******************************************************************************************
#include"message.h" using namespace std;
void message::received(order readinOrder){ cout << "RECEIVED: " << readinOrder.showCounter() <<" 's order is received" << endl; cout << "--------------------------------------------" << endl; } void message::returned(order readinOrder){ string side; if (readinOrder.showSide() == "S") side = "sell"; else side = "buy"; cout << "RETURNED: " << readinOrder.showCounter() << " no counterparty is founded for your order" << endl; cout << "--------------------------------------------" << endl; } void message::deal(order larger, order smaller){ if ((smaller.showQuantity())*(larger.showQuantity()) != 0) { cout << "FULFILLED: " << smaller.showCounter() << ", Your whole order is completed by " << larger.showCounter() << endl; cout << "--------------------------------------------" << endl; cout << "FULFILLED: " << larger.showCounter() << ", Your order is completed with " << smaller.showCounter() << " buy the quantity of " << smaller.showQuantity() << endl; cout << "--------------------------------------------" << endl; } } void message::complete(order readinOrder){
cout << " PUT IN ORDER : " << readinOrder.showCounter() << " , No counterparty, Order is now in the orderbook " << endl; cout << "--------------------------------------------" << endl; } void message::partin(order readinOrder){
cout << "INFO : " << readinOrder.showCounter() << " , After transaction, there are " << readinOrder.showQuantity() << " shares of your order in the list" << endl; cout << "--------------------------------------------" << endl; } void message::partreturn(order readinOrder){
cout << "[Market Message-Status]: " << readinOrder.showCounter() << " , your order has been partially fuifiled, the rest of your order (" << readinOrder.showQuantity() << " )has been returned " << endl; cout << "--------------------------------------------" << endl; }
This class is composed by a series of mini functions, they serve the function of sending message in various condition.
#3 Main body
*********************************************************************************************
#include<iostream> #include<map> #include<vector> #include<string> #include<fstream> #include"order.h" #include"message.h" #include"Orderbook.h" using namespace std;
int main(){
Orderbook orderbook; message MarketMessage; ifstream readin; readin.open("orders.txt"); int m = 1; string temp; vector<string> oneorder; while (m) { readin >> temp; if (readin) { oneorder.push_back(temp); if ((oneorder.size() > 0) && (oneorder.size() % 6 == 0)) { order inputorder(oneorder[0], oneorder[1], oneorder[2], atoi((oneorder[3]).c_str()), atof((oneorder[4]).c_str()), oneorder[5]); orderbook.input_order(MarketMessage, inputorder); oneorder.clear(); } } else { m = 0; if (readin.eof()); else exit(0); } } readin.close(); orderbook.showSellOrders(); orderbook.showbuyOrders();
return 1; }
What the main function do is to read order data from file and then generate a order type data, and then call orderbook class' s function to process this order.
#4 order class
*************************************************************************************************
#include"order.h"
order::order(string security, string buyorsell, string morl, int quantity, double pricetag, string party){ ticker = security; side = buyorsell; type = morl; volume = quantity; price = pricetag; counterparty = party; }