kraken: engine: refactor 'cancel' ordering
Now that we have a way to reverse-lookup for cancel orders, we are not linear in the number of active orders.
This commit is contained in:
parent
acbae579b3
commit
fae4a9d5c7
|
@ -139,47 +139,68 @@ void Engine::operator()(TradeOrder const& trade_order) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record reverse-lookup info for faster cancelling
|
||||||
|
cancel_reverse_info_.insert({
|
||||||
|
{
|
||||||
|
trade_order.user,
|
||||||
|
trade_order.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
trade_order.side,
|
||||||
|
trade_order.symbol,
|
||||||
|
trade_order.price,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
listener_->on_acknowledgement(trade_order.user, trade_order.id);
|
listener_->on_acknowledgement(trade_order.user, trade_order.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::operator()(CancelOrder const& cancel_order) {
|
void Engine::operator()(CancelOrder const& cancel_order) {
|
||||||
// Assume that the input is well-behaved,
|
|
||||||
// no duplicate (userId, userOrderId) values.
|
|
||||||
auto const matches_order = [&](auto const& data) {
|
auto const matches_order = [&](auto const& data) {
|
||||||
return data.second.user == cancel_order.user
|
return data.second.user == cancel_order.user
|
||||||
&& data.second.id == cancel_order.id;
|
&& data.second.id == cancel_order.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto& [symbol, bid_map] : bids_) {
|
if (auto it = cancel_reverse_info_.find(cancel_order);
|
||||||
auto const it = std::ranges::find_if(bid_map, matches_order);
|
it != cancel_reverse_info_.end()) {
|
||||||
if (it != bid_map.end()) {
|
auto const& [_, info] = *it;
|
||||||
// Set-up automatic call-back in case top-of-book changes
|
|
||||||
auto _ = CallbackOnTopOfBookChange(symbol, *this);
|
|
||||||
|
|
||||||
bid_map.erase(it);
|
// Set-up automatic call-back in case top-of-book changes
|
||||||
listener_->on_acknowledgement(cancel_order.user, cancel_order.id);
|
auto __ = CallbackOnTopOfBookChange(info.symbol, *this);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& [symbol, ask_map] : asks_) {
|
|
||||||
auto const it = std::ranges::find_if(ask_map, matches_order);
|
|
||||||
if (it != ask_map.end()) {
|
|
||||||
// Set-up automatic call-back in case top-of-book changes
|
|
||||||
auto _ = CallbackOnTopOfBookChange(symbol, *this);
|
|
||||||
|
|
||||||
|
switch (info.side) {
|
||||||
|
case Side::ASK: {
|
||||||
|
auto& ask_map = asks_[info.symbol];
|
||||||
|
auto const [begin, end] = ask_map.equal_range(info.price);
|
||||||
|
auto it = std::find_if(begin, end, matches_order);
|
||||||
|
if (it == end) {
|
||||||
|
listener_->on_bad_order(cancel_order.user, cancel_order.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
ask_map.erase(it);
|
ask_map.erase(it);
|
||||||
listener_->on_acknowledgement(cancel_order.user, cancel_order.id);
|
break;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
case Side::BID: {
|
||||||
|
auto& bid_map = bids_[info.symbol];
|
||||||
|
auto const [begin, end] = bid_map.equal_range(info.price);
|
||||||
|
auto it = std::find_if(begin, end, matches_order);
|
||||||
|
if (it == end) {
|
||||||
|
listener_->on_bad_order(cancel_order.user, cancel_order.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bid_map.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cancel_reverse_info_.erase(it);
|
||||||
|
listener_->on_acknowledgement(cancel_order.user, cancel_order.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
listener_->on_bad_order(cancel_order.user, cancel_order.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::operator()(FlushOrder const&) {
|
void Engine::operator()(FlushOrder const&) {
|
||||||
bids_.clear();
|
bids_.clear();
|
||||||
asks_.clear();
|
asks_.clear();
|
||||||
|
cancel_reverse_info_.clear();
|
||||||
|
|
||||||
listener_->on_flush();
|
listener_->on_flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,15 @@ private:
|
||||||
|
|
||||||
std::map<Symbol, instrument_side_data<std::greater<void>>> bids_;
|
std::map<Symbol, instrument_side_data<std::greater<void>>> bids_;
|
||||||
std::map<Symbol, instrument_side_data<std::less<void>>> asks_;
|
std::map<Symbol, instrument_side_data<std::less<void>>> asks_;
|
||||||
|
|
||||||
|
// Map cancel information to allow faster lookups
|
||||||
|
struct CancelReverseInfo {
|
||||||
|
Side side;
|
||||||
|
Symbol symbol;
|
||||||
|
Price price;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<CancelOrder, CancelReverseInfo> cancel_reverse_info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace kraken::engine
|
} // namespace kraken::engine
|
||||||
|
|
Loading…
Reference in a new issue