-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOrderBook.cpp
More file actions
186 lines (157 loc) · 5.15 KB
/
OrderBook.cpp
File metadata and controls
186 lines (157 loc) · 5.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include "OrderBook.h"
#include "CSVReader.h"
#include <map>
/** contruct reading a csv data file*/
OrderBook::OrderBook(std::string fileName)
{
orders = CSVReader::readCSV(fileName);
}
/** Gets all known products in dataset*/
std::vector<std::string> OrderBook::getKnownProducts()
{
std::vector<std::string> products;
std::map<std::string, bool> prodMap;
for (OrderBookEntry& e : orders)
{
prodMap[e.product] = true;
}
// flatten the map into a vector of strings
for (auto const& e : prodMap)
{
products.push_back(e.first);
}
return products;
}
/** Gets all orders according to sent filters*/
std::vector<OrderBookEntry> OrderBook::getOrders(OrderBookType type,
std::string product,
std::string timestamp)
{
std::vector<OrderBookEntry> orders_sub;
for (OrderBookEntry& e : orders)
{
if (e.orderType == type &&
e.product == product &&
e.timeStamp == timestamp)
{
orders_sub.push_back(e);
}
}
return orders_sub;
}
/** Returns the highest price of a vector of orders.*/
double OrderBook::getHighPrice(std::vector<OrderBookEntry>& orders)
{
double max = orders[0].price;
for (OrderBookEntry& e : orders) {
if (e.price > max) max = e.price;
}
return max;
}
/** Returns the lowest price of a vector of orders.*/
double OrderBook::getLowPrice(std::vector<OrderBookEntry>& orders)
{
double min = orders[0].price;
for (OrderBookEntry& e : orders) {
if (e.price < min) min = e.price;
}
return min;
}
/** Returns the earliest time in the order book*/
std::string OrderBook::getEarliestTime()
{
// assuming orders are sorted
return orders[0].timeStamp;
}
/** Returns the next time after the sent time
* If there is no next it wraps around to the start.
*/
std::string OrderBook::getNextTime(std::string timeStamp)
{
std::string next_timeStamp = "";
// again assuming ordered by time
for (OrderBookEntry& e : orders)
{
if (e.timeStamp > timeStamp)
{
next_timeStamp = e.timeStamp;
break;
}
}
// wrapping to start
if (next_timeStamp == "") next_timeStamp = orders[0].timeStamp;
return next_timeStamp;
}
/**Inserting an order into the book*/
void OrderBook::insertOrder(OrderBookEntry& order)
{
orders.push_back(order);
// sorts the orders by timestamp
std::sort(orders.begin(), orders.end(), OrderBookEntry::campareByTimestamp);
}
/** Matching algorithm (price-time priority with pro rata based partial order completion)*/
std::vector<OrderBookEntry> OrderBook::matchAsksToBids(std::string product, std::string timestamp)
{
// get all the asks and bids
std::vector<OrderBookEntry> asks = getOrders(OrderBookType::ask,
product,
timestamp);
std::vector<OrderBookEntry> bids = getOrders(OrderBookType::bid,
product,
timestamp);
std::vector<OrderBookEntry> sales;
// sort asks in ascending order and bids in decending order (price priority)
std::sort(asks.begin(), asks.end(), OrderBookEntry::compareByPriceAsc);
std::sort(bids.begin(), bids.end(), OrderBookEntry::compareByPriceDesc);
// iterate through all bids and asks
for (OrderBookEntry &ask : asks)
{
for (OrderBookEntry &bid : bids)
{
// order can be placed
if (bid.price >= ask.price)
{
// create a new sale
OrderBookEntry sale{ask.price, 0, timestamp, product, OrderBookType::asksale};
// update the order type for our simulated user
if (bid.username == "simuser")
{
sale.username = "simuser";
sale.orderType = OrderBookType::bidsale;
}
if (ask.username == "simuser")
{
sale.username = "simuser";
sale.orderType = OrderBookType::asksale;
};
// if the bid and ask amounts are the same, transfer all over to bidder
if (bid.amount == ask.amount)
{
sale.amount = ask.amount;
sales.push_back(sale);
bid.amount = 0;
break;
}
// if the bid amount > ask amount, only take the amount that was offered
if (bid.amount > ask.amount)
{
sale.amount = ask.amount;
sales.push_back(sale);
bid.amount = bid.amount - ask.amount;
break;
}
// give the highest bidder the amount they asked for, leave the rest in the ask
if (bid.amount < ask.amount &&
bid.amount > 0)
{
sale.amount = bid.amount;
sales.push_back(sale);
ask.amount = ask.amount - bid.amount;
bid.amount = 0;
continue;
}
}
}
}
return sales;
}