From 0b7aa02704f6ece97d17fbb118519c5cc62caaba Mon Sep 17 00:00:00 2001
From: Joel Grunbaum <joelgrun@gmail.com>
Date: Wed, 19 Jan 2022 07:45:21 +0000
Subject: [PATCH] Bot prints exchange feed
---
protocol.cpp | 249 +++++++++++++++++++++++++++++--------------------
1 files changed, 149 insertions(+), 100 deletions(-)
diff --git a/protocol.cpp b/protocol.cpp
index a129985..a4b8475 100644
--- a/protocol.cpp
+++ b/protocol.cpp
@@ -2,162 +2,206 @@
#include "book.hpp"
#include "cpp-httplib/httplib.h"
+#include "easywsclient/easywsclient.hpp"
#include "json.hpp"
#include "secrets.hpp"
#include <chrono>
+#include <cstddef>
#include <iostream>
+#include <memory>
#include <queue>
#include <sstream>
+#include <stdexcept>
#include <string>
#include <unordered_map>
namespace protocol
{
static std::unordered_map<json::MessageTypes, book::ProductTypeEnum>
- mapAnnounce;
+ mapAnnounce;
std::string server = std::string(HOST) + ":" + std::string(PORT);
httplib::Client cli("http://" + server);
+std::unique_ptr<easywsclient::WebSocket> ws;
+
+double lastime = 0;
void initialise()
{
- mapAnnounce = {{json::FUTURE_TYPE, book::FUTURE},
- {json::SPREAD_TYPE, book::SPREAD},
- {json::CALL_TYPE, book::CALL},
- {json::PUT_TYPE, book::PUT}};
+ 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("../data.test");
- 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;
+ std::unordered_map<std::string, book::Book> bs;
+ // std::ifstream sampleFile("../data.test");
+ // std::stringstream ss;
+ // ss << sampleFile.rdbuf();
+ httplib::Client cli("http://" + server);
+ auto res = cli.Get("/recover");
+ std::string l;
+ // l = ss.str();
+ l = res->body;
+ std::queue<json::Message*> a(json::parse(l));
+ while (!a.empty()) {
+ if (static_cast<json::FromExchange*>(a.front()) != nullptr ||
+ static_cast<json::FromExchange*>(a.front())->timestamp > lastime) {
+ lastime = static_cast<json::FromExchange*>(a.front())->timestamp;
+ protocol::handleMessage(bs, a.front());
+ }
+ delete a.front();
+ a.pop();
+ }
+ return bs;
+}
+
+void createWebSocket()
+{
+ ws = std::unique_ptr<easywsclient::WebSocket>(
+ easywsclient::WebSocket::pointer(easywsclient::WebSocket::from_url(
+ "ws://" + server + "/information")));
+ ws->poll();
+}
+
+std::deque<json::Message*>
+catchUp(std::unordered_map<std::string, book::Book>& bs)
+{
+ std::string feed;
+ bool gotMessage;
+ std::deque<json::Message*> out;
+ do {
+ gotMessage = false;
+ ws->poll();
+ ws->dispatch([gotMessageOut = &gotMessage, messageOut = &feed,
+ ws = ws.get()](const std::string& message) {
+ *gotMessageOut = true;
+ *messageOut = message;
+ });
+ if (gotMessage) {
+ std::queue<json::Message*> a(json::parse(feed));
+ while (!a.empty()) {
+ if (static_cast<json::FromExchange*>(a.front()) != nullptr ||
+ static_cast<json::FromExchange*>(a.front())->timestamp >
+ lastime) {
+ lastime =
+ static_cast<json::FromExchange*>(a.front())->timestamp;
+ }
+ protocol::handleMessage(bs, a.front());
+ out.push_back(a.front());
+ a.pop();
+ }
+ }
+ } while (gotMessage);
+ return out;
}
json::Message* addOrder(json::AddMessage& order)
{
- std::string message = "{\"message\": " + order.as_string() + ", " +
- "\"username\": \"" + std::string(USER) +
- "\", \"password\": \"" + std::string(PASS) + "\"}";
- return send(message);
+ 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) + "\"}";
- return send(message);
+ std::string message = order.as_string();
+ return send(message);
}
void handleMessage(std::unordered_map<std::string, book::Book>& bs,
json::Message* message)
{
- if (mapAnnounce.empty()) initialise();
- switch (message->type) {
- case json::FUTURE_TYPE:
- case json::SPREAD_TYPE:
- case json::CALL_TYPE:
- case json::PUT_TYPE:
- announce(bs, dynamic_cast<json::AnnounceMessage*>(message));
- 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:;
- }
+ if (mapAnnounce.empty()) initialise();
+ if (dynamic_cast<json::FromExchange*>(message) != nullptr) {
+ lastime = dynamic_cast<json::FromExchange*>(message)->timestamp;
+ }
+ switch (message->type) {
+ case json::FUTURE_TYPE:
+ case json::SPREAD_TYPE:
+ case json::CALL_TYPE:
+ case json::PUT_TYPE:
+ announce(bs, static_cast<json::AnnounceMessage*>(message));
+ break;
+ case json::SETTLEMENT:
+ settle(bs, static_cast<json::SettleMessage*>(message));
+ break;
+ case json::ADDED:
+ addedOrder(bs, static_cast<json::AddedMessage*>(message));
+ break;
+ case json::DELETED:
+ deletedOrder(bs, static_cast<json::DeletedMessage*>(message));
+ break;
+ case json::TRADE:
+ tradeOrder(bs, static_cast<json::TradeMessage*>(message));
+ break;
+ case json::BROKER_REQUEST:
+ case json::BROKER_ACK:
+ case json::BROKER_CONFIRM:
+ broker(bs, static_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);
+ 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);
+ 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);
- }
+ if (message->side == book::Buy && message->resting) {
+ book::Order t(message->price, book::Buy, message->resting,
+ message->timestamp, message->id);
+ bs[message->product].bid(t);
+ } else if (message->side == book::Sell && message->resting) {
+ 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 (std::size_t i = 0; i < bs[message->product].bidSide.size(); i++) {
- if (bs[message->product].bidSide[i].id == message->id) {
- bs[message->product].bidSide[i] = bs[message->product].bidSide.back();
- bs[message->product].bidSide.erase(bs[message->product].bidSide.end());
- std::make_heap(bs[message->product].bidSide.begin(),
- bs[message->product].bidSide.end(),
- std::less<book::Level>());
- }
+ if (message->side == book::Buy) {
+ bs[message->product].bidSide.erase(message->id);
+ } else {
+ bs[message->product].askSide.erase(message->id);
}
- } else {
- for (std::size_t i = 0; i < bs[message->product].askSide.size(); i++) {
- if (bs[message->product].askSide[i].id == message->id) {
- bs[message->product].askSide[i] = bs[message->product].askSide.back();
- bs[message->product].askSide.erase(bs[message->product].askSide.end());
- 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);
- }
+ if (bs.find(message->passiveOrder) != bs.end()) {
+ if (message->tradeType == json::BUY_AGGRESSOR) {
+ if (message->passiveOrderRemaining > 0) {
+ bs[message->product].askSide.at(message->passiveOrder).volume =
+ message->passiveOrderRemaining;
+ } else {
+ bs[message->product].askSide.erase(message->passiveOrder);
+ }
+ } else if (message->tradeType == json::SELL_AGGRESSOR) {
+ if (message->passiveOrderRemaining > 0) {
+ bs[message->product].bidSide.at(message->passiveOrder).volume =
+ message->passiveOrderRemaining;
+ } else {
+ bs[message->product].bidSide.erase(message->passiveOrder);
+ }
+ }
+ }
}
+
void broker(std::unordered_map<std::string, book::Book>& bs,
json::Broker* message)
{
@@ -165,8 +209,13 @@
json::Message* send(std::string& message)
{
- auto res = cli.Post("/execution", message, "text/plain");
- return json::parseSingle(res->body);
+ 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
--
Gitblit v1.10.0