Skip to content

Commit

Permalink
Merge pull request #1 from Kautenja/remove-account
Browse files Browse the repository at this point in the history
Remove account
  • Loading branch information
Kautenja authored Dec 17, 2019
2 parents 25ba307 + 0dc3478 commit 916f0f5
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 1,244 deletions.
22 changes: 8 additions & 14 deletions benchmark/benchmark_lob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ using Catch::Benchmark::Chronometer;
//

inline void spam_limits(LimitOrderBook book, int count) {
Account account;
for (int i = 0; i < count; i++)
book.limit(&account, Side::Buy, 50, i, i);
for (int i = 0; i < count; i++) book.limit(Side::Buy, 50, i, i);
}

TEST_CASE("Spam new Limits") {
Expand Down Expand Up @@ -58,9 +56,8 @@ TEST_CASE("Spam new Limits") {
//

inline void spam_orders(LimitOrderBook book, int count, int variance = 5) {
Account account;
for (int i = 0; i < count; i++)
book.limit(&account, Side::Buy, 50, i % variance, i);
book.limit(Side::Buy, 50, i % variance, i);
}

TEST_CASE("Spam new Orders") {
Expand Down Expand Up @@ -101,12 +98,11 @@ inline void spam_orders_random_cancels(
int variance = 30,
int cancel_every = 5
) {
Account account;
auto generator = std::default_random_engine();
auto price_distribution = std::normal_distribution<double>(mean, variance);
book.limit(&account, Side::Buy, 50, price_distribution(generator), 0);
book.limit(Side::Buy, 50, price_distribution(generator), 0);
for (int i = 1; i < count; i++) {
book.limit(&account, Side::Buy, 50, price_distribution(generator), i);
book.limit(Side::Buy, 50, price_distribution(generator), i);
if (i % cancel_every == 0)
book.cancel(i - cancel_every);
}
Expand Down Expand Up @@ -152,16 +148,15 @@ inline void spam_limit_random_orders(
int size_variance = 10,
int order_every = 100
) {
Account account;
auto generator = std::default_random_engine();
auto price = std::normal_distribution<double>(price_mean, price_variance);
auto size = std::normal_distribution<double>(size_mean, size_variance);
for (int i = 1; i < count; i++) {
auto price_ = static_cast<uint64_t>(price(generator));
auto size_ = static_cast<uint32_t>(size(generator));
book.limit(&account, Side::Buy, 100, price_, i);
book.limit(Side::Buy, 100, price_, i);
if (i % order_every == 0) // random submit a market order
book.market(&account, Side::Sell, size_, i);
book.market(Side::Sell, size_, i);
}
}

Expand All @@ -188,15 +183,14 @@ inline void spam_limit_many_market_orders(
int size_mean = 50,
int size_variance = 10
) {
Account account;
auto generator = std::default_random_engine();
auto price = std::normal_distribution<double>(price_mean, price_variance);
auto size = std::normal_distribution<double>(size_mean, size_variance);
for (int i = 1; i < count; i++) {
auto price_ = static_cast<uint64_t>(price(generator));
auto size_ = static_cast<uint32_t>(size(generator));
book.limit(&account, Side::Buy, 100, price_, i);
book.market(&account, Side::Sell, size_, i);
book.limit(Side::Buy, 100, price_, i);
book.market(Side::Sell, size_, i);
}
}

Expand Down
32 changes: 14 additions & 18 deletions include/limit_order_book.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ class LimitOrderBook {

/// Add a new sell limit order to the book.
///
/// @param account the account for the order
/// @param size the number of shares to sell
/// @param price the limit price for the order
/// @param arrival the time the order arrived at
/// @return the order ID for the order added to the book
///
UID limit_sell(Account* account, Size size, Price price, Timestamp arrival) {
UID limit_sell(Size size, Price price, Timestamp arrival) {
// put the order into the sequence map
orders.insert({sequence, {account, sequence, Side::Sell, size, price, arrival}});
orders.insert({sequence, {sequence, Side::Sell, size, price, arrival}});
if (buys.best != nullptr && price <= buys.best->key) { // crosses
// place a market order with the limit price
buys.market(&orders.at(sequence), [&](UID uid) { orders.erase(uid); });
Expand All @@ -54,15 +53,14 @@ class LimitOrderBook {

/// Add a new buy limit order to the book.
///
/// @param account the account for the order
/// @param size the number of shares to buy
/// @param price the limit price for the order
/// @param arrival the time the order arrived at
/// @return the order ID for the order added to the book
///
UID limit_buy(Account* account, Size size, Price price, Timestamp arrival) {
UID limit_buy(Size size, Price price, Timestamp arrival) {
// put the order into the sequence map
orders.insert({sequence, {account, sequence, Side::Buy, size, price, arrival}});
orders.insert({sequence, {sequence, Side::Buy, size, price, arrival}});
if (sells.best != nullptr && price >= sells.best->key) { // crosses
// place a market order with the limit price
sells.market(&orders.at(sequence), [&](UID uid) { orders.erase(uid); });
Expand All @@ -83,10 +81,10 @@ class LimitOrderBook {
/// @param arrival the time the order arrived at
/// @return the order ID for the order added to the book
///
inline UID limit(Account* account, Side side, Size size, Price price, Timestamp arrival) {
inline UID limit(Side side, Size size, Price price, Timestamp arrival) {
switch (side) { // send the order to the appropriate side
case Side::Sell: return limit_sell(account, size, price, arrival);
case Side::Buy: return limit_buy(account, size, price, arrival);
case Side::Sell: return limit_sell(size, price, arrival);
case Side::Buy: return limit_buy(size, price, arrival);
}
}

Expand Down Expand Up @@ -119,24 +117,22 @@ class LimitOrderBook {

/// Execute a sell market order.
///
/// @param account the account for the order
/// @param size the size of the market order
/// @arrival the arrival of the market order
///
void market_sell(Account* account, Size size, Timestamp arrival) {
auto order = Order(account, sequence, Side::Sell, size, 0, arrival);
void market_sell(Size size, Timestamp arrival) {
auto order = Order(sequence, Side::Sell, size, 0, arrival);
order.execution = arrival;
buys.market(&order, [&](UID uid) { orders.erase(uid); });
}

/// Execute a buy market order.
///
/// @param account the account for the order
/// @param size the size of the market order
/// @arrival the arrival of the market order
///
void market_buy(Account* account, Size size, Timestamp arrival) {
auto order = Order(account, sequence, Side::Buy, size, 0, arrival);
void market_buy(Size size, Timestamp arrival) {
auto order = Order(sequence, Side::Buy, size, 0, arrival);
order.execution = arrival;
sells.market(&order, [&](UID uid) { orders.erase(uid); });
}
Expand All @@ -147,10 +143,10 @@ class LimitOrderBook {
/// @param size the size of the market order
/// @arrival the arrival of the market order
///
inline void market(Account* account, Side side, Size size, Timestamp arrival) {
inline void market(Side side, Size size, Timestamp arrival) {
switch (side) { // send the market order to the appropriate side
case Side::Sell: { market_sell(account, size, arrival); break; }
case Side::Buy: { market_buy(account, size, arrival); break; }
case Side::Sell: { market_sell(size, arrival); break; }
case Side::Buy: { market_buy(size, arrival); break; }
}
}

Expand Down
28 changes: 4 additions & 24 deletions include/limit_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,14 @@ struct LimitTree {
// update the size and volume for the entire tree
++size;
volume += order->size;
// update the account
order->account->limit(order);
}

// TODO: use object pool for limit reuse?
/// Remove an order from the limit tree.
///
/// @param order an order that exists in the limit tree
///
void remove(Order* order) {
void cancel(Order* order) {
// unwrap the limit for the order
auto limit_ = order->limit;
if (order->prev == nullptr && order->next == nullptr) { // last Order
Expand Down Expand Up @@ -180,15 +178,6 @@ struct LimitTree {
volume -= order->size;
}

/// Cancel an order in the limit tree.
///
/// @param order an order that exists in the limit tree
///
inline void cancel(Order* order) {
remove(order);
order->account->cancel(order);
}

/// Perform a market order of given size on the given limit tree.
///
/// @param order the order to find a market order for
Expand All @@ -200,17 +189,13 @@ struct LimitTree {
while (best != nullptr && is_in_limit<side>(best->key, order->price)) {
// get the next match as the front of the best price
auto match = best->order_head;
// TODO: Update timestamping?
// set the execution time for the current match
// TODO: update with different timestamping pattern?
match->execution = order->arrival;
if (match->size >= order->size) { // current match can fill
// update the account for the market order
order->account->market_fill(match, order);
if (match->size == order->size) { // limit order filled
// update the account for the limit order
match->account->limit_fill(match, order);
// remove the current match from the book
remove(match);
cancel(match);
did_fill(match->uid);
} else { // limit order partially filled
// remove the market order quantity from the limit quantity
Expand All @@ -219,18 +204,13 @@ struct LimitTree {
match->limit->volume -= order->size;
// update the volume for the entire tree
volume -= order->size;
// update the account for the limit order
match->account->limit_partial(match, order);
}
return;
} // else: current match can NOT fill
// decrement the remaining size of the market order
order->size -= match->size;
// update the accounts for the orders
order->account->market_partial(match, order);
match->account->limit_fill(match, order);
// remove the current match from the book
remove(match);
cancel(match);
did_fill(match->uid);
}
}
Expand Down
Loading

0 comments on commit 916f0f5

Please sign in to comment.