LCOV - code coverage report
Current view: top level - src/app/engine - matching_engine.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 76.5 % 387 296
Test Date: 2025-12-19 03:13:09 Functions: 87.9 % 33 29

            Line data    Source code
       1              : /**
       2              :  * @file matching_engine.cpp
       3              :  * @brief 撮合引擎实现
       4              :  *
       5              :  * 实现行情驱动撮合模式:用户订单与CTP行情盘口比对撮合。
       6              :  */
       7              : 
       8              : #include "app/engine/matching_engine.hpp"
       9              : #include "app/manager/risk_manager.hpp"
      10              : #include "app/manager/instrument_manager.hpp"
      11              : #include "base/logger.hpp"
      12              : #include <sstream>
      13              : #include <iomanip>
      14              : #include <algorithm>
      15              : 
      16              : namespace fix40 {
      17              : 
      18              : namespace {
      19              : 
      20            6 : const char* sideToString(OrderSide side) {
      21            6 :     return side == OrderSide::BUY ? "Buy" : "Sell";
      22              : }
      23              : 
      24            6 : const char* ordTypeToString(OrderType type) {
      25            6 :     return type == OrderType::MARKET ? "Market" : "Limit";
      26              : }
      27              : 
      28            6 : const char* tifToString(TimeInForce tif) {
      29            6 :     switch (tif) {
      30            6 :         case TimeInForce::DAY: return "Day";
      31            0 :         case TimeInForce::GTC: return "GTC";
      32            0 :         case TimeInForce::IOC: return "IOC";
      33            0 :         case TimeInForce::FOK: return "FOK";
      34            0 :         default: return "Unknown";
      35              :     }
      36              : }
      37              : 
      38              : } // anonymous namespace
      39              : 
      40              : // =============================================================================
      41              : // 辅助函数:构建拒绝单 ExecutionReport
      42              : // =============================================================================
      43              : 
      44            1 : ExecutionReport buildRejectReport(const Order& order, RejectReason reason, const std::string& text) {
      45            1 :     ExecutionReport report;
      46            1 :     report.orderID = order.orderID;
      47            1 :     report.clOrdID = order.clOrdID;
      48            1 :     report.execID = "";  // 调用方需要设置
      49            1 :     report.symbol = order.symbol;
      50            1 :     report.side = order.side;
      51            1 :     report.orderQty = order.orderQty;
      52            1 :     report.price = order.price;
      53            1 :     report.ordType = order.ordType;
      54            1 :     report.ordStatus = OrderStatus::REJECTED;
      55            1 :     report.ordRejReason = static_cast<int>(reason);
      56            1 :     report.text = text;
      57            1 :     report.transactTime = std::chrono::system_clock::now();
      58            1 :     report.execTransType = ExecTransType::NEW;
      59            1 :     return report;
      60            0 : }
      61              : 
      62          535 : MatchingEngine::MatchingEngine() = default;
      63              : 
      64          535 : MatchingEngine::~MatchingEngine() {
      65          535 :     stop();
      66          535 : }
      67              : 
      68           15 : void MatchingEngine::start() {
      69           15 :     if (running_.exchange(true)) {
      70            0 :         return;  // 已经在运行
      71              :     }
      72              :     
      73           30 :     worker_thread_ = std::thread([this]() { run(); });
      74           15 :     LOG() << "[MatchingEngine] Started";
      75              : }
      76              : 
      77          570 : void MatchingEngine::stop() {
      78          570 :     if (!running_.exchange(false)) {
      79          555 :         return;  // 已经停止
      80              :     }
      81              :     
      82              :     // 提交一个空事件唤醒阻塞的 wait_dequeue
      83           15 :     event_queue_.enqueue(OrderEvent{});
      84              :     
      85           15 :     if (worker_thread_.joinable()) {
      86           15 :         worker_thread_.join();
      87              :     }
      88              :     
      89           15 :     LOG() << "[MatchingEngine] Stopped";
      90              : }
      91              : 
      92            0 : void MatchingEngine::submit(const OrderEvent& event) {
      93            0 :     event_queue_.enqueue(event);
      94            0 : }
      95              : 
      96           11 : void MatchingEngine::submit(OrderEvent&& event) {
      97           11 :     event_queue_.enqueue(std::move(event));
      98           11 : }
      99              : 
     100           15 : void MatchingEngine::run() {
     101           26 :     while (running_.load()) {
     102              :         // 先处理行情数据
     103           23 :         MarketData md;
     104           49 :         while (marketDataQueue_.try_dequeue(md)) {
     105            3 :             if (!running_.load()) break;
     106              :             try {
     107            3 :                 handleMarketData(md);
     108            0 :             } catch (const std::exception& e) {
     109            0 :                 LOG() << "[MatchingEngine] Exception processing market data: " << e.what();
     110            0 :             } catch (...) {
     111            0 :                 LOG() << "[MatchingEngine] Unknown exception processing market data";
     112            0 :             }
     113              :         }
     114              : 
     115              :         // 处理订单事件
     116           23 :         OrderEvent event;
     117           23 :         if (event_queue_.wait_dequeue_timed(event, std::chrono::milliseconds(10))) {
     118           20 :             if (!running_.load()) break;
     119              :             
     120              :             try {
     121            8 :                 process_event(event);
     122            0 :             } catch (const std::exception& e) {
     123            0 :                 LOG() << "[MatchingEngine] Exception processing event: " << e.what();
     124            0 :             } catch (...) {
     125            0 :                 LOG() << "[MatchingEngine] Unknown exception processing event";
     126            0 :             }
     127              :         }
     128           23 :     }
     129           15 : }
     130              : 
     131            8 : void MatchingEngine::process_event(const OrderEvent& event) {
     132            8 :     switch (event.type) {
     133            6 :         case OrderEventType::NEW_ORDER:
     134            6 :             handle_new_order(event);
     135            6 :             break;
     136            1 :         case OrderEventType::CANCEL_REQUEST:
     137            1 :             handle_cancel_request(event);
     138            1 :             break;
     139            0 :         case OrderEventType::SESSION_LOGON:
     140            0 :             handle_session_logon(event);
     141            0 :             break;
     142            1 :         case OrderEventType::SESSION_LOGOUT:
     143            1 :             handle_session_logout(event);
     144            1 :             break;
     145            0 :         default:
     146            0 :             LOG() << "[MatchingEngine] Unknown event type";
     147            0 :             break;
     148              :     }
     149            8 : }
     150              : 
     151            6 : void MatchingEngine::handle_new_order(const OrderEvent& event) {
     152            6 :     const Order* orderPtr = event.getOrder();
     153            6 :     if (!orderPtr) {
     154            0 :         LOG() << "[MatchingEngine] Invalid NEW_ORDER event: no order data";
     155            1 :         return;
     156              :     }
     157              :     
     158              :     // 复制订单
     159            6 :     Order order = *orderPtr;
     160            6 :     order.orderID = generateOrderID();
     161            6 :     order.leavesQty = order.orderQty;
     162            6 :     order.status = OrderStatus::PENDING_NEW;
     163              :     
     164            6 :     LOG() << "[MatchingEngine] Processing NewOrderSingle from " << event.sessionID.to_string();
     165            6 :     LOG() << "  ClOrdID: " << order.clOrdID;
     166            6 :     LOG() << "  Symbol: " << order.symbol;
     167            6 :     LOG() << "  Side: " << sideToString(order.side);
     168            6 :     LOG() << "  OrderQty: " << order.orderQty;
     169            6 :     LOG() << "  Price: " << order.price;
     170            6 :     LOG() << "  OrdType: " << ordTypeToString(order.ordType);
     171            6 :     LOG() << "  TimeInForce: " << tifToString(order.timeInForce);
     172              :     
     173              :     // userId 由上层 Application 在收到业务消息时完成身份绑定与校验。
     174              :     // 撮合引擎仍做一次防御性检查,避免产生无法路由或无法归属的订单状态。
     175            6 :     if (event.userId.empty()) {
     176            1 :         LOG() << "[MatchingEngine] Order rejected: empty userId";
     177            1 :         order.status = OrderStatus::REJECTED;
     178            1 :         auto report = buildRejectReport(order, RejectReason::NONE, "Invalid user identity");
     179            1 :         report.execID = generateExecID();
     180            1 :         sendExecutionReport(event.sessionID, report);
     181            1 :         return;
     182            1 :     }
     183              : 
     184              :     // 记录订单与会话的映射
     185            5 :     orderSessionMap_[order.clOrdID] = event.sessionID;
     186              :     // 记录订单与用户ID的映射(用于日志/追踪;资金与持仓更新由上层处理)
     187            5 :     orderUserMap_[order.clOrdID] = event.userId;
     188              :     
     189              :     // 获取行情快照
     190            5 :     auto snapshotIt = marketSnapshots_.find(order.symbol);
     191            5 :     MarketDataSnapshot snapshot;
     192            5 :     if (snapshotIt != marketSnapshots_.end()) {
     193            1 :         snapshot = snapshotIt->second;
     194              :     } else {
     195            4 :         snapshot.instrumentId = order.symbol;
     196              :     }
     197              :     
     198              :     // 尝试立即撮合
     199            5 :     bool matched = false;
     200            5 :     double fillPrice = 0.0;
     201              :     
     202            5 :     if (order.ordType == OrderType::MARKET) {
     203              :         // 市价单处理
     204            0 :         if (order.side == OrderSide::BUY) {
     205            0 :             if (snapshot.hasAsk()) {
     206            0 :                 matched = true;
     207            0 :                 fillPrice = snapshot.askPrice1;
     208              :             } else {
     209              :                 // 无对手盘,拒绝市价单
     210            0 :                 LOG() << "[MatchingEngine] Market order rejected: no ask side";
     211            0 :                 order.status = OrderStatus::REJECTED;
     212              :                 
     213            0 :                 auto report = buildRejectReport(order, RejectReason::NO_COUNTER_PARTY, "No counter party (ask side empty)");
     214            0 :                 report.execID = generateExecID();
     215              :                 
     216            0 :                 sendExecutionReport(event.sessionID, report);
     217            0 :                 orderSessionMap_.erase(order.clOrdID); orderUserMap_.erase(order.clOrdID);
     218            0 :                 return;
     219            0 :             }
     220              :         } else {
     221            0 :             if (snapshot.hasBid()) {
     222            0 :                 matched = true;
     223            0 :                 fillPrice = snapshot.bidPrice1;
     224              :             } else {
     225              :                 // 无对手盘,拒绝市价单
     226            0 :                 LOG() << "[MatchingEngine] Market order rejected: no bid side";
     227            0 :                 order.status = OrderStatus::REJECTED;
     228              :                 
     229            0 :                 auto report = buildRejectReport(order, RejectReason::NO_COUNTER_PARTY, "No counter party (bid side empty)");
     230            0 :                 report.execID = generateExecID();
     231              :                 
     232            0 :                 sendExecutionReport(event.sessionID, report);
     233            0 :                 orderSessionMap_.erase(order.clOrdID); orderUserMap_.erase(order.clOrdID);
     234            0 :                 return;
     235            0 :             }
     236              :         }
     237              :     } else {
     238              :         // 限价单处理
     239            5 :         if (order.side == OrderSide::BUY) {
     240            5 :             if (canMatchBuyOrder(order, snapshot)) {
     241            1 :                 matched = true;
     242            1 :                 fillPrice = snapshot.askPrice1;
     243              :             }
     244              :         } else {
     245            0 :             if (canMatchSellOrder(order, snapshot)) {
     246            0 :                 matched = true;
     247            0 :                 fillPrice = snapshot.bidPrice1;
     248              :             }
     249              :         }
     250              :     }
     251              :     
     252            5 :     if (matched) {
     253              :         // 立即成交
     254            1 :         order.status = OrderStatus::NEW;  // 先设为NEW,executeFill会更新为FILLED
     255            1 :         executeFill(order, fillPrice, order.orderQty);
     256            1 :         orderSessionMap_.erase(order.clOrdID); orderUserMap_.erase(order.clOrdID);
     257              :     } else {
     258              :         // 挂单等待
     259            4 :         order.status = OrderStatus::NEW;
     260            4 :         order.updateTime = std::chrono::system_clock::now();
     261              :         
     262              :         // 发送订单确认
     263            4 :         ExecutionReport report;
     264            4 :         report.orderID = order.orderID;
     265            4 :         report.clOrdID = order.clOrdID;
     266            4 :         report.execID = generateExecID();
     267            4 :         report.symbol = order.symbol;
     268            4 :         report.side = order.side;
     269            4 :         report.orderQty = order.orderQty;
     270            4 :         report.price = order.price;
     271            4 :         report.ordType = order.ordType;
     272            4 :         report.ordStatus = OrderStatus::NEW;
     273            4 :         report.cumQty = 0;
     274            4 :         report.avgPx = 0.0;
     275            4 :         report.leavesQty = order.leavesQty;
     276            4 :         report.transactTime = order.updateTime;
     277            4 :         report.execTransType = ExecTransType::NEW;
     278              :         
     279            4 :         LOG() << "[MatchingEngine] Order " << order.clOrdID << " acknowledged, pending for market data";
     280            4 :         sendExecutionReport(event.sessionID, report);
     281              :         
     282              :         // 添加到挂单列表
     283            4 :         addToPendingOrders(order);
     284            4 :     }
     285            6 : }
     286              : 
     287            1 : void MatchingEngine::handle_cancel_request(const OrderEvent& event) {
     288            1 :     const CancelRequest* req = event.getCancelRequest();
     289            1 :     if (!req) {
     290            0 :         LOG() << "[MatchingEngine] Invalid CANCEL_REQUEST event: no request data";
     291            0 :         return;
     292              :     }
     293              :     
     294            1 :     LOG() << "[MatchingEngine] Processing OrderCancelRequest from " << event.sessionID.to_string();
     295            1 :     LOG() << "  ClOrdID: " << req->clOrdID;
     296            1 :     LOG() << "  OrigClOrdID: " << req->origClOrdID;
     297            1 :     LOG() << "  Symbol: " << req->symbol;
     298              :     
     299            1 :     ExecutionReport report;
     300            1 :     report.clOrdID = req->clOrdID;
     301            1 :     report.origClOrdID = req->origClOrdID;
     302            1 :     report.execID = generateExecID();
     303            1 :     report.symbol = req->symbol;
     304            1 :     report.transactTime = std::chrono::system_clock::now();
     305              :     
     306              :     // 首先尝试从挂单列表中撤单(行情驱动模式)
     307            1 :     auto canceledOrder = removeFromPendingOrders(req->symbol, req->origClOrdID);
     308              :     
     309            1 :     if (!canceledOrder) {
     310              :         // 如果挂单列表中没有,尝试从传统订单簿中撤单(兼容模式)
     311            0 :         auto bookIt = orderBooks_.find(req->symbol);
     312            0 :         if (bookIt != orderBooks_.end()) {
     313            0 :             canceledOrder = bookIt->second->cancelOrder(req->origClOrdID);
     314              :         }
     315              :     }
     316              :     
     317            1 :     if (canceledOrder) {
     318              :         // 撤单成功
     319            1 :         report.orderID = canceledOrder->orderID;
     320            1 :         report.side = canceledOrder->side;
     321            1 :         report.orderQty = canceledOrder->orderQty;
     322            1 :         report.price = canceledOrder->price;
     323            1 :         report.ordType = canceledOrder->ordType;
     324            1 :         report.ordStatus = OrderStatus::CANCELED;
     325            1 :         report.cumQty = canceledOrder->cumQty;
     326            1 :         report.avgPx = canceledOrder->avgPx;
     327            1 :         report.leavesQty = 0;
     328            1 :         report.execTransType = ExecTransType::NEW;  // FIX 4.0: NEW + CANCELED status
     329              :         
     330            1 :         LOG() << "[MatchingEngine] Order " << req->origClOrdID << " canceled";
     331              :         
     332              :         // 清理映射
     333            1 :         orderSessionMap_.erase(req->origClOrdID); orderUserMap_.erase(req->origClOrdID);
     334              :     } else {
     335              :         // 撤单失败(订单不存在或已成交)
     336            0 :         report.ordStatus = OrderStatus::REJECTED;
     337            0 :         report.execTransType = ExecTransType::NEW;
     338            0 :         report.text = "Order not found or already filled";
     339              :         
     340            0 :         LOG() << "[MatchingEngine] Cancel rejected: order " << req->origClOrdID << " not found";
     341              :     }
     342              :     
     343            1 :     sendExecutionReport(event.sessionID, report);
     344            1 : }
     345              : 
     346            0 : void MatchingEngine::handle_session_logon(const OrderEvent& event) {
     347            0 :     LOG() << "[MatchingEngine] Session logged on: " << event.sessionID.to_string();
     348              :     // 会话登录时可以初始化交易状态
     349            0 : }
     350              : 
     351            1 : void MatchingEngine::handle_session_logout(const OrderEvent& event) {
     352            1 :     LOG() << "[MatchingEngine] Session logged out: " << event.sessionID.to_string();
     353              :     
     354              :     // 清理该会话的订单映射(可选:也可以保留用于重连恢复)
     355              :     // 这里简单处理,不主动撤单
     356            1 : }
     357              : 
     358            0 : OrderBook& MatchingEngine::getOrCreateOrderBook(const std::string& symbol) {
     359            0 :     auto it = orderBooks_.find(symbol);
     360            0 :     if (it == orderBooks_.end()) {
     361            0 :         auto [newIt, inserted] = orderBooks_.emplace(
     362            0 :             symbol, std::make_unique<OrderBook>(symbol));
     363            0 :         LOG() << "[MatchingEngine] Created OrderBook for " << symbol;
     364            0 :         return *newIt->second;
     365              :     }
     366            0 :     return *it->second;
     367              : }
     368              : 
     369            0 : const OrderBook* MatchingEngine::getOrderBook(const std::string& symbol) const {
     370            0 :     auto it = orderBooks_.find(symbol);
     371            0 :     if (it != orderBooks_.end()) {
     372            0 :         return it->second.get();
     373              :     }
     374            0 :     return nullptr;
     375              : }
     376              : 
     377            8 : void MatchingEngine::sendExecutionReport(const SessionID& sessionID, const ExecutionReport& report) {
     378            8 :     if (execReportCallback_) {
     379              :         try {
     380            7 :             execReportCallback_(sessionID, report);
     381            0 :         } catch (const std::exception& e) {
     382            0 :             LOG() << "[MatchingEngine] Exception in ExecutionReport callback: " << e.what();
     383            0 :         } catch (...) {
     384            0 :             LOG() << "[MatchingEngine] Unknown exception in ExecutionReport callback";
     385            0 :         }
     386              :     } else {
     387            1 :         LOG() << "[MatchingEngine] No ExecutionReport callback set, report dropped";
     388              :     }
     389            8 : }
     390              : 
     391            8 : std::string MatchingEngine::generateExecID() {
     392            8 :     std::ostringstream oss;
     393            8 :     oss << "EXEC-" << std::setfill('0') << std::setw(10) << nextExecID_++;
     394           16 :     return oss.str();
     395            8 : }
     396              : 
     397            6 : std::string MatchingEngine::generateOrderID() {
     398            6 :     std::ostringstream oss;
     399            6 :     oss << "ORD-" << std::setfill('0') << std::setw(10) << nextOrderID_++;
     400           12 :     return oss.str();
     401            6 : }
     402              : 
     403              : // =============================================================================
     404              : // 行情驱动撮合实现
     405              : // =============================================================================
     406              : 
     407            3 : void MatchingEngine::submitMarketData(const MarketData& md) {
     408            3 :     marketDataQueue_.enqueue(md);
     409            3 : }
     410              : 
     411            8 : const MarketDataSnapshot* MatchingEngine::getMarketSnapshot(const std::string& instrumentId) const {
     412            8 :     auto it = marketSnapshots_.find(instrumentId);
     413            8 :     if (it != marketSnapshots_.end()) {
     414            4 :         return &it->second;
     415              :     }
     416            4 :     return nullptr;
     417              : }
     418              : 
     419            3 : const std::list<Order>* MatchingEngine::getPendingOrders(const std::string& instrumentId) const {
     420            3 :     auto it = pendingOrders_.find(instrumentId);
     421            3 :     if (it != pendingOrders_.end()) {
     422            3 :         return &it->second;
     423              :     }
     424            0 :     return nullptr;
     425              : }
     426              : 
     427            2 : size_t MatchingEngine::getTotalPendingOrderCount() const {
     428            2 :     size_t count = 0;
     429            4 :     for (const auto& [instrumentId, orders] : pendingOrders_) {
     430            2 :         count += orders.size();
     431              :     }
     432            2 :     return count;
     433              : }
     434              : 
     435            3 : void MatchingEngine::handleMarketData(const MarketData& md) {
     436            3 :     std::string instrumentId = md.getInstrumentID();
     437              :     
     438              :     // 1. 更新行情快照
     439            3 :     MarketDataSnapshot& snapshot = marketSnapshots_[instrumentId];
     440            3 :     snapshot.instrumentId = instrumentId;
     441            3 :     snapshot.lastPrice = md.lastPrice;
     442            3 :     snapshot.bidPrice1 = md.bidPrice1;
     443            3 :     snapshot.bidVolume1 = md.bidVolume1;
     444            3 :     snapshot.askPrice1 = md.askPrice1;
     445            3 :     snapshot.askVolume1 = md.askVolume1;
     446            3 :     snapshot.upperLimitPrice = md.upperLimitPrice;
     447            3 :     snapshot.lowerLimitPrice = md.lowerLimitPrice;
     448            3 :     snapshot.updateTime = std::chrono::system_clock::now();
     449              : 
     450              :     // 2. 更新合约管理器中的涨跌停价格
     451            3 :     if (instrumentManager_) {
     452            2 :         instrumentManager_->updateLimitPrices(instrumentId, md.upperLimitPrice, md.lowerLimitPrice);
     453              :     }
     454              : 
     455              :     // 3. 触发行情更新回调(用于账户价值重算)
     456            3 :     if (marketDataUpdateCallback_ && md.lastPrice > 0) {
     457            2 :         marketDataUpdateCallback_(instrumentId, md.lastPrice);
     458              :     }
     459              : 
     460              :     // 4. 遍历该合约的挂单,检查是否可成交
     461            3 :     auto it = pendingOrders_.find(instrumentId);
     462            3 :     if (it == pendingOrders_.end() || it->second.empty()) {
     463            2 :         return;
     464              :     }
     465              : 
     466            1 :     auto& orders = it->second;
     467            1 :     auto orderIt = orders.begin();
     468              :     
     469            2 :     while (orderIt != orders.end()) {
     470            1 :         Order& order = *orderIt;
     471              :         
     472              :         // 尝试撮合
     473            1 :         if (tryMatch(order, snapshot)) {
     474              :             // 成交后移除订单
     475            1 :             orderSessionMap_.erase(order.clOrdID); orderUserMap_.erase(order.clOrdID);
     476            1 :             orderIt = orders.erase(orderIt);
     477              :         } else {
     478            0 :             ++orderIt;
     479              :         }
     480              :     }
     481            3 : }
     482              : 
     483            1 : bool MatchingEngine::tryMatch(Order& order, const MarketDataSnapshot& snapshot) {
     484            1 :     bool canMatch = false;
     485            1 :     double fillPrice = 0.0;
     486              :     
     487            1 :     if (order.side == OrderSide::BUY) {
     488            1 :         canMatch = canMatchBuyOrder(order, snapshot);
     489            1 :         if (canMatch) {
     490            1 :             fillPrice = snapshot.askPrice1;  // 买单以卖一价成交
     491              :         }
     492              :     } else {
     493            0 :         canMatch = canMatchSellOrder(order, snapshot);
     494            0 :         if (canMatch) {
     495            0 :             fillPrice = snapshot.bidPrice1;  // 卖单以买一价成交
     496              :         }
     497              :     }
     498              :     
     499            1 :     if (canMatch) {
     500            1 :         executeFill(order, fillPrice, order.leavesQty);
     501            1 :         return true;
     502              :     }
     503              :     
     504            0 :     return false;
     505              : }
     506              : 
     507          312 : bool MatchingEngine::canMatchBuyOrder(const Order& order, const MarketDataSnapshot& snapshot) const {
     508              :     // 买单成交条件:买价 >= CTP卖一价,且卖盘非空
     509          312 :     if (!snapshot.hasAsk()) {
     510            6 :         return false;
     511              :     }
     512              :     
     513          306 :     if (order.ordType == OrderType::MARKET) {
     514              :         // 市价单只要有卖盘就可成交
     515          101 :         return true;
     516              :     }
     517              :     
     518              :     // 限价单:买价 >= 卖一价
     519          205 :     return order.price >= snapshot.askPrice1;
     520              : }
     521              : 
     522          306 : bool MatchingEngine::canMatchSellOrder(const Order& order, const MarketDataSnapshot& snapshot) const {
     523              :     // 卖单成交条件:卖价 <= CTP买一价,且买盘非空
     524          306 :     if (!snapshot.hasBid()) {
     525            2 :         return false;
     526              :     }
     527              :     
     528          304 :     if (order.ordType == OrderType::MARKET) {
     529              :         // 市价单只要有买盘就可成交
     530          101 :         return true;
     531              :     }
     532              :     
     533              :     // 限价单:卖价 <= 买一价
     534          203 :     return order.price <= snapshot.bidPrice1;
     535              : }
     536              : 
     537            2 : void MatchingEngine::executeFill(Order& order, double fillPrice, int64_t fillQty) {
     538              :     // 计算加权平均成交价(在更新cumQty之前计算)
     539            2 :     int64_t prevCumQty = order.cumQty;
     540            2 :     double prevAvgPx = order.avgPx;
     541              :     
     542              :     // 更新订单状态
     543            2 :     order.cumQty += fillQty;
     544            2 :     order.leavesQty = order.orderQty - order.cumQty;
     545              :     
     546              :     // 计算加权平均成交价
     547            2 :     if (order.cumQty > 0) {
     548              :         // 加权平均:(旧均价 * 旧数量 + 新价格 * 新数量) / 总数量
     549            2 :         order.avgPx = (prevAvgPx * prevCumQty + fillPrice * fillQty) / order.cumQty;
     550              :     }
     551              :     
     552              :     // 更新订单状态
     553            2 :     if (order.leavesQty == 0) {
     554            2 :         order.status = OrderStatus::FILLED;
     555              :     } else {
     556            0 :         order.status = OrderStatus::PARTIALLY_FILLED;
     557              :     }
     558              :     
     559            2 :     order.updateTime = std::chrono::system_clock::now();
     560              :     
     561              :     // =========================================================================
     562              :     // 更新账户和持仓(如果设置了管理器)
     563              :     // =========================================================================
     564            2 :     auto sessionIt = orderSessionMap_.find(order.clOrdID);
     565            2 :     auto userIt = orderUserMap_.find(order.clOrdID);
     566            2 :     std::string accountId;
     567            2 :     if (userIt != orderUserMap_.end()) {
     568            2 :         accountId = userIt->second;  // 使用真实的用户ID
     569              :     }
     570              :     
     571              :     // 注意:持仓和保证金的处理由 SimulationApp::handleFill 统一处理
     572              :     // MatchingEngine 只负责撮合,不直接操作持仓
     573              :     // 这样可以正确处理开平仓逻辑(买入平空、卖出平多)
     574              :     
     575              :     // 发送 ExecutionReport
     576            2 :     if (sessionIt != orderSessionMap_.end()) {
     577            2 :         ExecutionReport report;
     578            2 :         report.orderID = order.orderID;
     579            2 :         report.clOrdID = order.clOrdID;
     580            2 :         report.execID = generateExecID();
     581            2 :         report.symbol = order.symbol;
     582            2 :         report.side = order.side;
     583            2 :         report.orderQty = order.orderQty;
     584            2 :         report.price = order.price;
     585            2 :         report.ordType = order.ordType;
     586            2 :         report.ordStatus = order.status;
     587            2 :         report.cumQty = order.cumQty;
     588            2 :         report.avgPx = order.avgPx;
     589            2 :         report.leavesQty = order.leavesQty;
     590            2 :         report.lastShares = fillQty;
     591            2 :         report.lastPx = fillPrice;
     592            2 :         report.transactTime = order.updateTime;
     593            2 :         report.execTransType = ExecTransType::NEW;
     594              :         
     595            4 :         LOG() << "[MatchingEngine] Order " << order.clOrdID << " filled: "
     596            2 :               << fillQty << " @ " << fillPrice
     597            2 :               << " (cumQty=" << order.cumQty << "/" << order.orderQty << ")";
     598              :         
     599            2 :         sendExecutionReport(sessionIt->second, report);
     600            2 :     }
     601            2 : }
     602              : 
     603            4 : void MatchingEngine::addToPendingOrders(const Order& order) {
     604            4 :     pendingOrders_[order.symbol].push_back(order);
     605            4 :     LOG() << "[MatchingEngine] Order " << order.clOrdID << " added to pending orders for " << order.symbol;
     606            4 : }
     607              : 
     608            1 : std::optional<Order> MatchingEngine::removeFromPendingOrders(const std::string& instrumentId, 
     609              :                                                               const std::string& clOrdID) {
     610            1 :     auto it = pendingOrders_.find(instrumentId);
     611            1 :     if (it == pendingOrders_.end()) {
     612            0 :         return std::nullopt;
     613              :     }
     614              :     
     615            1 :     auto& orders = it->second;
     616            1 :     for (auto orderIt = orders.begin(); orderIt != orders.end(); ++orderIt) {
     617            1 :         if (orderIt->clOrdID == clOrdID) {
     618            1 :             Order removedOrder = *orderIt;
     619            1 :             orders.erase(orderIt);
     620            1 :             return removedOrder;
     621            1 :         }
     622              :     }
     623              :     
     624            0 :     return std::nullopt;
     625              : }
     626              : 
     627              : } // namespace fix40
        

Generated by: LCOV version 2.0-1