文章目录
交易系统:Order Manager 交易系统:Order Manager 交易系统:Order Manager
OrderManager 接收策略想要的订单意图,用本地状态和交易所回报来决定下一步该发新单、撤单还是等待。
讲到订单管理,最重要的就是理清楚一张订单可以有哪些状态。在本书当中,订单状态的定义比较简单,没有引入部分成交之类的细分状态。
enum class OMOrderState : int8_t {
INVALID = 0,
PENDING_NEW = 1,
LIVE = 2,
PENIDNG_CANCEL = 3,
DEAD = 4
};
因此 OMOrder 的状态机如下图所示:

OrderManager 成员对象
typedef std::array<OMOrder, sideToIndex(Side::MAX) + 1> OMOrderSideHashMap;
// 这里花里胡哨的,是不是实质上就是买单和卖单分两边来管理?
typedef std::array<OMOrderSideHashMap, ME_MAX_TICKERS> OMOrderTickerSideHashMap;
class OrderManager {
private:
TradeEngine* trade_engine_ = nullptr;
cost RiskManager& risk_manager_;
std::string time_str_;
Common::Logger* logger_ = nullptr;
OMOrderTickerSideHashMap ticker_side_order_;
OrderId next_order_id_ = 1;
}
ticker_side_order_ 是二维数组,可以用“品种 + 买卖方向”来查找订单
typedef std::array<OMOrder, sideToIndex(Side::MAX) + 1> OMOrderSideHashMap;
typedef std::array<OMOrderSideHashMap, ME_MAX_TICKERS> OMOrderTickerSideHashMap;
OMOrderTickerSideHashMap ticker_side_order_;
OMOrder = ticker_side_order_[ticker_id][sideToIndex(Side::BUY / SELL)];
这里的 ticker_side_order_ 这个二维数组保存的是 OMOrder 对象,而不是指向这种对象的指针。我们可以发现,OrderManager 直接持有对象,没有通过内存池分配内存块。原因如下:
- 单一客户端的订单不多,且加以业务规则限制:每个 ticker 的买方和卖方各自最多只能有一张订单
- 单一客户端的订单不像订单簿那样需要频繁插入删除。订单状态变化只需修改已有对象的字段,无需频繁创建、销毁订单对象
- 在
ticker_side_order_这个二维数组构造的时候,已经是固定大小且分配好内存了,因此后续使用的时候不会出现动态内存分配
因此 ticker_side_order_ 当中的 OMOrder 对象不会销毁,而是其字段不断地被修改。在以下几种情况下其字段会修改:
- 由 newOrder() 发出新订单的时候,全部字段重写
- 由 cancelOrder() 撤单的时候,更新
order_state_字段 - 全部成交、撤单成功之类的其它情况下,由
onOrderUpdate(事件类型)修改其字段
OrderManager 向策略提供的唯一接口是 moveOrders()
newOrder()
auto OrderManager::newOrder(OMOrder* order, TickerId ticker_id, Price price, Side side, Qty qty) noexcept {
// 根据传入的参数构造 MEClientRequest
const Exchange::MEClientRequest new_request{Exchange::ClientRequestType::NEW, trade_engine_->clientId(), ticker_id, next_order_id_, side, price, qty};
trade_engine_->sendClientRequest(&new_request);
// 把 order 的状态修改为 PENDING_NEW
// *order 是内部使用的结构体 OMOrder 类型的
*order = {ticker_id, next_order_id_, side, price, qty, OMOrderState::PENDING_NEW};
++next_order_id_;
}
在 newOrder() 当中对于 order 对象修改的字段比较多
cancelOrder()
auto OrderManager::cancelOrder(OMOrder* order) noexcept {
// 根据传入的参数构造 MEClientRequest
const Exchange::MEClientRequest cancel_request{Exchange::ClientRequestType::CANCEL, trade_engine_->clientId(), order->ticker_id_, order->order_id_, order->side_, order->price_, order->qty_};
trade_engine_->sendClientRequest(&cancel_request);
order->order_state_ = OMOrderState::PENDING_CANCEL;
}
撤单的时候对于被撤订单在 ticker_side_order_ 当中的 OMOrder 对象,只修改其 order_state_ 字段,意味着其它字段保持原样,直到同 ticker 同方向有新订单时才被 addOrder() 覆盖掉。
moveOrder()
根据传入的目标 ticker、方向、价格和数量,检查一个 OMOrder 订单的当前状态。如果和期望状态不符,则靠撤单/重发新单来向目标靠拢。之所以说是向目标靠拢,是因为 OrderManager 只负责发单,而达成目标还需要交易所接受 OrderManager 的意图。
auto OrderManager::moveOrder(OMOrder* order, TickerId ticker_id, Price price, Side side, Qty qty) noexcept {
// 根据订单状态来决定操作
switch(order->order_state_) {
case OMOrderState::LIVE: {
// 和期望不符,直接撤单
if (order->price_ != price || order->qty_ != qty) { cancelOrder(order); }
break;
}
case OMOrderState::INVALID:
case OMOrderState::DEAD: {
// 在这种情况下就要重新发单是不是?
if (LIKELY(price != Price_INVALID)) {
const auto risk_result = risk_manager_.checkPreTradeRisk(ticker_id, side, qty);
if (LIKELY(risk_result == RiskCheckResult::ALLOWED)) {
newOrder(order, ticker_id, price, side, qty);
}
else { // 风控未通过,不准发单
logger->log(......);
}
}
break;
}
case OMOrderState::PENDING_NEW:
case OMOrderState::PENDING_CANCEL:
break;
}
}
moveOrders()
这个方法是 OrderManager 面向策略的唯一接口(即前面定义的 newOrder(), cancelOrder() 和 moveOrder() 都是 OrderManager 的内部辅助方法)。策略想要达成发新单、撤单、确保已发出的订单与策略意图相符的目的,都要调用本方法。
auto OrderManager::moveOrders(TickerId ticker_id, Price bid_price, Price ask_price, Qty bid_qty, Qty ask_qty) noexcept {
auto bid_order = &(ticker_side_order_.at(ticker_id).at(sideToIndex(side)));
moveOrder(bid_order, ticker_id, bid_price, Side::BUY, bid_qty);
auto ask_order = &(ticker_side_order_.at(ticker_id)).at(sideToIndex(Side::SELL));
moveOrder(ask_order, ticker_id, ask_price, Side::SELL, ask_qty);
}
这里不存在构造订单对象的过程。注意 OrderManager::ticker_side_order_ 这个二维数组保存的是 OMOrder 对象,且这些对象在这个二维数组构造的时候就被构造了
onOrderUpdate
根据私有订单回调更新 ticker_side_order_ 当中订单的状态
更新后只有三种情况:LIVE、DEAD 或维持现状
在 CANCEL_REJECTED 和 INVALID 的情况下,维持现状
auto onOrderUpdate(const Exchange::MEClientResponse* client_response) noexcept {
auto order = &(ticker_side_order_.at(client_response->ticker_id_).at(sideToIndex(client_response->side_)));
switch(client_response->type_) {
case MEClientResponseType::ACCEPTED: {
order->order_state_ = OMOrderState::LIVE;
break;
}
case MEClientResponseType::FILLED: {
order->order_state_ = OMOrderState::DEAD;
break;
}
case MEClientResponseType::CANCELLED: {
order->order_state_ = OMOrderState::DEAD;
break;
}
case MEClientResponseType::CANCEL_REJECTED:
case MEClientResponseType::INVALID: {
break; // 维持原状不变
}
}
}