|
| 1 | +#ifndef FAST_EXCHANGE_ORDER_H |
| 2 | +#define FAST_EXCHANGE_ORDER_H |
| 3 | +#include <chrono> |
| 4 | +#include <string> |
| 5 | +#include <utility> |
| 6 | +#include <array> |
| 7 | +#include <stdexcept> |
| 8 | +#include <numeric> |
| 9 | +#include <cmath> |
| 10 | +#include <iomanip> |
| 11 | +#include <boost/intrusive/list.hpp> |
| 12 | + |
| 13 | +// Represents the different actions of orders. |
| 14 | +enum class OrderAction {Limit = 0, Market = 1}; |
| 15 | +constexpr std::array order_action_to_string {"LIMIT", "MARKET"}; |
| 16 | + |
| 17 | +//Represents the different types of orders. |
| 18 | +// Good 'Til Cancelled: A good-til-canceled order will remain active until |
| 19 | +// you decide to cancel it. |
| 20 | +// Fill Or Kill: A fill-or-kill order will be executed immediately in its entirety; |
| 21 | +// otherwise, it will be cancelled. |
| 22 | +// Immediate or Cancel: A immediate-or-cancel order will be executed immediately |
| 23 | +// as fully as possible. Non-executed parts of the order are deleted |
| 24 | +// without entry in the order book. |
| 25 | +enum class OrderType {GoodTillCancel = 0, FillOrKill = 1, ImmediateOrCancel = 2}; |
| 26 | +constexpr std::array order_type_to_string {"GTC", "FOK", "IOC"}; |
| 27 | + |
| 28 | +// Represents the side of the order. |
| 29 | +enum class OrderSide {Bid = 0, Ask = 1}; |
| 30 | +constexpr std::array order_side_to_string {"BID", "ASK"}; |
| 31 | + |
| 32 | +// Represents the status of an order. |
| 33 | +enum class OrderStatus {Accepted = 0, Rejected = 1, PartiallyFilled = 1, Filled = 2, Cancelled = 3}; |
| 34 | +constexpr std::array order_status_to_string {"ACCEPTED", "REJECTED", "PARTIALLY FILLED", "FILLED", "CANCELLED"}; |
| 35 | + |
| 36 | +using namespace boost::intrusive; |
| 37 | + |
| 38 | +/** |
| 39 | + * An mutable order ADT. |
| 40 | + */ |
| 41 | +struct Order: public list_base_hook<> { |
| 42 | + const OrderAction action; |
| 43 | + const OrderSide side; |
| 44 | + const OrderType type; |
| 45 | + const uint64_t user_id; |
| 46 | + const uint64_t id; |
| 47 | + const std::string symbol; |
| 48 | + const std::chrono::time_point<std::chrono::system_clock> time; |
| 49 | + const float price; |
| 50 | + OrderStatus status; |
| 51 | + uint64_t quantity; |
| 52 | + |
| 53 | + /** |
| 54 | + * A constructor for the order ADT. |
| 55 | + * TODO: When is an order rejected? |
| 56 | + * |
| 57 | + * @param order_action the action of the order - limit or market. |
| 58 | + * @param order_side the side of the order - ask or bid. |
| 59 | + * @param order_type the type of the order - GTC, IOC, FOK. |
| 60 | + * @param order_quantity the quantity of the order, require that quantity is positive. |
| 61 | + * @param order_price the price of the order, require that price is non-negative. |
| 62 | + * @param order_id a unique ID associated with the order. |
| 63 | + * @param order_user_id a unique ID associated with the user placing the order. |
| 64 | + * @throws Error if price is negative or if quantity is not positive. |
| 65 | + */ |
| 66 | + Order(OrderAction order_action, OrderSide order_side, OrderType order_type, uint64_t order_quantity, float order_price, |
| 67 | + uint64_t order_id, uint64_t order_user_id) |
| 68 | + : action(order_action), side(order_side), type(order_type), status(OrderStatus::Accepted), quantity(order_quantity), |
| 69 | + price(order_price), id(order_id), user_id(order_user_id), time(std::chrono::system_clock::now()) |
| 70 | + { |
| 71 | + if (quantity == 0) |
| 72 | + throw std::invalid_argument("quantity must be positive!"); |
| 73 | + if (price < 0) |
| 74 | + throw std::invalid_argument("price must be non-negative!"); |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * Indicates whether two orders are equal. Two orders are equal if and only if they have |
| 79 | + * the same status, the same side, the same ID, and the same price (within epsilon). |
| 80 | + * |
| 81 | + * @param other another order. |
| 82 | + * @return true if the orders are equal and false otherwise. |
| 83 | + */ |
| 84 | + bool operator==(const Order& other) const { |
| 85 | + return status == other.status && |
| 86 | + action == other.action && |
| 87 | + type == other.type && |
| 88 | + side == other.side && |
| 89 | + id == other.id && |
| 90 | + user_id == other.user_id && |
| 91 | + quantity == other.quantity && |
| 92 | + (std::fabs(price - other.price) <= |
| 93 | + std::numeric_limits<float>::epsilon() * std::fmax(std::fabs(price), std::fabs(other.price))); |
| 94 | + } |
| 95 | + |
| 96 | + bool operator!=(const Order& other) const { |
| 97 | + return !(*this == other); |
| 98 | + } |
| 99 | + /** |
| 100 | + * @return the string representation of an order. |
| 101 | + */ |
| 102 | + std::string toString() { |
| 103 | + auto order_time = std::chrono::system_clock::to_time_t(time); |
| 104 | + std::string time_string = std::ctime(&order_time); |
| 105 | + std::string order_action = order_action_to_string[static_cast<std::underlying_type<OrderStatus>::type>(action)]; |
| 106 | + std::string order_side = order_side_to_string[static_cast<std::underlying_type<OrderStatus>::type>(side)]; |
| 107 | + std::string order_status = order_status_to_string[static_cast<std::underlying_type<OrderStatus>::type>(status)]; |
| 108 | + std::string order_type = order_type_to_string[static_cast<std::underlying_type<OrderStatus>::type>(type)]; |
| 109 | + std::string order_price = std::to_string(price); |
| 110 | + std::string order_quantity = std::to_string(quantity); |
| 111 | + std::string order_id = std::to_string(id); |
| 112 | + std::string order_user_id = std::to_string(user_id); |
| 113 | + |
| 114 | + return "Order ID: " + order_id + |
| 115 | + "\nUser ID: " + order_user_id + |
| 116 | + "\nOrder Time: " + time_string + |
| 117 | + "\nOrder Side: " + order_side + |
| 118 | + "\nOrder Action: " + order_action + |
| 119 | + "\nOrder Status: " + order_status + |
| 120 | + "\nOrder Type: " + order_type + |
| 121 | + "\nOrder Price: " + order_price + |
| 122 | + "\nOrder Quantity: " + order_quantity + "\n"; |
| 123 | + } |
| 124 | +}; |
| 125 | +#endif //FAST_EXCHANGE_ORDER_H |
0 commit comments