From 6bdd28a09c589cf631fce948476d48e9375f72a0 Mon Sep 17 00:00:00 2001
From: Joel Grunbaum <joelgrun@gmail.com>
Date: Mon, 10 Jan 2022 04:50:34 +0000
Subject: [PATCH] Click trader working, with exchange communication

---
 click.cpp    |   84 +++++++++++++++++++++++++--
 book.cpp     |    1 
 json.hpp     |   10 +++
 secrets.hpp  |    2 
 json.cpp     |   55 ++++++++++++++++++
 protocol.cpp |   18 +++---
 6 files changed, 152 insertions(+), 18 deletions(-)

diff --git a/book.cpp b/book.cpp
index 4473e8c..a450a08 100644
--- a/book.cpp
+++ b/book.cpp
@@ -144,7 +144,6 @@
 	std::size_t count = 0;
 	std::sort(askCopy.begin(), askCopy.end());
 	std::reverse(askCopy.begin(), askCopy.end());
-	uint64_t volume = 0;
 	double price = askCopy.front().price;
 	for (auto i : askCopy) {
 		std::cout << i << std::endl;
diff --git a/click.cpp b/click.cpp
index f373fce..749d649 100644
--- a/click.cpp
+++ b/click.cpp
@@ -7,7 +7,7 @@
 #include <iostream>
 #include <unordered_map>
 
-enum clickType { Buy, Sell, Flash };
+enum clickType { Buy, Sell, Flash, Delete };
 
 static std::unordered_map<std::string, clickType> mapClick;
 
@@ -15,7 +15,8 @@
 {
 	mapClick = {{"BUY", Buy}, {"SELL", Sell}, {"FLASH", Flash},
 	            {"b", Buy},   {"s", Sell},    {"f", Flash},
-	            {"B", Buy},   {"S", Sell},    {"F", Flash}};
+	            {"B", Buy},   {"S", Sell},    {"F", Flash},
+                {"DELETE", Delete}, {"D", Delete}, {"d", Delete}};
 }
 
 void usage()
@@ -25,7 +26,7 @@
 			  << std::endl
 			  << "USAGE" << std::endl
 			  << "\t-a product" << std::endl
-			  << "\t-t click type (buy, sell, flash)" << std::endl
+			  << "\t-t click type (buy, sell, flash, delete)" << std::endl
 			  << "\t-p price" << std::endl
 			  << "\t-v volume" << std::endl
 			  << "\t-i id" << std::endl
@@ -34,25 +35,80 @@
 			  << std::endl;
 }
 
