kraken: engine: add trading on cross behaviour
It is limited, and mostly untested, I would need more explicit semantics for the border cases to make it more robust.
This commit is contained in:
parent
68a7e55238
commit
ce9457fabd
|
@ -87,8 +87,9 @@ private:
|
||||||
TopInfo top_info_{};
|
TopInfo top_info_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Engine::Engine(std::shared_ptr<EngineListener> listener)
|
Engine::Engine(std::shared_ptr<EngineListener> listener,
|
||||||
: listener_(listener) {}
|
CrossBehaviour cross_behaviour)
|
||||||
|
: listener_(listener), cross_behaviour_(cross_behaviour) {}
|
||||||
|
|
||||||
void Engine::process_orders(std::vector<Order> const& orders) {
|
void Engine::process_orders(std::vector<Order> const& orders) {
|
||||||
for (auto const& order : orders) {
|
for (auto const& order : orders) {
|
||||||
|
@ -109,8 +110,31 @@ void Engine::operator()(TradeOrder const& trade_order) {
|
||||||
auto& [_, bid_map] = *bid_map_it;
|
auto& [_, bid_map] = *bid_map_it;
|
||||||
if (bid_map.size() > 0
|
if (bid_map.size() > 0
|
||||||
&& bid_map.begin()->first >= trade_order.price) {
|
&& bid_map.begin()->first >= trade_order.price) {
|
||||||
// FIXME: handle matching if enabled
|
if (cross_behaviour_ == CrossBehaviour::REJECT) {
|
||||||
listener_->on_rejection(trade_order.user, trade_order.id);
|
listener_->on_rejection(trade_order.user, trade_order.id);
|
||||||
|
} else {
|
||||||
|
// FIXME: assumes a single trade for the order
|
||||||
|
// FIXME: assumes no remaining orders on both sides
|
||||||
|
auto matching = bid_map.begin();
|
||||||
|
auto const& bid_order = matching->second;
|
||||||
|
|
||||||
|
auto const matching_quantity
|
||||||
|
= std::min(bid_order.quantity, trade_order.quantity);
|
||||||
|
// NOTE: Pick the asking price for matching
|
||||||
|
auto const matching_price = trade_order.price;
|
||||||
|
|
||||||
|
listener_->on_acknowledgement(trade_order.user,
|
||||||
|
trade_order.id);
|
||||||
|
listener_->on_match(bid_order.user, bid_order.id,
|
||||||
|
trade_order.user, trade_order.id,
|
||||||
|
matching_price, matching_quantity);
|
||||||
|
assert(matching_quantity == bid_order.quantity
|
||||||
|
&& "multiple matches not implemented");
|
||||||
|
assert(matching_quantity == trade_order.quantity
|
||||||
|
&& "multiple matches not implemented");
|
||||||
|
|
||||||
|
bid_map.erase(matching);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,8 +148,30 @@ void Engine::operator()(TradeOrder const& trade_order) {
|
||||||
auto& [_, ask_map] = *ask_map_it;
|
auto& [_, ask_map] = *ask_map_it;
|
||||||
if (ask_map.size() > 0
|
if (ask_map.size() > 0
|
||||||
&& ask_map.begin()->first <= trade_order.price) {
|
&& ask_map.begin()->first <= trade_order.price) {
|
||||||
// FIXME: handle matching if enabled
|
if (cross_behaviour_ == CrossBehaviour::REJECT) {
|
||||||
listener_->on_rejection(trade_order.user, trade_order.id);
|
listener_->on_rejection(trade_order.user, trade_order.id);
|
||||||
|
} else {
|
||||||
|
// FIXME: assumes a single trade for the order
|
||||||
|
// FIXME: assumes no remaining orders on both sides
|
||||||
|
auto matching = ask_map.begin();
|
||||||
|
// NOTE: Pick the asking price for matching
|
||||||
|
auto const& [matching_price, ask_order] = *matching;
|
||||||
|
|
||||||
|
auto const matching_quantity
|
||||||
|
= std::min(ask_order.quantity, trade_order.quantity);
|
||||||
|
|
||||||
|
listener_->on_acknowledgement(trade_order.user,
|
||||||
|
trade_order.id);
|
||||||
|
listener_->on_match(trade_order.user, trade_order.id,
|
||||||
|
ask_order.user, ask_order.id,
|
||||||
|
matching_price, matching_quantity);
|
||||||
|
assert(matching_quantity == ask_order.quantity
|
||||||
|
&& "multiple matches not implemented");
|
||||||
|
assert(matching_quantity == trade_order.quantity
|
||||||
|
&& "multiple matches not implemented");
|
||||||
|
|
||||||
|
ask_map.erase(matching);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,21 @@
|
||||||
|
|
||||||
namespace kraken::engine {
|
namespace kraken::engine {
|
||||||
|
|
||||||
|
/// Which behaviour on cross orders.
|
||||||
|
enum class CrossBehaviour {
|
||||||
|
/// Reject the crossing order.
|
||||||
|
REJECT,
|
||||||
|
/// Make the trade with the matching order(s).
|
||||||
|
MATCH,
|
||||||
|
};
|
||||||
|
|
||||||
struct CallbackOnTopOfBookChange;
|
struct CallbackOnTopOfBookChange;
|
||||||
struct EngineListener;
|
struct EngineListener;
|
||||||
|
|
||||||
/// Matching engine which processes orders and keeps the book up-to-date.
|
/// Matching engine which processes orders and keeps the book up-to-date.
|
||||||
struct Engine {
|
struct Engine {
|
||||||
Engine(std::shared_ptr<EngineListener> listener);
|
Engine(std::shared_ptr<EngineListener> listener,
|
||||||
|
CrossBehaviour cross_behaviour = CrossBehaviour::REJECT);
|
||||||
|
|
||||||
/// Process orders, triggerring the listener on each event.
|
/// Process orders, triggerring the listener on each event.
|
||||||
void process_orders(std::vector<Order> const& orders);
|
void process_orders(std::vector<Order> const& orders);
|
||||||
|
@ -25,6 +34,7 @@ private:
|
||||||
void operator()(FlushOrder const& flush_order);
|
void operator()(FlushOrder const& flush_order);
|
||||||
|
|
||||||
std::shared_ptr<EngineListener> listener_;
|
std::shared_ptr<EngineListener> listener_;
|
||||||
|
CrossBehaviour cross_behaviour_;
|
||||||
|
|
||||||
// Symbol, price, side are implicit given the way the book is represented
|
// Symbol, price, side are implicit given the way the book is represented
|
||||||
struct OrderMetaData {
|
struct OrderMetaData {
|
||||||
|
|
Loading…
Reference in a new issue