From 16b655e7c8cfb2e32e6bb839373f30ad63506f9a Mon Sep 17 00:00:00 2001
From: Joel Grunbaum <joelgrun@gmail.com>
Date: Sat, 08 Jan 2022 13:28:32 +0000
Subject: [PATCH] Added json parsing, protocol comprehension and began executables for algs

---
 date           |    1 
 .gitignore     |    1 
 main.cpp       |   10 
 .gitmodules    |    6 
 .clang-format  |    6 
 book.hpp       |   87 +-
 json.cpp       |  493 ++++++++++++++++++++
 protocol.cpp   |  177 +++++++
 CMakeLists.txt |   18 
 /dev/null      |   16 
 strat.cpp      |    5 
 click.cpp      |   77 +++
 test.cpp       |   15 
 book.cpp       |  255 +++++-----
 json.hpp       |  169 +++++++
 strat.hpp      |    7 
 secrets.hpp    |   14 
 bot.cpp        |    6 
 cpp-httplib    |    1 
 protocol.hpp   |   37 +
 20 files changed, 1,206 insertions(+), 195 deletions(-)

diff --git a/.clang-format b/.clang-format
index e6786f7..68225bd 100644
--- a/.clang-format
+++ b/.clang-format
@@ -5,4 +5,8 @@
 AllowShortIfStatementsOnASingleLine: true
 BreakBeforeBraces: Linux
 IndentCaseLabels: false
----
\ No newline at end of file
+PointerAlignment: Left
+AllowShortIfStatementsOnASingleLine: true
+IndentCaseBlocks: true
+IndentCaseLabels: false
+SortUsingDeclarations: true
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 4e07316..8c4231d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@
 bid
 ask
 oneshot
+build
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..d553919
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[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
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..1c49f41
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,18 @@
+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)
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 96fba56..0000000
--- a/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-CC=gcc
-CXX=g++
-CXXFLAGS=-g -Wall -std=c++20
-
-.PHONY: default all
-default: all
-
-all: exec
-
-exec: main.o book.o
-	${CXX} -o $@ $^
-
-%: %.cpp %.hpp
-	${CXX} ${CXXFLAGS} -o $@ $^
-
-
diff --git a/book.cpp b/book.cpp
index 9cb14e7..4702e4d 100644
--- a/book.cpp
+++ b/book.cpp
@@ -1,95 +1,84 @@
 #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,
@@ -97,65 +86,89 @@
            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
diff --git a/book.hpp b/book.hpp
index 9e3a89c..2240290 100644
--- a/book.hpp
+++ b/book.hpp
@@ -1,74 +1,67 @@
 #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
diff --git a/bot.cpp b/bot.cpp
new file mode 100644
index 0000000..3e80bf5
--- /dev/null
+++ b/bot.cpp
@@ -0,0 +1,6 @@
+#include "strat.hpp"
+
+int main(void)
+{
+    
+}
diff --git a/click.cpp b/click.cpp
new file mode 100644
index 0000000..4b43885
--- /dev/null
+++ b/click.cpp
@@ -0,0 +1,77 @@
+#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:;
+    }
+}
diff --git a/cpp-httplib b/cpp-httplib
new file mode 160000
index 0000000..11e02e9
--- /dev/null
+++ b/cpp-httplib
@@ -0,0 +1 @@
+Subproject commit 11e02e901cb9078f814903493359281ad4064ed5
diff --git a/date b/date
new file mode 160000
index 0000000..655b249
--- /dev/null
+++ b/date
@@ -0,0 +1 @@
+Subproject commit 655b249b8f463f690c53a19d6b4110297699e3c5
diff --git a/json.cpp b/json.cpp
new file mode 100644
index 0000000..a650550
--- /dev/null
+++ b/json.cpp
@@ -0,0 +1,493 @@
+#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
diff --git a/json.hpp b/json.hpp
new file mode 100644
index 0000000..5d1fc2b
--- /dev/null
+++ b/json.hpp
@@ -0,0 +1,169 @@
+#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
diff --git a/main.cpp b/main.cpp
index 612f52f..20d1aa9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,7 +1,15 @@
 #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();
+    }
 }
diff --git a/protocol.cpp b/protocol.cpp
new file mode 100644
index 0000000..fbcc617
--- /dev/null
+++ b/protocol.cpp
@@ -0,0 +1,177 @@
+#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
diff --git a/protocol.hpp b/protocol.hpp
new file mode 100644
index 0000000..94f6476
--- /dev/null
+++ b/protocol.hpp
@@ -0,0 +1,37 @@
+#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
diff --git a/secrets.hpp b/secrets.hpp
index b0622e5..d9d7ae8 100644
--- a/secrets.hpp
+++ b/secrets.hpp
@@ -1,11 +1,15 @@
 #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";
diff --git a/strat.cpp b/strat.cpp
new file mode 100644
index 0000000..ef8b0ba
--- /dev/null
+++ b/strat.cpp
@@ -0,0 +1,5 @@
+#include "strat.hpp"
+
+namespace strat {
+
+}
diff --git a/strat.hpp b/strat.hpp
index 212f323..893edce 100644
--- a/strat.hpp
+++ b/strat.hpp
@@ -1,9 +1,8 @@
 #pragma once
 
 #include "book.hpp"
-#include "secrets.hpp"
+#include <unordered_map>
+#include <string>
 
-Book recoverBook()
-{
-    
+namespace strat {
 }
diff --git a/test.cpp b/test.cpp
new file mode 100644
index 0000000..20d1aa9
--- /dev/null
+++ b/test.cpp
@@ -0,0 +1,15 @@
+#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();
+    }
+}

--
Gitblit v1.9.3