完整撮合引擎
Full Matching Engine
题目详情
撮合引擎是电子交易所的核心基础设施,要求确定性执行、严格的价格-时间优先规则和健壮的边界条件处理。实现低延迟撮合引擎需要管理复杂订单类型(如 IOC 和 FOK)、维护买卖双侧价格-时间优先队列,并正确处理部分成交和订单过期。
任务:实现 MatchingEngine 类,维护买卖双侧优先队列,支持新增、取消和 IOC/FOK 等订单类型。成交按价格优先、时间优先匹配。
英文原题
Matching engines form the core infrastructure of electronic exchanges, requiring deterministic execution, strict price-time priority rules, and robust edge-case handling. Implementing a low-latency matching engine involves managing complex order types like Immediate or Cancel (IOC) and Fill or Kill (FOK), alongside Self-Trade Prevention (STP). Understanding these microstructure mechanics is crucial in quantitative finance for developing high-frequency trading strategies that interact directly wi
解析
问题分析
撮合引擎是交易所的核心,需要确定性执行和严格的价格-时间优先级。低延迟撮合引擎管理限价单和市价单,支持 IOC(立即成交或取消)和 FOK(全部成交或取消)等复杂订单类型。
实现
class MatchingEngine {
struct Order { uint64_t id; double price; int qty; bool is_buy; uint64_t ts; };
struct Level { double price; std::list<Order> orders; int total_qty{0}; };
std::map<double, Level, std::greater<>> bids_;
std::map<double, Level> asks_;
uint64_t seq_{0};
public:
struct Fill { uint64_t order_id, counter_id; double price; int qty; };
std::vector<Fill> place(Order order) {
order.ts = ++seq_;
auto& book = order.is_buy ? asks_ : bids_;
std::vector<Fill> fills;
for (auto it = book.begin(); it != book.end() && order.qty > 0; ) {
if ((order.is_buy && it->first > order.price) ||
(!order.is_buy && it->first < order.price)) break;
auto& level = it->second;
while (!level.orders.empty() && order.qty > 0) {
auto& head = level.orders.front();
int fill_qty = std::min(order.qty, head.qty);
fills.push_back({order.id, head.id, it->first, fill_qty});
order.qty -= fill_qty; head.qty -= fill_qty;
level.total_qty -= fill_qty;
if (head.qty == 0) level.orders.pop_front();
}
if (level.orders.empty()) it = book.erase(it); else ++it;
}
if (order.qty > 0) {
auto& level = (order.is_buy ? bids_ : asks_)[order.price];
level.orders.push_back(order);
level.total_qty += order.qty;
}
return fills;
}
};复杂度与边界
- 时间复杂度:撮合 O(扫过的价格档位数),通常 ≤ 5 档
- 空间复杂度:O(活跃订单数)
- 边界条件:(1) 自成交检测与拒绝 (2) 价格<=0 拒绝 (3) qty<=0 拒绝 (4) 同价格按时间戳排序
英文解析
Analysis
The matching engine is the core of an exchange, requiring deterministic execution and strict price-time priority. A low-latency matching engine manages limit and market orders, supporting complex order types like IOC (Immediate Or Cancel) and FOK (Fill Or Kill).
Solution
class MatchingEngine {
struct Order { uint64_t id; double price; int qty; bool is_buy; uint64_t ts; };
struct Level { double price; std::list<Order> orders; int total_qty{0}; };
std::map<double, Level, std::greater<>> bids_;
std::map<double, Level> asks_;
uint64_t seq_{0};
public:
struct Fill { uint64_t order_id, counter_id; double price; int qty; };
std::vector<Fill> place(Order order) {
order.ts = ++seq_;
auto& book = order.is_buy ? asks_ : bids_;
std::vector<Fill> fills;
for (auto it = book.begin(); it != book.end() && order.qty > 0; ) {
if ((order.is_buy && it->first > order.price) ||
(!order.is_buy && it->first < order.price)) break;
auto& level = it->second;
while (!level.orders.empty() && order.qty > 0) {
auto& head = level.orders.front();
int fill_qty = std::min(order.qty, head.qty);
fills.push_back({order.id, head.id, it->first, fill_qty});
order.qty -= fill_qty; head.qty -= fill_qty;
level.total_qty -= fill_qty;
if (head.qty == 0) level.orders.erase(level.orders.begin());
}
if (level.total_qty <= 0) it = book.erase(it); else ++it;
}
if (order.qty > 0) addRestingOrder(order);
return fills;
}
};Complexity & Edge Cases
- Time complexity: O(fills at crossed levels) + O(log N) for resting order insertion
- Space complexity: O(active orders + price levels)
- Edge cases: (1) IOC cancels unfilled quantity (2) FOK rejects if total cannot fill (3) Self-match prevention (4) Same-price orders processed in arrival order (price-time priority)
Key Considerations
- Price-time priority: Orders at same price level are matched in arrival order; FIFO queue must be strictly maintained for fairness and regulatory compliance
- Self-trade prevention: Matching engine must detect and reject trades where buyer and seller are the same participant; configurable per exchange rule
- Partial fill semantics: Partially filled orders retain remaining quantity at original price level; must not reorder in priority queue
- Throughput requirement: Matching engine must process 100K+ orders/sec; data structure choice (red-black tree vs skip list) impacts latency at scale