Last active
April 16, 2020 14:03
-
-
Save nlyan/bb55b6054b89821a63a11a3d8307ec2a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Outputs: | |
Serialized Bytes: 464 | |
Bids: [ | |
{3, 0, 100}, | |
{1, 1.13, 1000}, | |
{2, 1.12, 500}, | |
{4, 1.12, 250} | |
] | |
Asks: [ | |
{6, 1.135, 90}, | |
{7, 1.135, 1020}, | |
{5, 1.14, 15} | |
] | |
Order 6: {6, 1.135, 90} | |
Asks: [ | |
{6, 1.135, 80}, | |
{7, 1.135, 1020}, | |
{5, 1.14, 15} | |
] | |
Ask depth at 1.135: 1100 | |
*/ | |
#include "cista.h" | |
namespace data = cista::offset; | |
struct Order { | |
CISTA_PRINTABLE (Order); | |
uint32_t order_id = 0; | |
float price = 0; | |
uint32_t quantity = 0; | |
}; | |
struct OrderBook { | |
data::indexed_vector<Order> bids; | |
data::indexed_vector<Order> asks; | |
data::hash_map<uint32_t, data::ptr<Order>> id_index; | |
}; | |
#include <algorithm> | |
#include <iostream> | |
// Needed for equal_range | |
struct OrderPriceCompare { | |
bool | |
operator() (Order const& order, float price) const { | |
return order.price < price; | |
} | |
bool | |
operator() (float price, Order const& order) const { | |
return price < order.price; | |
} | |
}; | |
// Need for accumulate | |
struct OrderQuantityAccumulator { | |
auto | |
operator() (Order const& order, int quantity) const { | |
return order.quantity + quantity; | |
} | |
auto | |
operator() (int quantity, Order const& order) const { | |
return order.quantity + quantity; | |
} | |
}; | |
int | |
main () { | |
constexpr auto mode = | |
cista::mode::WITH_VERSION | cista::mode::WITH_INTEGRITY; | |
std::vector<uint8_t> buffer; | |
{ | |
OrderBook book; | |
book.bids = {{1, 1.13, 1000}, | |
{2, 1.12, 500}, | |
{3, 0, 100}, // market order | |
{4, 1.12, 250}}; | |
book.asks = {{5, 1.14, 15}, | |
{6, 1.135, 90}, | |
{7, 1.135, 1020}}; | |
// Sort asks in ascending order by price | |
std::stable_sort (book.asks.begin (), | |
book.asks.end (), | |
[] (Order const& a, Order const& b) -> bool { | |
return a.price < b.price; | |
}); | |
// Sort bids in descending order by price, making sure market orders | |
// are at the top | |
std::stable_sort (book.bids.begin (), | |
book.bids.end (), | |
[] (Order const& a, Order const& b) -> bool { | |
if (a.price == 0.0f && b.price != 0.0f) | |
return true; | |
else if (b.price == 0.0f) | |
return false; | |
else | |
return (a.price > b.price); | |
}); | |
// Index all the orders by order id. This must be done last | |
// because all the hash_map values are offsets in memory to the | |
// orders stored in the bid and ask vectors, so re-ordering them | |
// afterward will screw things up. | |
for (auto& bid : book.bids) { | |
book.id_index.emplace (bid.order_id, &bid); | |
} | |
for (auto& ask : book.asks) { | |
book.id_index.emplace (ask.order_id, &ask); | |
} | |
buffer = cista::serialize<mode> (book); | |
} | |
std::cout << "Serialized Bytes: " << buffer.size () << "\n\n"; | |
// Reload everything and do some modification | |
{ | |
OrderBook* const book = cista::deserialize<OrderBook, mode> (buffer); | |
// Also works - Demonstrates that deserialization is trivial/zero-copy | |
// 8 bytes are used for the type id, and 8 bytes for the | |
// integrity hash | |
// Should only be done with trusted buffers | |
// OrderBook* const book = reinterpret_cast<OrderBook*> (buffer.data () + 16); | |
std::cout << "Bids: " << book->bids << "\n"; | |
std::cout << "Asks: " << book->asks << "\n\n"; | |
// O(1) lookup of orders by order id | |
auto order6 = book->id_index.find (6u); | |
if (order6 != book->id_index.end ()) { | |
std::cout << "Order 6: "; | |
std::cout << *order6->second << "\n\n"; | |
order6->second->quantity -= 10; | |
std::cout << "Asks: " << book->asks << "\n"; | |
} | |
// O(log N) lookup of orders by price | |
auto range = std::equal_range (book->asks.begin (), | |
book->asks.end (), | |
1.135f, | |
OrderPriceCompare ()); | |
std::cout << "Ask depth at 1.135: " | |
<< std::accumulate (range.first, | |
range.second, | |
0, | |
OrderQuantityAccumulator ()) | |
<< "\n"; | |
// No need to reserialize as changes are in place | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment