Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ Orderbook Class #7

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ if(POLICY CMP0167)
endif()

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

include_directories(${PROJECT_SOURCE_DIR}/include/)
include_directories(${PROJECT_SOURCE_DIR}/include/trading_engine)
include_directories(${PROJECT_SOURCE_DIR}/include/background_service)
include_directories(${PROJECT_SOURCE_DIR}/include/logger)
include_directories(${PROJECT_SOURCE_DIR}/include/orderbook)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(Boost REQUIRED COMPONENTS system)
Expand All @@ -20,6 +22,7 @@ add_executable(TradingEngineServer
src/trading_engine/TradingEngineServer.cpp
src/background_service/BackgroundService.cpp
src/background_service/ThreadPool.cpp
src/orderbook/Orderbook.cpp
)

target_link_libraries(TradingEngineServer
Expand Down
5 changes: 4 additions & 1 deletion include/background_service/BackgroundService.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ using boost::asio::ip::tcp;
class BackgroundService {
public:
BackgroundService(const std::string& log_file_path, const std::string& config_file_path)
: logger_(std::make_unique<FileLogger>(log_file_path)), config_(ServerConfiguration(config_file_path)), close_flag_(false) {}
: logger_(std::make_unique<FileLogger>(log_file_path))
, config_(ServerConfiguration(config_file_path))
, close_flag_(false)
{}

protected:
virtual void start_server();
Expand Down
56 changes: 56 additions & 0 deletions include/orderbook/Orderbook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include <condition_variable>
#include <thread>
#include <mutex>
#include <atomic>
#include <map>
#include <unordered_map>

#include <OrderbookAliases.h>
#include <Order.h>
#include <ModifiedOrder.h>
#include <OrderbookLevelInfo.h>
#include <Trade.h>

class Orderbook {
public:
Orderbook()
: shutdown_(false)
{}

~Orderbook();
Orderbook(const Orderbook&) = delete;
void operator=(const Orderbook&) = delete;
Orderbook(Orderbook&&) = delete;
void operator=(Orderbook&&) = delete;

Trades add_order(OrderPointer order);
void cancel_order(OrderId order_id);
Trades modify_order(ModifiedOrder order);

std::size_t size() const;
OrderbookLevelInfo get_order_info() const;

private:
void prune_good_for_day_orders();
void cancel_orders(Orders order_id_list);
void cancel_order_internal(OrderId order_id);
void on_order_cancelled(OrderPointer order);
void on_order_added(OrderPointer order);
void on_order_matched(Price price, Quantity quantity, bool isFullyFilled);
void update_level_data(Price price, Quantity quantity, LevelData::Operation operation);
bool can_fully_fill(SideType side, Price price, Quantity quantity) const;
bool can_match(SideType side, Price price) const;
Trades match_orders();

std::unordered_map<Price, LevelData> data_;
std::map<Price, OrderPointers, std::greater<Price>> bids_;
std::map<Price, OrderPointers, std::less<Price>> asks_;
std::unordered_map<OrderId, OrderEntry> orders_;
mutable std::mutex orders_mutex_;
std::thread orders_prune_thread_;
std::condition_variable shutdown_condition_variable_;
std::atomic<bool> shutdown_;

};
14 changes: 14 additions & 0 deletions include/orderbook/OrderbookAliases.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <vector>
#include <cstdint>
#include <limits>

using Price = std::int32_t;
using Quantity = std::uint32_t;
using OrderId = std::uint64_t;
using Orders = std::vector<OrderId>;

struct OrderbookAliases {
static const Price INVALID_PRICE = std::numeric_limits<Price>::quiet_NaN();
};
14 changes: 14 additions & 0 deletions include/orderbook/level/LevelData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "orderbook/OrderbookAliases.h"

struct LevelData {
Price price_;
Quantity quantity_;

enum class Operation {
ADD,
REMOVE,
MATCH
};
};
20 changes: 20 additions & 0 deletions include/orderbook/level/OrderbookLevelInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "LevelData.h"

using LevelInfo = std::vector<LevelData>;

class OrderbookLevelInfo {
public:
OrderbookLevelInfo(const LevelInfo& bids, const LevelInfo& asks)
: bids_(bids)
, asks_(asks)
{}

const LevelInfo& get_bids() const { return bids_; }
const LevelInfo& get_asks() const { return asks_; }

private:
LevelInfo bids_;
LevelInfo asks_;
};
28 changes: 28 additions & 0 deletions include/orderbook/order/ModifiedOrder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include <Order.h>

class ModifiedOrder {
ModifiedOrder(OrderId order_id, SideType side, Price price, Quantity quantity)
: order_id_(order_id)
, price_(price)
, side_(side)
, quantity_(quantity)
{}

OrderId get_order_id() const { return order_id_; }
Price get_price() const { return price_; }
SideType get_side() const { return side_; }
Quantity get_quantity() const { return quantity_; }

OrderPointer to_order_pointer(OrderType type) const {
return std::make_shared<Order>(type, get_order_id(), get_side(), get_price(), get_quantity());
}

private:
OrderId order_id_;
Price price_;
SideType side_;
Quantity quantity_;

};
66 changes: 66 additions & 0 deletions include/orderbook/order/Order.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#pragma once

#include <exception>
#include <list>
#include <memory>

#include <OrderbookAliases.h>
#include <OrderType.h>
#include <SideType.h>

class Order {
public:
Order(OrderType order_type, OrderId order_id, SideType side, Price price, Quantity quantity)
: order_type_(order_type)
, order_id_(order_id)
, side_(side)
, price_(price)
, initial_quantity_(quantity)
, remaining_quantity_(quantity)
{}

Order(OrderId order_id, SideType side, Quantity quantity)
: Order(OrderType::MARKET, order_id, side, OrderbookAliases::INVALID_PRICE, quantity)
{}

OrderId get_order_id() const { return order_id_; }
SideType get_side() const { return side_; }
Price get_price() const { return price_; }
OrderType get_order_type() const { return order_type_; }
Quantity get_initial_quantity() const { return initial_quantity_; }
Quantity get_remaining_quantity() const { return remaining_quantity_; }
Quantity get_filled_quantity() const { return get_initial_quantity() - get_remaining_quantity(); }
bool is_filled() const { return get_remaining_quantity() == 0; }

void fill(Quantity quantity) {
if (quantity > get_remaining_quantity())
// throw std::logic_error("Order (" + get_order_id() + ") cannot be filled for more than its remaining quantity.");

remaining_quantity_ -= quantity;
}

void to_good_till_cancel(Price price) {
if (get_order_type() != OrderType::MARKET)
// throw std::logic_error("Order (" + get_order_id() + ") cannot have its price adjusted, only market orders can.");

price_ = price;
order_type_ = OrderType::GOOD_TILL_CANCEL;
}

private:
OrderType order_type_;
OrderId order_id_;
SideType side_;
Price price_;
Quantity initial_quantity_;
Quantity remaining_quantity_;

};

using OrderPointer = std::shared_ptr<Order>;
using OrderPointers = std::list<OrderPointer>;

struct OrderEntry {
OrderPointer order_;
OrderPointers::iterator location_;
};
9 changes: 9 additions & 0 deletions include/orderbook/order/OrderType.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

enum class OrderType {
GOOD_TILL_CANCEL,
FILL_AND_KILL,
FILL_OR_KILL,
GOOD_FOR_DAY,
MARKET
};
6 changes: 6 additions & 0 deletions include/orderbook/order/SideType.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

enum class SideType {
BUY,
SELL
};
21 changes: 21 additions & 0 deletions include/orderbook/trade/Trade.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <TradeInfo.h>

class Trade {
public:
Trade(const TradeInfo& bid, const TradeInfo& ask)
: bid_trade_(bid)
, ask_trade_(ask)
{}

const TradeInfo& get_bid_trade() const { return bid_trade_; }
const TradeInfo& get_ask_trade() const { return ask_trade_; }

private:
TradeInfo bid_trade_;
TradeInfo ask_trade_;

};

using Trades = std::vector<Trade>;
9 changes: 9 additions & 0 deletions include/orderbook/trade/TradeInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <OrderbookAliases.h>

struct TradeInfo {
OrderId order_id_;
Price price_;
Quantity quantity_;
};
3 changes: 2 additions & 1 deletion include/trading_engine/TradingEngineServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
class TradingEngineServer : public BackgroundService {
public:
TradingEngineServer(const std::string& config_file_path, const std::string& log_file_path)
: BackgroundService(log_file_path, config_file_path) {}
: BackgroundService(log_file_path, config_file_path)
{}

void run_trading_engine();

Expand Down
Loading