From bb235393b72f5974a087e48e05c39fcd83e1db57 Mon Sep 17 00:00:00 2001 From: Joel Grunbaum <joelgrun@gmail.com> Date: Fri, 07 Jan 2022 07:29:27 +0000 Subject: [PATCH] begun cpp version --- .gitignore | 5 main.cpp | 6 + book.cpp | 127 +++++++++++++++++++++++++ Makefile | 16 +++ book.hpp | 89 +++++++++++++++++ strat.py | 4 6 files changed, 246 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore index 8a0a550..b836a20 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ * !*.py -!.gitignore \ No newline at end of file +!.gitignore +!*.cpp +!*.hpp +!Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b57ea21 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +CC=clang +CXX=clang +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 new file mode 100644 index 0000000..2202639 --- /dev/null +++ b/book.cpp @@ -0,0 +1,127 @@ +#include "book.hpp" +#include <chrono> +#include <iostream> + +Order::Order(double price, OrderSideEnum side, int volume, + std::chrono::nanoseconds timestamp, std::string id) + : price{price}, side{side}, remaining_volume{volume}, + filled_volume(0), timestamp{timestamp}, id{id} {} + +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 < 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 > 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 <= 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 >= 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; +} + +Book::Book() + : bidSide(), askSide(), productType(TEST), product("a"), stationId("b"), + unit("c"), expiry(std::chrono::nanoseconds(0)), aggFee(1), pasFee(-1), + broFee(2) {} + +Book::Book(ProductTypeEnum productType, std::string product, + std::string stationId, std::string unit, + std::chrono::nanoseconds expiry, double aggFee, double pasFee, + double broFee) + : bidSide{}, askSide{}, productType{productType}, product(product), + stationId(stationId), unit(unit), expiry(expiry), aggFee(aggFee), + 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; + } else { + order.remaining_volume -= this->bidSide.top().volume; + order.filled_volume += this->bidSide.top().volume; + this->bidSide.pop(); + } + 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; + } else { + order.remaining_volume -= this->askSide.top().volume; + order.filled_volume += this->askSide.top().volume; + this->askSide.pop(); + } + if (order.remaining_volume > 0) { + this->bidSide.emplace(order); + } + } +} + +void Book::printBook() { + std::cout << "Sell side"; + this->askSide.printTop(); + std::cout << "Buy side"; + this->bidSide.printTop(); +} + +Book testBook(int orders, bool printBook) { + Book b = Book(); + std::chrono::nanoseconds time(1); + for (int i = 0; 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(); + return b; +} diff --git a/book.hpp b/book.hpp new file mode 100644 index 0000000..a167b32 --- /dev/null +++ b/book.hpp @@ -0,0 +1,89 @@ +#pragma once + +#include <chrono> +#include <iostream> +#include <queue> +#include <string> +#include <vector> + +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); +}; + +struct Level { + double price; + int volume; + OrderSideEnum side; + std::chrono::nanoseconds timestamp; + std::string id; + + 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); + +template <class T> +struct Side : public std::priority_queue<Level, std::vector<Level>, T> { +public: + void 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); + } + } + } + + void topRemoveVolume(int volume) { this->c[0].volume -= volume; } + + void printTop(int num = 5) { + std::sort(this->c.begin(), this->c.end(), this->comp); + for (int i = 0; i < num && i < this->size(); i++) { + std::cout << "Price: " << this->c[i].price + << ", volume: " << this->c[i].volume + << ", time: " << this->c[i].timestamp.count() + << ", id: " << this->c[i].id << std::endl; + } + std::make_heap(this->c.begin(), this->c.end(), this->comp); + } +}; + +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; + + 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(); +}; + +Book testBook(int orders = 10, bool printBook = true); diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..b05ddec --- /dev/null +++ b/main.cpp @@ -0,0 +1,6 @@ +#include "book.hpp" + +int main(void) +{ + testBook(); +} diff --git a/strat.py b/strat.py new file mode 100644 index 0000000..d7c0db5 --- /dev/null +++ b/strat.py @@ -0,0 +1,4 @@ +""".#strat.py Strategy module.""" +import book +import protocol + -- Gitblit v1.9.3