-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathOrderBook.cpp
156 lines (143 loc) · 4.83 KB
/
OrderBook.cpp
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
#include "OrderBook.h"
#include "CSVReader.h"
#include <map>
OrderBook::OrderBook(std::string filename)
{
orders = CSVReader::readCSV(filename);
}
std::vector<std::string> OrderBook::getKnownProducts()
{
std::vector<std::string> products;
std::map<std::string, bool> productMap;
for (const OrderBookEntry& order : orders)
{
productMap[order.product] = true;
}
// now flatten the map to a vector of strings
for (auto const& product : productMap)
{
products.push_back(product.first);
}
return products;
}
std::vector<OrderBookEntry> OrderBook::getOrders(OrderBookType type,
std::string product,
std::string timestamp)
{
std::vector<OrderBookEntry> result;
for (OrderBookEntry& order : orders)
{
if (order.orderType == type && order.product == product && order.timestamp == timestamp)
{
result.push_back(order);
}
}
return result;
}
double OrderBook::getHighPrice(std::vector<OrderBookEntry>& orders)
{
double max = orders[0].price;
for (OrderBookEntry& order : orders)
{
if (order.price > max) max = order.price;
}
return max;
}
double OrderBook::getLowPrice(std::vector<OrderBookEntry>& orders)
{
double min = orders[0].price;
for (OrderBookEntry& order : orders)
{
if (order.price < min) min = order.price;
}
return min;
}
double OrderBook::getTotalVolume(std::vector<OrderBookEntry>& orders)
{
double totalVolume = 0.0;
for(const OrderBookEntry& order : orders) {
totalVolume += order.amount;
}
return totalVolume;
}
std::string OrderBook::getEarliestTime()
{
return orders[0].timestamp;
}
std::string OrderBook::getNextTime(std::string timestamp)
{
std::string nextTimestamp;
for (const OrderBookEntry& order : orders)
{
if (order.timestamp > timestamp)
{
nextTimestamp = order.timestamp;
break;
}
}
if (nextTimestamp == "")
{
nextTimestamp = orders[0].timestamp;
}
return nextTimestamp;
}
void OrderBook::insertOrder(OrderBookEntry& order)
{
orders.push_back(order);
std::sort(orders.begin(), orders.end(), OrderBookEntry::compareByTimestamp);
}
std::vector<OrderBookEntry> OrderBook::matchAsksToBids(std::string product, std::string timestamp)
{
std::vector<OrderBookEntry> sales;
std::vector<OrderBookEntry> asks = getOrders(OrderBookType::ask, product, timestamp);
std::vector<OrderBookEntry> bids = getOrders(OrderBookType::bid, product, timestamp);
std::sort(asks.begin(), asks.end(), OrderBookEntry::compareByPriceAsc); // sort asks lowest first
std::sort(bids.begin(), bids.end(), OrderBookEntry::compareByPriceDesc); // sort bids highest first
for (OrderBookEntry& ask : asks)
{
for (OrderBookEntry& bid : bids)
{
if (bid.price >= ask.price)
{ // we have a match
OrderBookEntry sale{ask.price, 0, timestamp, product, OrderBookType::asksale};
if (bid.username == "simuser")
{
sale.username = "simuser";
sale.orderType = OrderBookType::bidsale;
}
if (ask.username == "simuser")
{
sale.username = "simuser";
sale.orderType = OrderBookType::asksale;
}
// now we work out how much was sold
// create new bids and asks covering
// anything that was not sold
if (bid.amount == ask.amount)
{ // bid completely clears ask
sale.amount = ask.amount;
sales.push_back(sale);
bid.amount = 0; // make sure the bid is not processed again
break; // can do no more with this ask, go onto the next ask
}
if (bid.amount > ask.amount)
{ // ask is completely gone, slice the bid
sale.amount = ask.amount;
sales.push_back(sale);
bid.amount -= ask.amount; // adjust the bid in place
ask.amount = 0; // ask is completely gone, go to next ask
break;
}
if (bid.amount < ask.amount && bid.amount > 0)
{ // bid is completely gone, slice the ask
sale.amount = bid.amount;
sales.push_back(sale);
ask.amount -= bid.amount; // update the ask
bid.amount = 0; // make sure the bid is not processed again
continue; // some ask remains, go to the next bid
}
}
}
}
return sales;
}