+void buy(std::string& product, double price, uint64_t volume)
+{
+	json::AddMessage a(json::ADD, product, price, book::Buy, volume);
+	json::AddedMessage* b = static_cast<json::AddedMessage*>(protocol::addOrder(a));
+	std::cout << b->as_string() << std::endl;
+}
+
+void sell(std::string& product, double price, uint64_t volume)
+{
+	json::AddMessage a(json::ADD, product, price, book::Sell, volume);
+	json::AddedMessage* b = static_cast<json::AddedMessage*>(protocol::addOrder(a));
+	std::cout << b->as_string() << std::endl;
+	delete b;
+}
+
+void flash(std::string& product, double price, uint64_t volume, book::OrderSideEnum side)
+{
+	json::AddMessage a(json::ADD, product, price, side, volume);
+	json::Message* b = static_cast<json::Message*>(protocol::addOrder(a));
+    if (b->type == json::ERROR) {
+        std::cout << static_cast<json::ErrorMessage*>(b)->as_string() << std::endl;
+        return;
+    }
+	json::DeleteMessage c(json::DELETE, product, static_cast<json::AddedMessage*>(b)->id);
+	json::Message* d = protocol::deleteOrder(c);
+	std::cout << static_cast<json::AddedMessage*>(b)->as_string() << std::endl;
+	if (d->type == json::DELETED) {
+		std::cout << static_cast<json::DeletedMessage*>(d)->as_string()
+				  << std::endl;
+	} else {
+		std::cout << static_cast<json::RejectMessage*>(d)->as_string()
+				  << std::endl;
+	}
+	delete b;
+	delete d;
+}
+
+void deleteOrder(std::string& product, std::string& id)
+{
+    json::DeleteMessage a(json::DELETE, product, id);
+    json::Message* b = protocol::deleteOrder(a);
+    if (b->type == json::DELETED) {
+		std::cout << static_cast<json::DeletedMessage*>(b)->as_string()
+				  << std::endl;
+	} else if (b->type == json::REJECT) {
+		std::cout << static_cast<json::RejectMessage*>(b)->as_string()
+				  << std::endl;
+	} else {
+        std::cout << static_cast<json::ErrorMessage*>(b)->as_string() << std::endl;
+    }
+}
+
 int main(int argc, char** argv)
 {
 	int c;
 	std::string product, id;
 	double price;
-	clickType click;
+	clickType click, side;
 	uint64_t volume;
 	initialise();
 	if (argc == 1) {
 		usage(), exit(0);
 	}
-	while ((c = getopt(argc, argv, "a::t::p::v::i::")) != -1) {
+	while ((c = getopt(argc, argv, "a::t::s::p::v::i::")) != -1) {
 		switch (c) {
 		case 'a':
 			product = std::string(optarg);
 			break;
-		case 's':
+		case 't':
 			click = mapClick[optarg];
 			break;
+        case 's':
+            side = mapClick[optarg];
+            break;
 		case 'p':
 			price = std::stod(optarg);
 			break;
@@ -63,14 +119,28 @@
 			id = std::string(optarg);
 			break;
 		case '?':
+            std::cout << "*1" << std::endl;
 		default:
+            std::cout << "*2 " << (char) c << std::endl;
 			usage();
 			exit(0);
 		}
 	}
 	switch (click) {
 	case Buy:
+		buy(product, price, volume);
+		break;
 	case Sell:
-	case Flash:;
+		sell(product, price, volume);
+		break;
+	case Flash:
+        if (side == clickType::Buy)
+            flash(product, price, volume, book::Buy);
+        else
+            flash(product, price, volume, book::Sell);
+		break;
+    case Delete:
+        deleteOrder(product, id);
+        break;
 	}
 }
diff --git a/json.cpp b/json.cpp
index 5d8e340..ea1016a 100644
--- a/json.cpp
+++ b/json.cpp
@@ -58,10 +58,12 @@
 SettleMessage* settle(rapidjson::Value& d);
 AddedMessage* added(rapidjson::Value& d);
 DeletedMessage* deleted(rapidjson::Value& d);
+RejectMessage* reject(rapidjson::Value& d);
 TradeMessage* trade(rapidjson::Value& d);
 BrokerRequest* brokerReq(rapidjson::Value& d);
 BrokerAck* brokerAck(rapidjson::Value& d);
 BrokerConfirm* brokerCon(rapidjson::Value& d);
+ErrorMessage* error(rapidjson::Value& d);
 
 std::queue<Message*> parse(std::string& str)
 {
@@ -83,6 +85,7 @@
 	if (mapTypes.empty()) {
 		initialise();
 	}
+	if (d.HasMember("error")) return error(d);
 	Message* out;
 	switch (mapTypes[d["type"].GetString()]) {
 	case FUTURE_TYPE:
@@ -99,6 +102,9 @@
 		break;
 	case DELETED:
 		out = deleted(d);
+		break;
+	case REJECT:
+		out = reject(d);
 		break;
 	case TRADE:
 		out = trade(d);
@@ -161,6 +167,12 @@
 		d["sequence"].GetInt(), d["timestamp"].GetDouble());
 }
 
+RejectMessage* reject(rapidjson::Value& d)
+{
+	return new RejectMessage(mapTypes[d["type"].GetString()], "",
+	                         d["error"].GetString(), uint64_t(0), double(0));
+}
+
 TradeMessage* trade(rapidjson::Value& d)
 {
 	return new TradeMessage(
@@ -197,11 +209,25 @@
 		d["id"].GetString());
 }
 
+ErrorMessage* error(rapidjson::Value& d)
+{
+	return new ErrorMessage(d["error"].GetString());
+}
+
 Message::Message() : type(NONE), product("error") {}
 
 Message::Message(MessageTypes types, std::string product)
 	: type(types), product(product)
 {
+}
+
+ErrorMessage::ErrorMessage(std::string message)
+	: Message(ERROR, ""), message(message)
+{
+}
+std::string ErrorMessage::as_string()
+{
+	return "{\"error\": \"" + this->message + "\"}";
 }
 
 FromExchange::FromExchange(MessageTypes type, std::string product,
@@ -266,6 +292,18 @@
 {
 }
 
+std::string AddedMessage::as_string()
+{
+	return "{\"type\": \"ADDED\", \"product\": \"" + this->product +
+	       "\", \"product\": \"" + this->id + "\" \"side\": \"" +
+	       mapOrderSide[this->side] +
+	       "\", \"price\": " + std::to_string(this->price) +
+	       "\"filled\": " + std::to_string(this->filled) +
+	       ", \"resting\": " + std::to_string(this->resting) +
+	       ", \"sequence\": " + std::to_string(this->sequence) +
+	       ", \"timestamp\":" + std::to_string(this->timestamp) + "}";
+}
+
 DeleteMessage::DeleteMessage(MessageTypes type, std::string product,
                              std::string id)
 	: ToExchange(type, product), id(id)
@@ -286,6 +324,15 @@
 {
 }
 
+std::string DeletedMessage::as_string()
+{
+	return "{\"type\": \"DELETED\", \"product\": \"" + this->product +
+	       "\", \"product\": \"" + this->id + "\" \"side\": \"" +
+	       mapOrderSide[this->side] +
+	       ", \"sequence\": " + std::to_string(this->sequence) +
+	       ", \"timestamp\":" + std::to_string(this->timestamp) + "}";
+}
+
 RejectMessage::RejectMessage(MessageTypes type, std::string product,
                              std::string error, uint64_t sequence,
                              double timestamp)
@@ -293,6 +340,14 @@
 {
 }
 
+std::string RejectMessage::as_string()
+{
+	return "{\"type\": \"REJECT\", \"product\": \"" + this->product =
+	           "\", \"error\": \"" + this->error +
+	           "\", \"sequence\": " + std::to_string(this->sequence) +
+	           ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
+}
+
 TradeMessage::TradeMessage(MessageTypes type, std::string product, double price,
                            uint64_t volume, std::string buyer,
                            std::string seller, TradeTypeEnum tradeType,
diff --git a/json.hpp b/json.hpp
index adcb147..9da1381 100644
--- a/json.hpp
+++ b/json.hpp
@@ -25,6 +25,7 @@
 	BROKER_REQUEST,
 	BROKER_ACK,
 	BROKER_CONFIRM,
+	ERROR,
 	NONE
 };
 
@@ -36,6 +37,12 @@
 	Message(MessageTypes type, std::string product);
 	Message();
 	virtual ~Message() = default;
+};
+
+struct ErrorMessage : public Message {
+	std::string message;
+	ErrorMessage(std::string message);
+	std::string as_string();
 };
 
 struct FromExchange : public Message {
@@ -104,6 +111,7 @@
 	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);
+	std::string as_string();
 };
 
 struct DeleteMessage : public ToExchange {
@@ -118,12 +126,14 @@
 	DeletedMessage(MessageTypes type, std::string product, std::string id,
 	               book::OrderSideEnum side, uint64_t sequence,
 	               double timestamp);
+	std::string as_string();
 };
 
 struct RejectMessage : public FromExchange {
 	std::string error;
 	RejectMessage(MessageTypes type, std::string product, std::string error,
 	              uint64_t sequence, double timestamp);
+	std::string as_string();
 };
 
 struct TradeMessage : public FromExchange {
diff --git a/protocol.cpp b/protocol.cpp
index c15fded..0e168f5 100644
--- a/protocol.cpp
+++ b/protocol.cpp
@@ -49,17 +49,13 @@
 
 json::Message* addOrder(json::AddMessage& order)
 {
-	std::string message = "{\"message\": " + order.as_string() + ", " +
-	                      "\"username\": \"" + std::string(USER) +
-	                      "\", \"password\": \"" + std::string(PASS) + "\"}";
+	std::string message = order.as_string();
 	return send(message);
 }
 
 json::Message* deleteOrder(json::DeleteMessage& order)
 {
-	std::string message = "{\"message\": " + order.as_string() +
-	                      ", \"username\": \"" + std::string(USER) +
-	                      "\", \"password\": \"" + std::string(PASS) + "\"}";
+	std::string message = order.as_string();
 	return send(message);
 }
 
@@ -168,9 +164,13 @@
 
 json::Message* send(std::string& message)
 {
-	auto res = cli.Post("/execution", message, "text/plain");
-	std::queue<json::Message*> a = json::parse(res->body);
-	return a.front();
+    httplib::MultipartFormDataItems a = {{"message", message, "", ""},
+        {"username", USER, "", ""},
+        {"password", PASS, "", ""}};
+	auto res = cli.Post("/execution", a);
+	std::string b = res->body;
+	std::queue<json::Message*> c = json::parse(b);
+	return c.front();
 }
 
 } // namespace protocol
diff --git a/secrets.hpp b/secrets.hpp
index 398da5c..24acfae 100644
--- a/secrets.hpp
+++ b/secrets.hpp
@@ -2,7 +2,7 @@
 
 #include <string>
 
-// #define TEST
+#define TEST
 
 constexpr const char* HOST = "sytev070";
 #ifdef TEST

--
Gitblit v1.9.3