Added json parsing, protocol comprehension and began executables for algs
 
	
	
	
	
	
	
		
		1 files deleted
	
		
		12 files added
	
		
		7 files modified
	
	
 
	
	
	
	
	
	
	
	
 |  |  | 
 |  |  | AllowShortIfStatementsOnASingleLine: true | 
 |  |  | BreakBeforeBraces: Linux | 
 |  |  | IndentCaseLabels: false | 
 |  |  | --- | 
 |  |  | PointerAlignment: Left | 
 |  |  | AllowShortIfStatementsOnASingleLine: true | 
 |  |  | IndentCaseBlocks: true | 
 |  |  | IndentCaseLabels: false | 
 |  |  | SortUsingDeclarations: true | 
 
| New file | 
 |  |  | 
 |  |  | [submodule "cpp-httplib"] | 
 |  |  |     path = cpp-httplib | 
 |  |  |     url = https://github.com/yhirose/cpp-httplib.git | 
 |  |  | [submodule "date"] | 
 |  |  |     path = date | 
 |  |  |     url = https://github.com/HowardHinnant/date.git | 
 
| New file | 
 |  |  | 
 |  |  | cmake_minimum_required(VERSION 3.10) | 
 |  |  |  | 
 |  |  | project(bomex) | 
 |  |  |  | 
 |  |  | set(CMAKE_CXX_STANDARD 20) | 
 |  |  | set(CMAKE_CXX_STANDARD_REQUIRED True) | 
 |  |  |  | 
 |  |  | add_subdirectory(date) | 
 |  |  |  | 
 |  |  | add_library(MAIN json.cpp date protocol.cpp book.cpp) | 
 |  |  |  | 
 |  |  | add_executable(test test.cpp strat.cpp) | 
 |  |  | add_executable(bot bot.cpp strat.cpp) | 
 |  |  | add_executable(click click.cpp) | 
 |  |  |  | 
 |  |  | target_link_libraries(test PUBLIC MAIN) | 
 |  |  | target_link_libraries(bot PUBLIC MAIN) | 
 |  |  | target_link_libraries(click PUBLIC MAIN) | 
 
 |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  | #include <algorithm> | 
 |  |  | #include <chrono> | 
 |  |  | #include <cstddef> | 
 |  |  | #include <iostream> | 
 |  |  |  | 
 |  |  | Order::Order(double price, OrderSideEnum side, int volume, | 
 |  |  |              std::chrono::nanoseconds timestamp, std::string id) | 
 |  |  | namespace book | 
 |  |  | { | 
 |  |  | Order::Order(double price, OrderSideEnum side, int volume, double timestamp, | 
 |  |  |              std::string id) | 
 |  |  |     : price{price}, side{side}, remaining_volume{volume}, | 
 |  |  |       filled_volume(0), timestamp{timestamp}, id{id} {} | 
 |  |  |       filled_volume(0), timestamp{timestamp}, id{id} | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | Level::Level(Order &order) | 
 |  |  | Level::Level(Order& order) | 
 |  |  |     : price{order.price}, volume(order.remaining_volume), side{order.side}, | 
 |  |  |       timestamp{order.timestamp}, id{order.id} {} | 
 |  |  |  | 
 |  |  | bool operator<(const Level &a, const Level &b) { | 
 |  |  |   if (a.price < b.price) | 
 |  |  |     return true; | 
 |  |  |   else if (a.price == b.price && (a.timestamp.count() > b.timestamp.count())) | 
 |  |  |     return true; | 
 |  |  |   else | 
 |  |  |     return false; | 
 |  |  |       timestamp{order.timestamp}, id{order.id} | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | bool operator>(const Level &a, const Level &b) { | 
 |  |  |   if (a.price > b.price) | 
 |  |  |     return true; | 
 |  |  |   else if (a.price == b.price && (a.timestamp.count() > b.timestamp.count())) | 
 |  |  |     return true; | 
 |  |  |   else | 
 |  |  |     return false; | 
 |  |  | bool operator<(const Level& a, const Level& b) | 
 |  |  | { | 
 |  |  |     if (a.price < b.price) | 
 |  |  |     return true; | 
 |  |  |     else if (a.price == b.price && (a.timestamp > b.timestamp)) | 
 |  |  |     return true; | 
 |  |  |     else | 
 |  |  |     return false; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | bool operator<=(const Level &a, const Level &b) { | 
 |  |  |   if (a.price <= b.price) | 
 |  |  |     return true; | 
 |  |  |   else if (a.price == b.price && (a.timestamp.count() >= b.timestamp.count())) | 
 |  |  |     return true; | 
 |  |  |   else | 
 |  |  |     return false; | 
 |  |  | bool operator>(const Level& a, const Level& b) | 
 |  |  | { | 
 |  |  |     if (a.price > b.price) | 
 |  |  |     return true; | 
 |  |  |     else if (a.price == b.price && (a.timestamp > b.timestamp)) | 
 |  |  |     return true; | 
 |  |  |     else | 
 |  |  |     return false; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | bool operator>=(const Level &a, const Level &b) { | 
 |  |  |   if (a.price >= b.price) | 
 |  |  |     return true; | 
 |  |  |   else if (a.price == b.price && (a.timestamp.count() >= b.timestamp.count())) | 
 |  |  |     return true; | 
 |  |  |   else | 
 |  |  |     return false; | 
 |  |  | bool operator<=(const Level& a, const Level& b) | 
 |  |  | { | 
 |  |  |     if (a.price <= b.price) | 
 |  |  |     return true; | 
 |  |  |     else if (a.price == b.price && (a.timestamp >= b.timestamp)) | 
 |  |  |     return true; | 
 |  |  |     else | 
 |  |  |     return false; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | bool operator==(const Level &a, const Level &b) { | 
 |  |  |     if (a.price == b.price && (a.timestamp.count() == b.timestamp.count())) | 
 |  |  |     return true; | 
 |  |  |   else | 
 |  |  |     return false; | 
 |  |  | bool operator>=(const Level& a, const Level& b) | 
 |  |  | { | 
 |  |  |     if (a.price >= b.price) | 
 |  |  |     return true; | 
 |  |  |     else if (a.price == b.price && (a.timestamp >= b.timestamp)) | 
 |  |  |     return true; | 
 |  |  |     else | 
 |  |  |     return false; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | bool operator==(const Level& a, const Level& b) | 
 |  |  | { | 
 |  |  |     if (a.price == b.price && (a.timestamp == b.timestamp)) | 
 |  |  |     return true; | 
 |  |  |     else | 
 |  |  |     return false; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | std::ostream& operator<<(std::ostream& out, const Level& a) | 
 |  |  | { | 
 |  |  |     return out << "Price: " << a.price << ", volume: " << a.volume << ", time: " << a.timestamp.count() << ", id: " << a.id; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | template<class T> | 
 |  |  | void Side<T>::deleteLevel(std::string orderId) | 
 |  |  | { | 
 |  |  |     for (auto i = this->c.begin(); i != this->c.end();) { | 
 |  |  |         if (*i.id == orderId) { | 
 |  |  |             this->c.erase(i); | 
 |  |  |             std::make_heap(this->c.begin(), this->c.end(), this->comp); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  | } | 
 |  |  |  | 
 |  |  | template<class T> | 
 |  |  | void Side<T>::topRemoveVolume(int volume) { this->c[0].volume -= volume; } | 
 |  |  |  | 
 |  |  | template<class T> | 
 |  |  | void Side<T>::printTop(std::size_t num) | 
 |  |  | { | 
 |  |  |     std::vector<Level> copy(this->c); | 
 |  |  |     std::sort(copy.begin(), copy.end(), this->comp); | 
 |  |  |     if (copy.size() && copy[0].side == Buy) | 
 |  |  |         std::reverse(copy.begin(), copy.end()); | 
 |  |  |     for (std::size_t i = 0; i < copy.size() &&  i < num; i++) { | 
 |  |  |         std::cout << copy[i] << std::endl; | 
 |  |  |     } | 
 |  |  |     return out << "Price: " << a.price << ", volume: " << a.volume | 
 |  |  |                << ", time: " << a.timestamp << ", id: " << a.id; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | Book::Book() | 
 |  |  |     : bidSide(), askSide(), productType(TEST), product("a"), stationId("b"), | 
 |  |  |       unit("c"), expiry(std::chrono::nanoseconds(0)), aggFee(1), pasFee(-1), | 
 |  |  |       broFee(2) {} | 
 |  |  |       broFee(2) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | Book::Book(ProductTypeEnum productType, std::string product, | 
 |  |  |            std::string stationId, std::string unit, | 
 |  |  | 
 |  |  |            double broFee) | 
 |  |  |     : bidSide{}, askSide{}, productType{productType}, product(product), | 
 |  |  |       stationId(stationId), unit(unit), expiry(expiry), aggFee(aggFee), | 
 |  |  |       pasFee(pasFee), broFee(broFee) {} | 
 |  |  |       pasFee(pasFee), broFee(broFee) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void Book::ask(Order &order) { | 
 |  |  |   while (this->bidSide.size() && this->bidSide.top().price >= order.price) { | 
 |  |  |     if (this->bidSide.top().volume > order.remaining_volume) { | 
 |  |  |       int temp = this->bidSide.top().volume; | 
 |  |  |       order.filled_volume += temp; | 
 |  |  |       this->bidSide.topRemoveVolume(order.remaining_volume); | 
 |  |  |       order.remaining_volume -= temp; | 
 |  |  |       break; | 
 |  |  |     } else { | 
 |  |  |       order.remaining_volume -= this->bidSide.top().volume; | 
 |  |  |       order.filled_volume += this->bidSide.top().volume; | 
 |  |  |       this->bidSide.pop(); | 
 |  |  | void Book::ask(Order& order) | 
 |  |  | { | 
 |  |  |     while (this->bidSide.size() && this->bidSide[0].price >= order.price) { | 
 |  |  |     if (this->bidSide[0].volume > order.remaining_volume) { | 
 |  |  |         int temp = this->bidSide[0].volume; | 
 |  |  |         order.filled_volume += temp; | 
 |  |  |         this->bidSide.front().volume -= order.remaining_volume; | 
 |  |  |         order.remaining_volume -= temp; | 
 |  |  |         break; | 
 |  |  |     } else { | 
 |  |  |         order.remaining_volume -= this->bidSide[0].volume; | 
 |  |  |         order.filled_volume += this->bidSide[0].volume; | 
 |  |  |         this->bidSide.erase(this->bidSide.begin()); | 
 |  |  |         std::make_heap(this->bidSide.begin(), this->bidSide.end(), | 
 |  |  |                        std::less<Level>()); | 
 |  |  |     } | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  |   if (order.remaining_volume > 0) { | 
 |  |  |     this->askSide.emplace(order); | 
 |  |  |   } | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void Book::bid(Order &order) { | 
 |  |  |   while (this->askSide.size() && this->askSide.top().price <= order.price) { | 
 |  |  |     if (this->askSide.top().volume > order.remaining_volume) { | 
 |  |  |       int temp = this->askSide.top().volume; | 
 |  |  |       order.filled_volume += temp; | 
 |  |  |       this->askSide.topRemoveVolume(order.remaining_volume); | 
 |  |  |       order.remaining_volume -= temp; | 
 |  |  |       break; | 
 |  |  |     } else { | 
 |  |  |       order.remaining_volume -= this->askSide.top().volume; | 
 |  |  |       order.filled_volume += this->askSide.top().volume; | 
 |  |  |       this->askSide.pop(); | 
 |  |  |     if (order.remaining_volume > 0) { | 
 |  |  |     this->askSide.emplace(this->askSide.begin(), order); | 
 |  |  |     std::make_heap(this->askSide.begin(), this->askSide.end(), | 
 |  |  |                    std::greater<Level>()); | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  |   if (order.remaining_volume > 0) { | 
 |  |  |     this->bidSide.emplace(order); | 
 |  |  |   } | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void Book::printBook(std::size_t numOrders) { | 
 |  |  |   std::cout << "Sell side: " << this->askSide.size() << std::endl; | 
 |  |  |   this->askSide.printTop(numOrders); | 
 |  |  |   std::cout << "Buy side: " << this->bidSide.size() << std::endl; | 
 |  |  |   this->bidSide.printTop(numOrders); | 
 |  |  | void Book::bid(Order& order) | 
 |  |  | { | 
 |  |  |     while (this->askSide.size() && this->askSide[0].price <= order.price) { | 
 |  |  |     if (this->askSide[0].volume > order.remaining_volume) { | 
 |  |  |         int temp = this->askSide.front().volume; | 
 |  |  |         order.filled_volume += temp; | 
 |  |  |         this->askSide.front().volume -= order.remaining_volume; | 
 |  |  |         order.remaining_volume -= temp; | 
 |  |  |         break; | 
 |  |  |     } else { | 
 |  |  |         order.remaining_volume -= this->askSide[0].volume; | 
 |  |  |         order.filled_volume += this->askSide[0].volume; | 
 |  |  |         this->askSide.erase(this->askSide.begin()); | 
 |  |  |         std::make_heap(this->askSide.begin(), this->askSide.end(), | 
 |  |  |                        std::greater<Level>()); | 
 |  |  |     } | 
 |  |  |     } | 
 |  |  |     if (order.remaining_volume > 0) { | 
 |  |  |     this->bidSide.emplace(this->bidSide.begin(), order); | 
 |  |  |     std::make_heap(this->bidSide.begin(), this->bidSide.end(), | 
 |  |  |                    std::less<Level>()); | 
 |  |  |     } | 
 |  |  | } | 
 |  |  |  | 
 |  |  | Book testBook(int orders, bool printBook) { | 
 |  |  |   Book b = Book(); | 
 |  |  |   std::chrono::nanoseconds time(1); | 
 |  |  |   for (int i = 1; i < orders; i++) { | 
 |  |  |     Order t(i, Buy, 10, time++, "a"); | 
 |  |  |     b.bid(t); | 
 |  |  |   } | 
 |  |  |   for (int i = orders + 1; i < 2 * orders; i++) { | 
 |  |  |     Order t(i, Sell, 10, time++, "b"); | 
 |  |  |     b.ask(t); | 
 |  |  |   } | 
 |  |  |   if (printBook) | 
 |  |  |     b.printBook(orders - 1); | 
 |  |  |   return b; | 
 |  |  | void Book::printBook(std::size_t numOrders) | 
 |  |  | { | 
 |  |  |     std::cout << "Sell side: " << this->askSide.size() << std::endl; | 
 |  |  |     std::vector<Level> askCopy(this->askSide); | 
 |  |  |     int count = 0; | 
 |  |  |     std::sort(askCopy.begin(), askCopy.end()); | 
 |  |  |     for (auto i = askCopy.rbegin(); i != askCopy.rend() && count < numOrders; i++, count++) { | 
 |  |  |         std::cout << *i << std::endl; | 
 |  |  |     } | 
 |  |  |     std::cout << "Buy side: " << this->bidSide.size() << std::endl; | 
 |  |  |     std::vector<Level> bidCopy(this->bidSide); | 
 |  |  |     count = 0; | 
 |  |  |     std::sort(bidCopy.begin(), bidCopy.end()); | 
 |  |  |     for (auto i = bidCopy.rbegin(); i != bidCopy.rend() && count < numOrders; i++, count++) { | 
 |  |  |         std::cout << *i << std::endl; | 
 |  |  |     } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | Book testBook(int orders, bool printBook) | 
 |  |  | { | 
 |  |  |     Book b = Book(); | 
 |  |  |     double time(1); | 
 |  |  |     for (int i = 1; i < orders; i++) { | 
 |  |  |     Order t(i, Buy, 10, time++, "a"); | 
 |  |  |     b.bid(t); | 
 |  |  |     } | 
 |  |  |     for (int i = orders + 1; i < 2 * orders; i++) { | 
 |  |  |     Order t(i, Sell, 10, time++, "b"); | 
 |  |  |     b.ask(t); | 
 |  |  |     } | 
 |  |  |     if (printBook) b.printBook(orders - 1); | 
 |  |  |     return b; | 
 |  |  | } | 
 |  |  | } // namespace book | 
 
 |  |  | 
 |  |  | #pragma once | 
 |  |  |  | 
 |  |  | #include <algorithm> | 
 |  |  | #include <chrono> | 
 |  |  | #include <cstddef> | 
 |  |  | #include <iostream> | 
 |  |  | #include <queue> | 
 |  |  | #include <string> | 
 |  |  | #include <vector> | 
 |  |  | #include <algorithm> | 
 |  |  |  | 
 |  |  | namespace book | 
 |  |  | { | 
 |  |  | enum OrderSideEnum { Buy, Sell }; | 
 |  |  | enum ProductTypeEnum { TEST, FUTURE, SPREAD, CALL, PUT }; | 
 |  |  |  | 
 |  |  | struct Order { | 
 |  |  |   double price; | 
 |  |  |   OrderSideEnum side; | 
 |  |  |   int remaining_volume; | 
 |  |  |   int filled_volume; | 
 |  |  |   std::chrono::nanoseconds timestamp; | 
 |  |  |   std::string id; | 
 |  |  |   Order(double price, OrderSideEnum side, int volume, | 
 |  |  |         std::chrono::nanoseconds timestamp, std::string id); | 
 |  |  |     double price; | 
 |  |  |     OrderSideEnum side; | 
 |  |  |     int remaining_volume; | 
 |  |  |     int filled_volume; | 
 |  |  |     double timestamp; | 
 |  |  |     std::string id; | 
 |  |  |     Order(double price, OrderSideEnum side, int volume, double timestamp, | 
 |  |  |           std::string id); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct Level { | 
 |  |  |   double price; | 
 |  |  |   int volume; | 
 |  |  |   OrderSideEnum side; | 
 |  |  |   std::chrono::nanoseconds timestamp; | 
 |  |  |   std::string id; | 
 |  |  |     double price; | 
 |  |  |     int volume; | 
 |  |  |     OrderSideEnum side; | 
 |  |  |     double timestamp; | 
 |  |  |     std::string id; | 
 |  |  |  | 
 |  |  |   Level(Order &order); | 
 |  |  |     Level(Order& order); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | bool operator>(const Level &a, const Level &b); | 
 |  |  | bool operator<(const Level &a, const Level &b); | 
 |  |  | bool operator>=(const Level &a, const Level &b); | 
 |  |  | bool operator<=(const Level &a, const Level &b); | 
 |  |  | bool operator==(const Level &a, const Level &b); | 
 |  |  | bool operator>(const Level& a, const Level& b); | 
 |  |  | bool operator<(const Level& a, const Level& b); | 
 |  |  | bool operator>=(const Level& a, const Level& b); | 
 |  |  | bool operator<=(const Level& a, const Level& b); | 
 |  |  | bool operator==(const Level& a, const Level& b); | 
 |  |  | std::ostream& operator<<(std::ostream& out, const Level& a); | 
 |  |  |  | 
 |  |  | template <class T> | 
 |  |  | struct Side : public std::priority_queue<Level, std::vector<Level>, T> { | 
 |  |  | public: | 
 |  |  |     void deleteLevel(std::string orderId); | 
 |  |  |     void topRemoveVolume(int volume); | 
 |  |  |     void printTop(std::size_t num = 5); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | using AskSide = Side<std::greater<Level>>; | 
 |  |  | using BidSide = Side<std::less<Level>>; | 
 |  |  |  | 
 |  |  | struct Book { | 
 |  |  |   BidSide bidSide; | 
 |  |  |   AskSide askSide; | 
 |  |  |   ProductTypeEnum productType; | 
 |  |  |   std::string product; | 
 |  |  |   std::string stationId; | 
 |  |  |   std::string unit; | 
 |  |  |   std::chrono::nanoseconds expiry; | 
 |  |  |   double aggFee; | 
 |  |  |   double pasFee; | 
 |  |  |   double broFee; | 
 |  |  |     std::vector<Level> bidSide; | 
 |  |  |     std::vector<Level> askSide; | 
 |  |  |     ProductTypeEnum productType; | 
 |  |  |     std::string product; | 
 |  |  |     std::string stationId; | 
 |  |  |     std::string unit; | 
 |  |  |     std::chrono::nanoseconds expiry; | 
 |  |  |     double aggFee; | 
 |  |  |     double pasFee; | 
 |  |  |     double broFee; | 
 |  |  |  | 
 |  |  |   Book(); | 
 |  |  |   Book(ProductTypeEnum productType, std::string product, std::string stationId, | 
 |  |  |        std::string unit, std::chrono::nanoseconds expiry, double aggFee, | 
 |  |  |        double pasFee, double broFee); | 
 |  |  |   void ask(Order &order); | 
 |  |  |   void bid(Order &order); | 
 |  |  |     Book(); | 
 |  |  |     Book(ProductTypeEnum productType, std::string product, | 
 |  |  |          std::string stationId, std::string unit, | 
 |  |  |          std::chrono::nanoseconds expiry, double aggFee, double pasFee, | 
 |  |  |          double broFee); | 
 |  |  |     void ask(Order& order); | 
 |  |  |     void bid(Order& order); | 
 |  |  |     void printBook(std::size_t numOrders = 10); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | Book testBook(int orders = 10, bool printBook = true); | 
 |  |  | } // namespace book | 
 
| New file | 
 |  |  | 
 |  |  | #include "strat.hpp" | 
 |  |  |  | 
 |  |  | int main(void) | 
 |  |  | { | 
 |  |  |      | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  | #include "json.hpp" | 
 |  |  | #include "protocol.hpp" | 
 |  |  |  | 
 |  |  | #include <cstdlib> | 
 |  |  | #include <getopt.h> | 
 |  |  | #include <iostream> | 
 |  |  | #include <unordered_map> | 
 |  |  |  | 
 |  |  | enum clickType { Buy, Sell, Flash }; | 
 |  |  |  | 
 |  |  | static std::unordered_map<std::string, clickType> mapClick; | 
 |  |  |  | 
 |  |  | void initialise() | 
 |  |  | { | 
 |  |  |     mapClick = {{"BUY", Buy}, {"SELL", Sell}, {"FLASH", Flash}, | 
 |  |  |                 {"b", Buy},   {"s", Sell},    {"f", Flash}, | 
 |  |  |                 {"B", Buy},   {"S", Sell},    {"F", Flash}}; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void usage() | 
 |  |  | { | 
 |  |  |     std::cout << "DESCRIPTION" << std::endl | 
 |  |  |           << "Click trader using same algs" << std::endl | 
 |  |  |           << std::endl | 
 |  |  |           << "USAGE" << std::endl | 
 |  |  |           << "\t-a product" << std::endl | 
 |  |  |           << "\t-t click type (buy, sell, flash)" << std::endl | 
 |  |  |           << "\t-p price" << std::endl | 
 |  |  |           << "\t-v volume" << std::endl | 
 |  |  |           << "\t-i id" << std::endl | 
 |  |  |           << "Always need product, need side, price and volume for " | 
 |  |  |          "adding/flash, need id for deleting" | 
 |  |  |           << std::endl; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | int main(int argc, char** argv) | 
 |  |  | { | 
 |  |  |     int c; | 
 |  |  |     int index; | 
 |  |  |     std::string product, id; | 
 |  |  |     double price; | 
 |  |  |     clickType click; | 
 |  |  |     uint64_t volume; | 
 |  |  |     initialise(); | 
 |  |  |     if (argc == 1) { | 
 |  |  |     usage(), exit(0); | 
 |  |  |     } | 
 |  |  |     while ((c = getopt(argc, argv, "a::t::p::v::i::")) != -1) { | 
 |  |  |     switch (c) { | 
 |  |  |     case 'a': | 
 |  |  |         product = std::string(optarg); | 
 |  |  |         break; | 
 |  |  |     case 's': | 
 |  |  |         click = mapClick[optarg]; | 
 |  |  |         break; | 
 |  |  |     case 'p': | 
 |  |  |         price = std::stod(optarg); | 
 |  |  |         break; | 
 |  |  |     case 'v': | 
 |  |  |         volume = std::stoll(optarg); | 
 |  |  |         break; | 
 |  |  |     case 'i': | 
 |  |  |         id = std::string(optarg); | 
 |  |  |         break; | 
 |  |  |     case '?': | 
 |  |  |     default: | 
 |  |  |         usage(); | 
 |  |  |         exit(0); | 
 |  |  |     } | 
 |  |  |     } | 
 |  |  |     switch (click) { | 
 |  |  |     case Buy: | 
 |  |  |     case Sell: | 
 |  |  |     case Flash:; | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | Subproject commit 11e02e901cb9078f814903493359281ad4064ed5 | 
 
| New file | 
 |  |  | 
 |  |  | Subproject commit 655b249b8f463f690c53a19d6b4110297699e3c5 | 
 
| New file | 
 |  |  | 
 |  |  | #include "json.hpp" | 
 |  |  | #include "book.hpp" | 
 |  |  | #include "date/include/date/date.h" | 
 |  |  | #include "protocol.hpp" | 
 |  |  | #include <chrono> | 
 |  |  | #include <cstddef> | 
 |  |  | #include <cstdint> | 
 |  |  | #include <cstring> | 
 |  |  | #include <deque> | 
 |  |  | #include <iomanip> | 
 |  |  | #include <netdb.h> | 
 |  |  | #include <numeric> | 
 |  |  | #include <queue> | 
 |  |  | #include <sstream> | 
 |  |  | #include <string> | 
 |  |  | #include <unordered_map> | 
 |  |  | #include <utility> | 
 |  |  |  | 
 |  |  | namespace json | 
 |  |  | { | 
 |  |  | static std::unordered_map<std::string, MessageTypes> mapTypes; | 
 |  |  | static std::unordered_map<MessageTypes, book::ProductTypeEnum> mapAnnounce; | 
 |  |  | static std::unordered_map<std::string, book::OrderSideEnum> mapOrder; | 
 |  |  | static std::unordered_map<std::string, TradeTypeEnum> mapTrade; | 
 |  |  | static std::unordered_map<book::OrderSideEnum, std::string> mapOrderSide; | 
 |  |  |  | 
 |  |  | void initialise() | 
 |  |  | { | 
 |  |  |     mapTypes = {{"FUTURE", FUTURE_TYPE}, | 
 |  |  |                 {"SPREAD", SPREAD_TYPE}, | 
 |  |  |                 {"CALL", CALL_TYPE}, | 
 |  |  |                 {"PUT", PUT_TYPE}, | 
 |  |  |                 {"SETTLEMENT", SETTLEMENT}, | 
 |  |  |                 {"ADDED", ADDED}, | 
 |  |  |                 {"DELETED", DELETED}, | 
 |  |  |                 {"TRADE", TRADE}, | 
 |  |  |                 {"BROKER_REQUEST", BROKER_REQUEST}, | 
 |  |  |                 {"BROKER_ACK", BROKER_ACK}, | 
 |  |  |                 {"BROKER_CONFIRM", BROKER_CONFIRM}}; | 
 |  |  |  | 
 |  |  |     mapAnnounce = {{FUTURE_TYPE, book::FUTURE}, | 
 |  |  |                    {SPREAD_TYPE, book::SPREAD}, | 
 |  |  |                    {CALL_TYPE, book::CALL}, | 
 |  |  |                    {PUT_TYPE, book::PUT}}; | 
 |  |  |  | 
 |  |  |     mapOrder = {{"BUY", book::Buy}, {"SELL", book::Sell}}; | 
 |  |  |  | 
 |  |  |     mapTrade = {{"BUY_AGGRESSOR", BUY_AGGRESSOR}, | 
 |  |  |                 {"SELL_AGGRESSOR", SELL_AGGRESSOR}}; | 
 |  |  |  | 
 |  |  |     mapOrderSide = {{book::Buy, "BUY"}, {book::Sell, "SELL"}}; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | AnnounceMessage* announce(std::string& str); | 
 |  |  | SettleMessage* settle(std::string& str); | 
 |  |  | AddedMessage* added(std::string& str); | 
 |  |  | DeletedMessage* deleted(std::string& str); | 
 |  |  | TradeMessage* trade(std::string& str); | 
 |  |  | BrokerRequest* brokerReq(std::string& str); | 
 |  |  | BrokerAck* brokerAck(std::string& str); | 
 |  |  | BrokerConfirm* brokerCon(std::string& str); | 
 |  |  |  | 
 |  |  | std::queue<Message*> parseMany(std::string& str) | 
 |  |  | { | 
 |  |  |     std::queue<Message*> out; | 
 |  |  |     std::size_t startIndex = 0, endIndex = 0; | 
 |  |  |     while (true) { | 
 |  |  |     startIndex = str.find("{", endIndex); | 
 |  |  |     if (startIndex == std::string::npos) break; | 
 |  |  |     endIndex = str.find("},", startIndex); | 
 |  |  |     std::string substr = str.substr(startIndex, endIndex - startIndex + 1); | 
 |  |  |     // std::cout << substr << std::endl; | 
 |  |  |     Message* a = parseSingle(substr); | 
 |  |  |     out.push(a); | 
 |  |  |     } | 
 |  |  |     return out; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | Message* parseSingle(std::string& str) | 
 |  |  | { | 
 |  |  |     if (mapTypes.empty()) { | 
 |  |  |     initialise(); | 
 |  |  |     } | 
 |  |  |     std::size_t startIndex = str.find("\"type\": \"") + 9; | 
 |  |  |     std::size_t endIndex = str.find("\"", startIndex + 1); | 
 |  |  |     Message* out; | 
 |  |  |     switch (mapTypes[str.substr(startIndex, endIndex - startIndex)]) { | 
 |  |  |     case FUTURE_TYPE: | 
 |  |  |     case SPREAD_TYPE: | 
 |  |  |     case CALL_TYPE: | 
 |  |  |     case PUT_TYPE: | 
 |  |  |     out = announce(str); | 
 |  |  |     break; | 
 |  |  |     case SETTLEMENT: | 
 |  |  |     out = settle(str); | 
 |  |  |     break; | 
 |  |  |     case ADDED: | 
 |  |  |     out = added(str); | 
 |  |  |     break; | 
 |  |  |     case DELETED: | 
 |  |  |     out = deleted(str); | 
 |  |  |     break; | 
 |  |  |     case TRADE: | 
 |  |  |     out = trade(str); | 
 |  |  |     break; | 
 |  |  |     case BROKER_REQUEST: | 
 |  |  |     out = brokerReq(str); | 
 |  |  |     break; | 
 |  |  |     case BROKER_ACK: | 
 |  |  |     out = brokerAck(str); | 
 |  |  |     break; | 
 |  |  |     case BROKER_CONFIRM: | 
 |  |  |     out = brokerCon(str); | 
 |  |  |     break; | 
 |  |  |     default: | 
 |  |  |     out = new Message(NONE, ""); | 
 |  |  |     break; | 
 |  |  |     } | 
 |  |  |     return out; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | inline std::pair<std::size_t, std::size_t> | 
 |  |  | find_arg(std::string str, std::string a, bool quotes, bool end = false) | 
 |  |  | { | 
 |  |  |     std::size_t out[2]; | 
 |  |  |     if (quotes) { | 
 |  |  |     out[0] = str.find("\"" + a + "\": \"") + 5 + a.size(); | 
 |  |  |     if (end) { | 
 |  |  |         out[1] = str.find("\"}", out[0] + 1); | 
 |  |  |     } else { | 
 |  |  |         out[1] = str.find("\",", out[0] + 1); | 
 |  |  |     } | 
 |  |  |     } else { | 
 |  |  |     out[0] = str.find("\"" + a + "\": ") + 4 + a.size(); | 
 |  |  |     if (end) { | 
 |  |  |         out[1] = str.find("}", out[0] + 1); | 
 |  |  |     } else { | 
 |  |  |         out[1] = str.find(",", out[0] + 1); | 
 |  |  |     } | 
 |  |  |     } | 
 |  |  |     return std::make_pair(out[0], out[1]); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | AnnounceMessage* announce(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, stationId, stationName, | 
 |  |  |     unit, expiry, aggFee, pasFee, broFee, sequence, timestamp; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     stationId = find_arg(str, "stationId", false, false); | 
 |  |  |     stationName = find_arg(str, "stationName", true, false); | 
 |  |  |     unit = find_arg(str, "unit", true, false); | 
 |  |  |     expiry = find_arg(str, "expiry", true, false); | 
 |  |  |     aggFee = find_arg(str, "aggressiveFee", false, false); | 
 |  |  |     pasFee = find_arg(str, "passiveFee", false, false); | 
 |  |  |     broFee = find_arg(str, "brokerFee", false, false); | 
 |  |  |     sequence = find_arg(str, "sequence", false, false); | 
 |  |  |     timestamp = find_arg(str, "timestamp", false, true); | 
 |  |  |     std::stringstream expiryStream( | 
 |  |  |     str.substr(expiry.first, expiry.second - expiry.first)); | 
 |  |  |     std::chrono::nanoseconds exp_time; | 
 |  |  |     expiryStream >> | 
 |  |  |     date::parse("%Y-%m-%f %H:%M%z", exp_time); // Parsing is broken | 
 |  |  |     return new AnnounceMessage( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     str.substr(stationId.first, stationId.second - stationId.first), | 
 |  |  |     str.substr(stationName.first, stationName.second - stationName.first), | 
 |  |  |     str.substr(unit.first, unit.second - unit.first), exp_time, | 
 |  |  |     std::stod(str.substr(aggFee.first, aggFee.second - aggFee.first)), | 
 |  |  |     std::stod(str.substr(pasFee.first, pasFee.second - pasFee.first)), | 
 |  |  |     std::stod(str.substr(broFee.first, broFee.second - broFee.first)), | 
 |  |  |     std::stoll( | 
 |  |  |         str.substr(sequence.first, sequence.second - sequence.first)), | 
 |  |  |     std::stod( | 
 |  |  |         str.substr(timestamp.first, timestamp.second - timestamp.first))); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | SettleMessage* settle(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, stationName, expiry, | 
 |  |  |     price, sequence, timestamp; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     stationName = find_arg(str, "stationName", true, false); | 
 |  |  |     expiry = find_arg(str, "expiry", true, false); | 
 |  |  |     price = find_arg(str, "price", false, false); | 
 |  |  |     sequence = find_arg(str, "sequence", false, false); | 
 |  |  |     timestamp = find_arg(str, "timestamp", false, true); | 
 |  |  |     std::stringstream expiryStream( | 
 |  |  |     str.substr(expiry.first, expiry.second - expiry.first)); | 
 |  |  |     std::chrono::nanoseconds exp_time; | 
 |  |  |     expiryStream >> date::parse("%Y-%m-%d %H:%M%z", exp_time); | 
 |  |  |     return new SettleMessage( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     str.substr(stationName.first, stationName.second - stationName.first), | 
 |  |  |     exp_time, | 
 |  |  |     std::stod(str.substr(price.first, price.second - price.first)), | 
 |  |  |     std::stoll( | 
 |  |  |         str.substr(sequence.first, sequence.second - sequence.first)), | 
 |  |  |     std::stod( | 
 |  |  |         str.substr(timestamp.first, timestamp.second - timestamp.first))); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | AddedMessage* added(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, id, side, price, filled, | 
 |  |  |     resting, sequence, timestamp; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     sequence = find_arg(str, "sequence", false, false); | 
 |  |  |     timestamp = find_arg(str, "timestamp", false, true); | 
 |  |  |     id = find_arg(str, "id", true, false); | 
 |  |  |     side = find_arg(str, "side", true, false); | 
 |  |  |     price = find_arg(str, "price", false, false); | 
 |  |  |     filled = find_arg(str, "filled", false, false); | 
 |  |  |     resting = find_arg(str, "resting", false, false); | 
 |  |  |     return new AddedMessage( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     str.substr(id.first, id.second - id.first), | 
 |  |  |     mapOrder[str.substr(side.first, side.second - side.first)], | 
 |  |  |     std::stod(str.substr(price.first, price.second - price.first)), | 
 |  |  |     std::stoll(str.substr(filled.first, filled.second - filled.first)), | 
 |  |  |     std::stoll(str.substr(resting.first, resting.second - resting.first)), | 
 |  |  |     std::stoll( | 
 |  |  |         str.substr(sequence.first, sequence.second - sequence.first)), | 
 |  |  |     std::stod( | 
 |  |  |         str.substr(timestamp.first, timestamp.second - timestamp.first))); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | DeletedMessage* deleted(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, id, side, sequence, | 
 |  |  |     timestamp; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     sequence = find_arg(str, "sequence", false, false); | 
 |  |  |     timestamp = find_arg(str, "timestamp", false, true); | 
 |  |  |     id = find_arg(str, "id", true, false); | 
 |  |  |     side = find_arg(str, "side", true, false); | 
 |  |  |     return new DeletedMessage( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     str.substr(id.first, id.second - id.first), | 
 |  |  |     mapOrder[str.substr(side.first, side.second - side.first)], | 
 |  |  |     std::stoll( | 
 |  |  |         str.substr(sequence.first, sequence.second - sequence.first)), | 
 |  |  |     std::stod( | 
 |  |  |         str.substr(timestamp.first, timestamp.second - timestamp.first))); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | TradeMessage* trade(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, price, volume, buyer, | 
 |  |  |     seller, tradeType, passiveOrder, passiveOrderRemaining, sequence, | 
 |  |  |     timestamp; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     sequence = find_arg(str, "sequence", false, false); | 
 |  |  |     timestamp = find_arg(str, "timestamp", false, true); | 
 |  |  |     price = find_arg(str, "price", false, false); | 
 |  |  |     volume = find_arg(str, "volume", false, false); | 
 |  |  |     buyer = find_arg(str, "buyer", true, false); | 
 |  |  |     seller = find_arg(str, "seller", true, false); | 
 |  |  |     tradeType = find_arg(str, "tradeType", true, false); | 
 |  |  |     passiveOrder = find_arg(str, "passiveOrder", true, false); | 
 |  |  |     passiveOrderRemaining = | 
 |  |  |     find_arg(str, "passiveOrderRemaining", false, false); | 
 |  |  |  | 
 |  |  |     return new TradeMessage( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     std::stod(str.substr(price.first, price.second - price.first)), | 
 |  |  |     std::stoll(str.substr(volume.first, volume.second - volume.first)), | 
 |  |  |     str.substr(buyer.first, buyer.second - buyer.first), | 
 |  |  |     str.substr(seller.first, seller.second - seller.first), | 
 |  |  |     mapTrade[str.substr(tradeType.first, | 
 |  |  |                             tradeType.second - tradeType.first)], | 
 |  |  |     str.substr(passiveOrder.first, | 
 |  |  |                    passiveOrder.second - passiveOrder.first), | 
 |  |  |     std::stoll(str.substr(passiveOrderRemaining.first, | 
 |  |  |                               passiveOrderRemaining.second - | 
 |  |  |                                   passiveOrderRemaining.first)), | 
 |  |  |     std::stoll( | 
 |  |  |         str.substr(sequence.first, sequence.second - sequence.first)), | 
 |  |  |     std::stod( | 
 |  |  |         str.substr(timestamp.first, timestamp.second - timestamp.first))); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | BrokerRequest* brokerReq(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, price, side, volume, | 
 |  |  |     counterparty; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     price = find_arg(str, "price", false, false); | 
 |  |  |     side = find_arg(str, "side", true, false); | 
 |  |  |     volume = find_arg(str, "volume", false, false); | 
 |  |  |     counterparty = find_arg(str, "counterparty", true, false); | 
 |  |  |     return new BrokerRequest( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     std::stod(str.substr(price.first, price.second - price.first)), | 
 |  |  |     mapOrder[str.substr(side.first, side.second - side.first)], | 
 |  |  |     std::stoll(str.substr(volume.first, volume.second - volume.first)), | 
 |  |  |     str.substr(counterparty.first, | 
 |  |  |                    counterparty.second - counterparty.first)); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | BrokerAck* brokerAck(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, price, side, volume, | 
 |  |  |     counterparty, id, brokerTradeStatus, owner; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     price = find_arg(str, "price", false, false); | 
 |  |  |     side = find_arg(str, "side", true, false); | 
 |  |  |     volume = find_arg(str, "volume", false, false); | 
 |  |  |     counterparty = find_arg(str, "counterparty", true, false); | 
 |  |  |     id = find_arg(str, "id", true, false); | 
 |  |  |     brokerTradeStatus = find_arg(str, "brokerTradeStatus", true, false); | 
 |  |  |     owner = find_arg(str, "owner", true, false); | 
 |  |  |  | 
 |  |  |     return new BrokerAck( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     std::stod(str.substr(price.first, price.second - price.first)), | 
 |  |  |     mapOrder[str.substr(side.first, side.second - side.first)], | 
 |  |  |     std::stoll(str.substr(volume.first, volume.second - volume.first)), | 
 |  |  |     str.substr(counterparty.first, | 
 |  |  |                    counterparty.second - counterparty.first), | 
 |  |  |     str.substr(id.first, id.second - id.first), | 
 |  |  |     str.substr(brokerTradeStatus.first, | 
 |  |  |                    brokerTradeStatus.second - brokerTradeStatus.first), | 
 |  |  |     str.substr(owner.first, owner.second - owner.first)); | 
 |  |  | } | 
 |  |  | BrokerConfirm* brokerCon(std::string& str) | 
 |  |  | { | 
 |  |  |     std::pair<std::size_t, std::size_t> type, product, price, side, volume, | 
 |  |  |     counterparty, id; | 
 |  |  |     type = find_arg(str, "type", true, false); | 
 |  |  |     product = find_arg(str, "product", true, false); | 
 |  |  |     price = find_arg(str, "price", false, false); | 
 |  |  |     side = find_arg(str, "side", true, false); | 
 |  |  |     volume = find_arg(str, "volume", false, false); | 
 |  |  |     counterparty = find_arg(str, "counterparty", true, false); | 
 |  |  |     id = find_arg(str, "id", true, false); | 
 |  |  |  | 
 |  |  |     return new BrokerConfirm( | 
 |  |  |     mapTypes[str.substr(type.first, type.second - type.first)], | 
 |  |  |     str.substr(product.first, product.second - product.first), | 
 |  |  |     std::stod(str.substr(price.first, price.second - price.first)), | 
 |  |  |     mapOrder[str.substr(side.first, side.second - side.first)], | 
 |  |  |     std::stoll(str.substr(volume.first, volume.second - volume.first)), | 
 |  |  |     str.substr(counterparty.first, | 
 |  |  |                    counterparty.second - counterparty.first), | 
 |  |  |     str.substr(id.first, id.second - id.first)); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | Message::Message() : type(NONE), product("error") {} | 
 |  |  |  | 
 |  |  | Message::Message(MessageTypes types, std::string product) | 
 |  |  |     : type(types), product(product) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | FromExchange::FromExchange(MessageTypes type, std::string product, | 
 |  |  |                            uint64_t sequence, double timestamp) | 
 |  |  |     : Message(type, product), sequence(sequence), timestamp(timestamp) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | ToExchange::ToExchange(MessageTypes type, std::string product) | 
 |  |  |     : Message(type, product){}; | 
 |  |  |  | 
 |  |  | Broker::Broker(MessageTypes type, std::string product, double price, | 
 |  |  |                book::OrderSideEnum side, uint64_t volume, | 
 |  |  |                std::string counterparty) | 
 |  |  |     : Message(type, product), price(price), side(side), volume(volume), | 
 |  |  |       counterparty(counterparty) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | AnnounceMessage::AnnounceMessage(MessageTypes type, std::string product, | 
 |  |  |                                  std::string stationId, std::string stationName, | 
 |  |  |                                  std::string unit, | 
 |  |  |                                  std::chrono::nanoseconds expiry, double aggFee, | 
 |  |  |                                  double pasFee, double broFee, | 
 |  |  |                                  uint64_t sequence, double timestamp) | 
 |  |  |     : FromExchange(type, product, sequence, timestamp), stationId(stationId), | 
 |  |  |       stationName(stationName), unit(unit), expiry(expiry), aggFee(aggFee), | 
 |  |  |       pasFee(pasFee), broFee(broFee) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | SettleMessage::SettleMessage(MessageTypes type, std::string product, | 
 |  |  |                              std::string stationName, | 
 |  |  |                              std::chrono::nanoseconds expiry, double price, | 
 |  |  |                              uint64_t sequence, double timestamp) | 
 |  |  |     : FromExchange(type, product, sequence, timestamp), | 
 |  |  |       stationName(stationName), expiry(expiry), price(price) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | AddMessage::AddMessage(MessageTypes type, std::string product, double price, | 
 |  |  |                        book::OrderSideEnum side, uint64_t volume) | 
 |  |  |     : ToExchange(type, product), price(price), side(side), volume(volume) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | std::string AddMessage::as_string() | 
 |  |  | { | 
 |  |  |     if (mapOrderSide.empty()) initialise(); | 
 |  |  |     return "{\"type\": \"ADD\", \"product\": \"" + this->product + | 
 |  |  |            "\", \"price\": " + std::to_string(this->price) + ", \"side\": \"" + | 
 |  |  |            mapOrderSide[this->side] + | 
 |  |  |            "\", \"volume\": " + std::to_string(this->volume) + "}"; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | AddedMessage::AddedMessage(MessageTypes type, std::string product, | 
 |  |  |                            std::string id, book::OrderSideEnum side, | 
 |  |  |                            double price, uint64_t filled, uint64_t resting, | 
 |  |  |                            uint64_t sequence, double timestamp) | 
 |  |  |     : FromExchange(type, product, sequence, timestamp), id(id), side(side), | 
 |  |  |       price(price), filled(filled), resting(resting) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | DeleteMessage::DeleteMessage(MessageTypes type, std::string product, | 
 |  |  |                              std::string id) | 
 |  |  |     : ToExchange(type, product), id(id) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | std::string DeleteMessage::as_string() | 
 |  |  | { | 
 |  |  |     if (mapOrderSide.empty()) initialise(); | 
 |  |  |     return "{\"type\": \"DELETE\", \"product\": \"" + this->product + | 
 |  |  |            "\", \"id\": \"" + this->id + "\"}"; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | DeletedMessage::DeletedMessage(MessageTypes type, std::string product, | 
 |  |  |                                std::string id, book::OrderSideEnum side, | 
 |  |  |                                uint64_t sequence, double timestamp) | 
 |  |  |     : FromExchange(type, product, sequence, timestamp), id(id), side(side) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | RejectMessage::RejectMessage(MessageTypes type, std::string product, | 
 |  |  |                              std::string error, uint64_t sequence, | 
 |  |  |                              double timestamp) | 
 |  |  |     : FromExchange(type, product, sequence, timestamp), error(error) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | TradeMessage::TradeMessage(MessageTypes type, std::string product, double price, | 
 |  |  |                            uint64_t volume, std::string buyer, | 
 |  |  |                            std::string seller, TradeTypeEnum tradeType, | 
 |  |  |                            std::string passiveOrder, | 
 |  |  |                            uint64_t passiveOrderRemaining, uint64_t sequence, | 
 |  |  |                            double timestamp) | 
 |  |  |     : FromExchange(type, product, sequence, timestamp), price(price), | 
 |  |  |       volume(volume), buyer(buyer), seller(seller), tradeType(tradeType), | 
 |  |  |       passiveOrder(passiveOrder), passiveOrderRemaining(passiveOrderRemaining) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | BrokerRequest::BrokerRequest(MessageTypes type, std::string product, | 
 |  |  |                              double price, book::OrderSideEnum side, | 
 |  |  |                              uint64_t volume, std::string counterparty) | 
 |  |  |     : Broker(type, product, price, side, volume, counterparty) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | BrokerAck::BrokerAck(MessageTypes type, std::string product, double price, | 
 |  |  |                      book::OrderSideEnum side, uint64_t volume, | 
 |  |  |                      std::string counterparty, std::string id, | 
 |  |  |                      std::string brokerTradeStatus, std::string owner) | 
 |  |  |     : Broker(type, product, price, side, volume, counterparty), id(id), | 
 |  |  |       brokerTradeStatus(brokerTradeStatus), owner(owner) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | BrokerConfirm::BrokerConfirm(MessageTypes type, std::string product, | 
 |  |  |                              double price, book::OrderSideEnum side, | 
 |  |  |                              uint64_t volume, std::string counterparty, | 
 |  |  |                              std::string id) | 
 |  |  |     : Broker(type, product, price, side, volume, counterparty), id(id) | 
 |  |  | { | 
 |  |  | } | 
 |  |  | } // namespace json | 
 
| New file | 
 |  |  | 
 |  |  | #pragma once | 
 |  |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  |  | 
 |  |  | #include <chrono> | 
 |  |  | #include <cstdint> | 
 |  |  | #include <ostream> | 
 |  |  | #include <queue> | 
 |  |  | #include <unordered_map> | 
 |  |  |  | 
 |  |  | namespace json | 
 |  |  | { | 
 |  |  | enum MessageTypes { | 
 |  |  |     FUTURE_TYPE, | 
 |  |  |     SPREAD_TYPE, | 
 |  |  |     CALL_TYPE, | 
 |  |  |     PUT_TYPE, | 
 |  |  |     SETTLEMENT, | 
 |  |  |     ADD, | 
 |  |  |     ADDED, | 
 |  |  |     DELETE, | 
 |  |  |     DELETED, | 
 |  |  |     REJECT, | 
 |  |  |     TRADE, | 
 |  |  |     BROKER_REQUEST, | 
 |  |  |     BROKER_ACK, | 
 |  |  |     BROKER_CONFIRM, | 
 |  |  |     NONE | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | enum TradeTypeEnum { BUY_AGGRESSOR, SELL_AGGRESSOR }; | 
 |  |  |  | 
 |  |  | struct Message { | 
 |  |  |     MessageTypes type; | 
 |  |  |     std::string product; | 
 |  |  |     Message(MessageTypes type, std::string product); | 
 |  |  |     Message(); | 
 |  |  |     virtual ~Message() = default; | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct FromExchange : public Message { | 
 |  |  |     uint64_t sequence; | 
 |  |  |     double timestamp; | 
 |  |  |     FromExchange(MessageTypes type, std::string product, uint64_t sequence, | 
 |  |  |                  double timestamp); | 
 |  |  |     virtual ~FromExchange() = default; | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct ToExchange : public Message { | 
 |  |  |     ToExchange(MessageTypes type, std::string product); | 
 |  |  |     virtual ~ToExchange() = default; | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct Broker : public Message { | 
 |  |  |     double price; | 
 |  |  |     book::OrderSideEnum side; | 
 |  |  |     uint64_t volume; | 
 |  |  |     std::string counterparty; | 
 |  |  |     Broker(MessageTypes type, std::string product, double price, | 
 |  |  |            book::OrderSideEnum side, uint64_t volume, std::string counterparty); | 
 |  |  |     virtual ~Broker() = default; | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct AnnounceMessage : public FromExchange { | 
 |  |  |     std::string stationId; | 
 |  |  |     std::string stationName; | 
 |  |  |     std::string unit; | 
 |  |  |     std::chrono::nanoseconds expiry; | 
 |  |  |     double aggFee; | 
 |  |  |     double pasFee; | 
 |  |  |     double broFee; | 
 |  |  |  | 
 |  |  |     AnnounceMessage(MessageTypes type, std::string product, | 
 |  |  |                     std::string stationId, std::string stationName, | 
 |  |  |                     std::string unit, std::chrono::nanoseconds expiry, | 
 |  |  |                     double aggFee, double pasFee, double broFee, | 
 |  |  |                     uint64_t sequence, double timestamp); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct SettleMessage : public FromExchange { | 
 |  |  |     std::string stationName; | 
 |  |  |     std::chrono::nanoseconds expiry; | 
 |  |  |     double price; | 
 |  |  |     SettleMessage(MessageTypes type, std::string product, | 
 |  |  |                   std::string stationName, std::chrono::nanoseconds expiry, | 
 |  |  |                   double price, uint64_t sequence, double timestamp); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct AddMessage : public ToExchange { | 
 |  |  |     double price; | 
 |  |  |     book::OrderSideEnum side; | 
 |  |  |     uint64_t volume; | 
 |  |  |     AddMessage(MessageTypes type, std::string product, double price, | 
 |  |  |                book::OrderSideEnum side, uint64_t volume); | 
 |  |  |     std::string as_string(); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct AddedMessage : public FromExchange { | 
 |  |  |     std::string id; | 
 |  |  |     book::OrderSideEnum side; | 
 |  |  |     double price; | 
 |  |  |     uint64_t filled; | 
 |  |  |     uint64_t resting; | 
 |  |  |     AddedMessage(MessageTypes type, std::string product, std::string id, | 
 |  |  |                  book::OrderSideEnum side, double price, uint64_t filled, | 
 |  |  |                  uint64_t resting, uint64_t sequence, double timestamp); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct DeleteMessage : public ToExchange { | 
 |  |  |     std::string id; | 
 |  |  |     DeleteMessage(MessageTypes type, std::string product, std::string id); | 
 |  |  |     std::string as_string(); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct DeletedMessage : public FromExchange { | 
 |  |  |     std::string id; | 
 |  |  |     book::OrderSideEnum side; | 
 |  |  |     DeletedMessage(MessageTypes type, std::string product, std::string id, | 
 |  |  |                    book::OrderSideEnum side, uint64_t sequence, | 
 |  |  |                    double timestamp); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct RejectMessage : public FromExchange { | 
 |  |  |     std::string error; | 
 |  |  |     RejectMessage(MessageTypes type, std::string product, std::string error, | 
 |  |  |                   uint64_t sequence, double timestamp); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct TradeMessage : public FromExchange { | 
 |  |  |     double price; | 
 |  |  |     uint64_t volume; | 
 |  |  |     std::string buyer; | 
 |  |  |     std::string seller; | 
 |  |  |     TradeTypeEnum tradeType; | 
 |  |  |     std::string passiveOrder; | 
 |  |  |     uint64_t passiveOrderRemaining; | 
 |  |  |     TradeMessage(MessageTypes type, std::string product, double price, | 
 |  |  |                  uint64_t volume, std::string buyer, std::string seller, | 
 |  |  |                  TradeTypeEnum tradeType, std::string passiveOrder, | 
 |  |  |                  uint64_t passiveOrderRemaining, uint64_t sequence, | 
 |  |  |                  double timestamp); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct BrokerRequest : public Broker { | 
 |  |  |     BrokerRequest(MessageTypes type, std::string product, double price, | 
 |  |  |                   book::OrderSideEnum side, uint64_t volume, | 
 |  |  |                   std::string counterparty); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct BrokerAck : public Broker { | 
 |  |  |     std::string id; | 
 |  |  |     std::string brokerTradeStatus; | 
 |  |  |     std::string owner; | 
 |  |  |     BrokerAck(MessageTypes type, std::string product, double price, | 
 |  |  |               book::OrderSideEnum side, uint64_t volume, | 
 |  |  |               std::string counterparty, std::string id, | 
 |  |  |               std::string brokerTradeStatus, std::string owner); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | struct BrokerConfirm : public Broker { | 
 |  |  |     std::string id; | 
 |  |  |     BrokerConfirm(MessageTypes type, std::string product, double price, | 
 |  |  |                   book::OrderSideEnum side, uint64_t volume, | 
 |  |  |                   std::string counterparty, std::string id); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | Message* parseSingle(std::string& str); | 
 |  |  | std::queue<Message*> parseMany(std::string& str); | 
 |  |  | } // namespace json | 
 
 |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  | #include "json.hpp" | 
 |  |  | #include "protocol.hpp" | 
 |  |  | #include <chrono> | 
 |  |  |  | 
 |  |  | int main(void) | 
 |  |  | { | 
 |  |  |     Book b = testBook(10, true); | 
 |  |  |     book::Book b = book::testBook(10, true); | 
 |  |  |     auto bs = protocol::recoverBook(); | 
 |  |  |     std::cout << bs.size() << std::endl; | 
 |  |  |     for (auto i : bs) { | 
 |  |  |         std::cout << i.first << std::endl; | 
 |  |  |         i.second.printBook(); | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | #include "protocol.hpp" | 
 |  |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  | #include "cpp-httplib/httplib.h" | 
 |  |  | #include "json.hpp" | 
 |  |  | #include "secrets.hpp" | 
 |  |  |  | 
 |  |  | #include <chrono> | 
 |  |  | #include <iostream> | 
 |  |  | #include <queue> | 
 |  |  | #include <sstream> | 
 |  |  | #include <string> | 
 |  |  | #include <unordered_map> | 
 |  |  |  | 
 |  |  | namespace protocol | 
 |  |  | { | 
 |  |  | static std::unordered_map<json::MessageTypes, book::ProductTypeEnum> | 
 |  |  |     mapAnnounce; | 
 |  |  | std::string server = std::string(HOST) + ":" + std::string(PORT); | 
 |  |  | httplib::Client cli("http://" + server); | 
 |  |  |  | 
 |  |  | void initialise() | 
 |  |  | { | 
 |  |  |     mapAnnounce = {{json::FUTURE_TYPE, book::FUTURE}, | 
 |  |  |                    {json::SPREAD_TYPE, book::SPREAD}, | 
 |  |  |                    {json::CALL_TYPE, book::CALL}, | 
 |  |  |                    {json::PUT_TYPE, book::PUT}}; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | std::unordered_map<std::string, book::Book> recoverBook() | 
 |  |  | { | 
 |  |  |     std::unordered_map<std::string, book::Book> bs; | 
 |  |  |     std::ifstream sampleFile("../rec.log"); | 
 |  |  |     std::stringstream ss; | 
 |  |  |     ss << sampleFile.rdbuf(); | 
 |  |  |     // httplib::Client cli("http://" + server); | 
 |  |  |     // auto res = cli.Get("/recover"); | 
 |  |  |     std::string l; | 
 |  |  |     l = ss.str(); | 
 |  |  |     std::queue<json::Message*> a(json::parseMany(l)); | 
 |  |  |     while (!a.empty()) { | 
 |  |  |     protocol::handleMessage(bs, a.front()); | 
 |  |  |     delete a.front(); | 
 |  |  |     a.pop(); | 
 |  |  |     } | 
 |  |  |     return bs; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void addOrder(json::AddMessage& order) | 
 |  |  | { | 
 |  |  |     std::string message = "{\"message\": " + order.as_string() + ", " + | 
 |  |  |                           "\"username\": \"" + std::string(USER) + | 
 |  |  |                           "\", \"password\": \"" + std::string(PASS) + "\"}"; | 
 |  |  |     send(message); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void deleteOrder(json::DeleteMessage& order) | 
 |  |  | { | 
 |  |  |     std::string message = "{\"message\": " + order.as_string() + | 
 |  |  |                           ", \"username\": \"" + std::string(USER) + | 
 |  |  |                           "\", \"password\": \"" + std::string(PASS) + "\"}"; | 
 |  |  |     send(message); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void handleMessage(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |                    json::Message* message) | 
 |  |  | { | 
 |  |  |     if (mapAnnounce.empty()) initialise(); | 
 |  |  |     json::AnnounceMessage* a = dynamic_cast<json::AnnounceMessage*>(message); | 
 |  |  |     json::SettleMessage* b = dynamic_cast<json::SettleMessage*>(message); | 
 |  |  |     json::AddedMessage* c = dynamic_cast<json::AddedMessage*>(message); | 
 |  |  |     json::DeletedMessage* d = dynamic_cast<json::DeletedMessage*>(message); | 
 |  |  |     json::TradeMessage* e = dynamic_cast<json::TradeMessage*>(message); | 
 |  |  |     json::Broker* f = dynamic_cast<json::Broker*>(message); | 
 |  |  |     switch (message->type) { | 
 |  |  |     case json::FUTURE_TYPE: | 
 |  |  |     case json::SPREAD_TYPE: | 
 |  |  |     case json::CALL_TYPE: | 
 |  |  |     case json::PUT_TYPE: | 
 |  |  |     announce(bs, a); | 
 |  |  |     break; | 
 |  |  |     case json::SETTLEMENT: | 
 |  |  |     settle(bs, dynamic_cast<json::SettleMessage*>(message)); | 
 |  |  |     break; | 
 |  |  |     case json::ADDED: | 
 |  |  |     addedOrder(bs, dynamic_cast<json::AddedMessage*>(message)); | 
 |  |  |     break; | 
 |  |  |     case json::DELETED: | 
 |  |  |     deletedOrder(bs, dynamic_cast<json::DeletedMessage*>(message)); | 
 |  |  |     break; | 
 |  |  |     case json::TRADE: | 
 |  |  |     tradeOrder(bs, dynamic_cast<json::TradeMessage*>(message)); | 
 |  |  |     break; | 
 |  |  |     case json::BROKER_REQUEST: | 
 |  |  |     case json::BROKER_ACK: | 
 |  |  |     case json::BROKER_CONFIRM: | 
 |  |  |     broker(bs, dynamic_cast<json::Broker*>(message)); | 
 |  |  |     break; | 
 |  |  |     default:; | 
 |  |  |     } | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void announce(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |               json::AnnounceMessage* message) | 
 |  |  | { | 
 |  |  |     bs[message->product] = | 
 |  |  |     book::Book(mapAnnounce[message->type], message->product, | 
 |  |  |                    message->stationId, message->unit, message->expiry, | 
 |  |  |                    message->aggFee, message->pasFee, message->broFee); | 
 |  |  | } | 
 |  |  | void settle(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |             json::SettleMessage* message) | 
 |  |  | { | 
 |  |  |     bs.erase(message->product); | 
 |  |  | } | 
 |  |  | void addedOrder(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |                 json::AddedMessage* message) | 
 |  |  | { | 
 |  |  |     if (message->side == book::Buy) { | 
 |  |  |     book::Order t(message->price, book::Buy, message->resting, | 
 |  |  |                   message->timestamp, message->id); | 
 |  |  |     bs[message->product].bid(t); | 
 |  |  |     } else { | 
 |  |  |     book::Order t(message->price, book::Sell, message->resting, | 
 |  |  |                   message->timestamp, message->id); | 
 |  |  |     bs[message->product].ask(t); | 
 |  |  |     } | 
 |  |  | } | 
 |  |  | void deletedOrder(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |                   json::DeletedMessage* message) | 
 |  |  | { | 
 |  |  |     if (message->side == book::Buy) { | 
 |  |  |     for (auto i = bs[message->product].bidSide.begin(); | 
 |  |  |          i != bs[message->product].bidSide.end(); i++) { | 
 |  |  |         if (i->id == message->id) { | 
 |  |  |         bs[message->product].bidSide.erase(i); | 
 |  |  |         std::make_heap(bs[message->product].bidSide.begin(), | 
 |  |  |                        bs[message->product].bidSide.end(), | 
 |  |  |                        std::less<book::Level>()); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |     } else { | 
 |  |  |     for (auto i = bs[message->product].askSide.begin(); | 
 |  |  |          i != bs[message->product].askSide.end(); i++) { | 
 |  |  |         if (i->id == message->id) { | 
 |  |  |         bs[message->product].askSide.erase(i); | 
 |  |  |         std::make_heap(bs[message->product].askSide.begin(), | 
 |  |  |                        bs[message->product].askSide.end(), | 
 |  |  |                        std::greater<book::Level>()); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |     } | 
 |  |  | } | 
 |  |  | void tradeOrder(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |                 json::TradeMessage* message) | 
 |  |  | { | 
 |  |  |     if (message->tradeType == json::BUY_AGGRESSOR) { | 
 |  |  |     book::Order t(message->price, book::Buy, message->volume, | 
 |  |  |                   message->timestamp, message->passiveOrder); | 
 |  |  |     bs[message->product].bid(t); | 
 |  |  |     } else { | 
 |  |  |     book::Order t(message->price, book::Sell, message->volume, | 
 |  |  |                   message->timestamp, message->passiveOrder); | 
 |  |  |     bs[message->product].ask(t); | 
 |  |  |     } | 
 |  |  | } | 
 |  |  | void broker(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |             json::Broker* message) | 
 |  |  | { | 
 |  |  | } | 
 |  |  |  | 
 |  |  | void send(std::string& message) | 
 |  |  | { | 
 |  |  |     cli.Post("/execution", message, "text/plain"); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | } // namespace protocol | 
 
| New file | 
 |  |  | 
 |  |  | #pragma once | 
 |  |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  | #include "json.hpp" | 
 |  |  |  | 
 |  |  | #include <string> | 
 |  |  | #include <unordered_map> | 
 |  |  |  | 
 |  |  | namespace protocol | 
 |  |  | { | 
 |  |  | enum OrderEnum { ADD, DELETE, BROKER_REQUEST, BROKER_CONFIRM }; | 
 |  |  |  | 
 |  |  |     // Catchup utilities | 
 |  |  | std::unordered_map<std::string, book::Book> recoverBook(); | 
 |  |  |  | 
 |  |  |     // Outgoing messages | 
 |  |  |     void addOrder(json::AddMessage& order); | 
 |  |  |     void deleteOrder(json::DeleteMessage& order); | 
 |  |  |  | 
 |  |  | // Incoming messages | 
 |  |  | void handleMessage(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |                    json::Message* message); | 
 |  |  | void announce(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |               json::AnnounceMessage* message); | 
 |  |  | void settle(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |             json::SettleMessage* message); | 
 |  |  | void addedOrder(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |               json::AddedMessage* message); | 
 |  |  | void deletedOrder(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |                  json::DeletedMessage* message); | 
 |  |  | void tradeOrder(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |                 json::TradeMessage* message); | 
 |  |  | void broker(std::unordered_map<std::string, book::Book>& bs, | 
 |  |  |             json::Broker* message); | 
 |  |  |  | 
 |  |  |     void send(std::string& message); | 
 |  |  | } // namespace protocol | 
 
 |  |  | 
 |  |  | #pragma once | 
 |  |  |  | 
 |  |  | #define HOST "sytev070" | 
 |  |  | #include <string> | 
 |  |  |  | 
 |  |  | #define TEST | 
 |  |  |  | 
 |  |  | constexpr const char* HOST="sytev070"; | 
 |  |  | #ifdef TEST | 
 |  |  | #define PORT "9005" | 
 |  |  | constexpr const char* PORT="9005"; | 
 |  |  | #else | 
 |  |  | #define PORT "9000" | 
 |  |  | constexpr const char* PORT="9000"; | 
 |  |  | #endif | 
 |  |  |  | 
 |  |  | #define USER "jgrunbau" | 
 |  |  | #define PASS "b7d630945a0854581d9f86ba147f34a5" | 
 |  |  | constexpr const char* USER="jgrunbau"; | 
 |  |  | constexpr const char* PASS="b7d630945a0854581d9f86ba147f34a5"; | 
 
| New file | 
 |  |  | 
 |  |  | #include "strat.hpp" | 
 |  |  |  | 
 |  |  | namespace strat { | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  | #pragma once | 
 |  |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  | #include "secrets.hpp" | 
 |  |  | #include <unordered_map> | 
 |  |  | #include <string> | 
 |  |  |  | 
 |  |  | Book recoverBook() | 
 |  |  | { | 
 |  |  |      | 
 |  |  | namespace strat { | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | #include "book.hpp" | 
 |  |  | #include "json.hpp" | 
 |  |  | #include "protocol.hpp" | 
 |  |  | #include <chrono> | 
 |  |  |  | 
 |  |  | int main(void) | 
 |  |  | { | 
 |  |  |     book::Book b = book::testBook(10, true); | 
 |  |  |     auto bs = protocol::recoverBook(); | 
 |  |  |     std::cout << bs.size() << std::endl; | 
 |  |  |     for (auto i : bs) { | 
 |  |  |         std::cout << i.first << std::endl; | 
 |  |  |         i.second.printBook(); | 
 |  |  |     } | 
 |  |  | } |