LCOV - code coverage report
Current view: top level - include/app/engine - matching_engine.hpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 8 8
Test Date: 2025-12-19 03:13:09 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /**
       2              :  * @file matching_engine.hpp
       3              :  * @brief 撮合引擎接口
       4              :  *
       5              :  * 提供独立线程运行的撮合引擎,从无锁队列消费订单事件并处理。
       6              :  * 支持行情驱动撮合模式:用户订单与CTP行情盘口比对撮合。
       7              :  */
       8              : 
       9              : #pragma once
      10              : 
      11              : #include <thread>
      12              : #include <atomic>
      13              : #include <functional>
      14              : #include <unordered_map>
      15              : #include <list>
      16              : #include <memory>
      17              : #include "base/blockingconcurrentqueue.h"
      18              : #include "app/engine/order_event.hpp"
      19              : #include "app/engine/order_book.hpp"
      20              : #include "app/model/market_data_snapshot.hpp"
      21              : #include "market/market_data.hpp"
      22              : 
      23              : namespace fix40 {
      24              : 
      25              : // 前向声明
      26              : class InstrumentManager;
      27              : 
      28              : /**
      29              :  * @brief ExecutionReport 回调类型
      30              :  * 
      31              :  * 当撮合引擎产生执行报告时调用此回调。
      32              :  * 参数:sessionID - 目标会话,report - 执行报告
      33              :  */
      34              : using ExecutionReportCallback = std::function<void(const SessionID&, const ExecutionReport&)>;
      35              : 
      36              : /**
      37              :  * @brief 行情更新回调类型
      38              :  * 
      39              :  * 当行情数据更新时调用此回调,用于触发账户价值重算。
      40              :  * 参数:instrumentId - 合约代码,lastPrice - 最新价
      41              :  */
      42              : using MarketDataUpdateCallback = std::function<void(const std::string&, double)>;
      43              : 
      44              : /**
      45              :  * @class MatchingEngine
      46              :  * @brief 行情驱动撮合引擎
      47              :  *
      48              :  * 在独立线程中运行,从无锁队列消费订单事件并处理。
      49              :  * 
      50              :  * @par 与原有撮合引擎的区别
      51              :  * - 原有:用户订单之间互相撮合
      52              :  * - 新版:用户订单与CTP行情盘口比对撮合
      53              :  *
      54              :  * @par 设计特点
      55              :  * - Application::fromApp() 只做轻量的入队操作,快速返回
      56              :  * - 所有订单处理在单线程中串行执行,无需加锁
      57              :  * - 工作线程不会因业务逻辑阻塞
      58              :  * - 支持行情驱动的被动撮合
      59              :  *
      60              :  * @par 撮合规则
      61              :  * - 买单成交条件:买价 >= CTP卖一价
      62              :  * - 卖单成交条件:卖价 <= CTP买一价
      63              :  * - 成交价格:取CTP对手盘价格
      64              :  *
      65              :  * @par 使用示例
      66              :  * @code
      67              :  * MatchingEngine engine;
      68              :  * engine.setExecutionReportCallback([](const SessionID& sid, const ExecutionReport& rpt) {
      69              :  *     // 发送 ExecutionReport 到客户端
      70              :  * });
      71              :  * engine.start();
      72              :  * 
      73              :  * // 从 Application::fromApp() 中提交事件
      74              :  * engine.submit(OrderEvent{OrderEventType::NEW_ORDER, sessionID, order});
      75              :  * 
      76              :  * // 提交行情数据触发撮合
      77              :  * engine.submitMarketData(marketData);
      78              :  * 
      79              :  * // 关闭时
      80              :  * engine.stop();
      81              :  * @endcode
      82              :  */
      83              :         class MatchingEngine {
      84              :         public:
      85              :     /**
      86              :      * @brief 构造撮合引擎
      87              :      */
      88              :     MatchingEngine();
      89              : 
      90              :     /**
      91              :      * @brief 析构函数
      92              :      *
      93              :      * 自动停止引擎线程。
      94              :      */
      95              :     ~MatchingEngine();
      96              : 
      97              :     // 禁止拷贝
      98              :     MatchingEngine(const MatchingEngine&) = delete;
      99              :     MatchingEngine& operator=(const MatchingEngine&) = delete;
     100              : 
     101              :     /**
     102              :      * @brief 启动撮合引擎线程
     103              :      */
     104              :     void start();
     105              : 
     106              :     /**
     107              :      * @brief 停止撮合引擎线程
     108              :      *
     109              :      * 等待当前处理完成后退出。
     110              :      */
     111              :     void stop();
     112              : 
     113              :     /**
     114              :      * @brief 提交订单事件
     115              :      * @param event 订单事件
     116              :      *
     117              :      * 线程安全,可从任意线程调用。
     118              :      * 事件会被放入无锁队列,由引擎线程异步处理。
     119              :      */
     120              :     void submit(const OrderEvent& event);
     121              : 
     122              :     /**
     123              :      * @brief 提交订单事件(移动语义)
     124              :      * @param event 订单事件
     125              :      */
     126              :     void submit(OrderEvent&& event);
     127              : 
     128              :     /**
     129              :      * @brief 检查引擎是否正在运行
     130              :      * @return true 正在运行
     131              :      * @return false 已停止
     132              :      */
     133            3 :     bool is_running() const { return running_.load(); }
     134              : 
     135              :     /**
     136              :      * @brief 设置 ExecutionReport 回调
     137              :      * @param callback 回调函数
     138              :      * 
     139              :      * 必须在 start() 之前调用。
     140              :      */
     141           23 :     void setExecutionReportCallback(ExecutionReportCallback callback) {
     142           23 :         execReportCallback_ = std::move(callback);
     143           23 :     }
     144              : 
     145              :     /**
     146              :      * @brief 设置行情更新回调
     147              :      * @param callback 回调函数
     148              :      * 
     149              :      * 当行情数据更新时调用,用于触发账户价值重算和推送。
     150              :      * 必须在 start() 之前调用。
     151              :      */
     152           20 :     void setMarketDataUpdateCallback(MarketDataUpdateCallback callback) {
     153           20 :         marketDataUpdateCallback_ = std::move(callback);
     154           20 :     }
     155              : 
     156              :     /**
     157              :      * @brief 获取订单簿(只读)
     158              :      * @param symbol 合约代码
     159              :      * @return const OrderBook* 订单簿指针,不存在返回 nullptr
     160              :      */
     161              :     const OrderBook* getOrderBook(const std::string& symbol) const;
     162              : 
     163              :     // =========================================================================
     164              :     // 行情驱动撮合接口
     165              :     // =========================================================================
     166              : 
     167              :     /**
     168              :      * @brief 提交行情数据
     169              :      *
     170              :      * 当新行情到达时,检查虚拟订单簿中是否有可成交的挂单。
     171              :      * 线程安全,可从任意线程调用。
     172              :      *
     173              :      * @param md 行情数据
     174              :      */
     175              :     void submitMarketData(const MarketData& md);
     176              : 
     177              :     /**
     178              :      * @brief 获取行情快照
     179              :      *
     180              :      * @param instrumentId 合约代码
     181              :      * @return const MarketDataSnapshot* 行情快照指针,不存在返回 nullptr
     182              :      */
     183              :     const MarketDataSnapshot* getMarketSnapshot(const std::string& instrumentId) const;
     184              : 
     185              :     /**
     186              :      * @brief 获取挂单列表(只读)
     187              :      *
     188              :      * @param instrumentId 合约代码
     189              :      * @return const std::list<Order>* 挂单列表指针,不存在返回 nullptr
     190              :      */
     191              :     const std::list<Order>* getPendingOrders(const std::string& instrumentId) const;
     192              : 
     193              :     /**
     194              :      * @brief 获取所有挂单数量
     195              :      *
     196              :      * @return 所有合约的挂单总数
     197              :      */
     198              :     size_t getTotalPendingOrderCount() const;
     199              : 
     200              :     // =========================================================================
     201              :     // 管理器设置(用于提供撮合所需的只读信息)
     202              :     // =========================================================================
     203              : 
     204              :     /**
     205              :      * @brief 设置合约管理器
     206              :      * @param instrumentMgr 合约管理器指针
     207              :      *
     208              :      * 撮合引擎会在行情更新时更新合约的涨跌停等信息。
     209              :      *
     210              :      * @note 账户/持仓/风控等业务权威逻辑由上层 Application(如 SimulationApp)负责,
     211              :      * 撮合引擎只负责撮合与订单状态推进。
     212              :      */
     213           20 :     void setInstrumentManager(InstrumentManager* instrumentMgr) { instrumentManager_ = instrumentMgr; }
     214              : 
     215              :     // =========================================================================
     216              :     // 行情驱动撮合核心方法(公开以便测试)
     217              :     // =========================================================================
     218              : 
     219              :     /**
     220              :      * @brief 检查买单是否可成交
     221              :      *
     222              :      * 买单成交条件:买价 >= CTP卖一价
     223              :      *
     224              :      * @param order 待检查的买单
     225              :      * @param snapshot 当前行情快照
     226              :      * @return 可成交返回 true
     227              :      */
     228              :     bool canMatchBuyOrder(const Order& order, const MarketDataSnapshot& snapshot) const;
     229              : 
     230              :     /**
     231              :      * @brief 检查卖单是否可成交
     232              :      *
     233              :      * 卖单成交条件:卖价 <= CTP买一价
     234              :      *
     235              :      * @param order 待检查的卖单
     236              :      * @param snapshot 当前行情快照
     237              :      * @return 可成交返回 true
     238              :      */
     239              :     bool canMatchSellOrder(const Order& order, const MarketDataSnapshot& snapshot) const;
     240              : 
     241              : private:
     242              :     /**
     243              :      * @brief 引擎主循环
     244              :      */
     245              :     void run();
     246              : 
     247              :     /**
     248              :      * @brief 处理单个订单事件
     249              :      * @param event 订单事件
     250              :      */
     251              :     void process_event(const OrderEvent& event);
     252              : 
     253              :     /**
     254              :      * @brief 处理新订单(行情驱动模式)
     255              :      * @param event 订单事件
     256              :      *
     257              :      * 流程:
     258              :      * 1. 尝试立即撮合(与当前行情比对)
     259              :      * 2. 未成交部分挂入虚拟订单簿等待行情触发
     260              :      */
     261              :     void handle_new_order(const OrderEvent& event);
     262              : 
     263              :     /**
     264              :      * @brief 处理撤单请求
     265              :      * @param event 订单事件
     266              :      */
     267              :     void handle_cancel_request(const OrderEvent& event);
     268              : 
     269              :     /**
     270              :      * @brief 处理会话登录
     271              :      * @param event 事件
     272              :      */
     273              :     void handle_session_logon(const OrderEvent& event);
     274              : 
     275              :     /**
     276              :      * @brief 处理会话登出
     277              :      * @param event 事件
     278              :      */
     279              :     void handle_session_logout(const OrderEvent& event);
     280              : 
     281              :     /**
     282              :      * @brief 获取或创建订单簿
     283              :      * @param symbol 合约代码
     284              :      * @return OrderBook& 订单簿引用
     285              :      */
     286              :     OrderBook& getOrCreateOrderBook(const std::string& symbol);
     287              : 
     288              :     /**
     289              :      * @brief 发送 ExecutionReport
     290              :      * @param sessionID 目标会话
     291              :      * @param report 执行报告
     292              :      */
     293              :     void sendExecutionReport(const SessionID& sessionID, const ExecutionReport& report);
     294              : 
     295              :     /**
     296              :      * @brief 生成 ExecID
     297              :      */
     298              :     std::string generateExecID();
     299              : 
     300              :     /**
     301              :      * @brief 生成 OrderID
     302              :      */
     303              :     std::string generateOrderID();
     304              : 
     305              :     // =========================================================================
     306              :     // 行情驱动撮合内部方法
     307              :     // =========================================================================
     308              : 
     309              :     /**
     310              :      * @brief 处理行情更新
     311              :      *
     312              :      * 1. 更新行情快照
     313              :      * 2. 遍历该合约的挂单
     314              :      * 3. 检查是否满足成交条件
     315              :      * 4. 触发成交
     316              :      *
     317              :      * @param md 行情数据
     318              :      */
     319              :     void handleMarketData(const MarketData& md);
     320              : 
     321              :     /**
     322              :      * @brief 尝试撮合订单(行情驱动)
     323              :      *
     324              :      * @param order 待撮合订单
     325              :      * @param snapshot 当前行情快照
     326              :      * @return 是否成交
     327              :      */
     328              :     bool tryMatch(Order& order, const MarketDataSnapshot& snapshot);
     329              : 
     330              :     /**
     331              :      * @brief 执行成交
     332              :      *
     333              :      * @param order 成交的订单
     334              :      * @param fillPrice 成交价格
     335              :      * @param fillQty 成交数量
     336              :      */
     337              :     void executeFill(Order& order, double fillPrice, int64_t fillQty);
     338              : 
     339              :     /**
     340              :      * @brief 将订单添加到挂单列表
     341              :      *
     342              :      * @param order 待挂单的订单
     343              :      */
     344              :     void addToPendingOrders(const Order& order);
     345              : 
     346              :     /**
     347              :      * @brief 从挂单列表移除订单
     348              :      *
     349              :      * @param instrumentId 合约代码
     350              :      * @param clOrdID 客户订单ID
     351              :      * @return 被移除的订单,不存在返回 nullopt
     352              :      */
     353              :     std::optional<Order> removeFromPendingOrders(const std::string& instrumentId, 
     354              :                                                    const std::string& clOrdID);
     355              : 
     356              :     std::atomic<bool> running_{false};  ///< 运行状态
     357              :     std::thread worker_thread_;          ///< 工作线程
     358              :     
     359              :     /// 订单事件队列(无锁阻塞队列)
     360              :     moodycamel::BlockingConcurrentQueue<OrderEvent> event_queue_;
     361              : 
     362              :     /// 订单簿映射:symbol -> OrderBook(保留用于兼容)
     363              :     std::unordered_map<std::string, std::unique_ptr<OrderBook>> orderBooks_;
     364              : 
     365              :             /// 订单到会话的映射:clOrdID -> SessionID(用于成交通知)
     366              :             std::unordered_map<std::string, SessionID> orderSessionMap_;
     367              : 
     368              :             /// 订单到用户ID的映射:clOrdID -> userId(用于日志/追踪,业务处理由上层负责)
     369              :             std::unordered_map<std::string, std::string> orderUserMap_;
     370              : 
     371              :     /// ExecutionReport 回调
     372              :     ExecutionReportCallback execReportCallback_;
     373              : 
     374              :     /// 行情更新回调
     375              :     MarketDataUpdateCallback marketDataUpdateCallback_;
     376              : 
     377              :     /// ExecID 计数器
     378              :     uint64_t nextExecID_ = 1;
     379              : 
     380              :     /// OrderID 计数器
     381              :     uint64_t nextOrderID_ = 1;
     382              : 
     383              :     // =========================================================================
     384              :     // 行情驱动撮合相关成员
     385              :     // =========================================================================
     386              : 
     387              :     /// 行情快照:instrumentId -> snapshot
     388              :     std::unordered_map<std::string, MarketDataSnapshot> marketSnapshots_;
     389              : 
     390              :     /// 虚拟订单簿(挂单列表):instrumentId -> 挂单列表
     391              :     std::unordered_map<std::string, std::list<Order>> pendingOrders_;
     392              : 
     393              :     /// 行情数据队列(无锁阻塞队列)
     394              :             moodycamel::BlockingConcurrentQueue<MarketData> marketDataQueue_;
     395              : 
     396              :             // =========================================================================
     397              :             // 管理器指针(用于提供撮合所需的只读信息)
     398              :             // =========================================================================
     399              : 
     400              :             InstrumentManager* instrumentManager_ = nullptr; ///< 合约管理器
     401              :         };
     402              : 
     403              : } // namespace fix40
        

Generated by: LCOV version 2.0-1