撮合引擎模块

版本: v0.2.0 更新日期: 2025-12-17 开发团队: @yutiansut @quantaxis


📋 目录

  1. 模块概述
  2. 架构设计
  3. 核心组件
  4. 撮合算法
  5. API参考
  6. 性能指标
  7. 测试覆盖

模块概述

撮合引擎是 QAExchange 的核心交易组件,负责订单的接收、匹配和成交处理。

设计原则

  • 高性能: 单订单处理延迟 P99 < 10μs
  • 高吞吐: 支持 > 300,000 orders/sec
  • 零拷贝: 基于 qars::Orderbook 的零拷贝撮合
  • 并发安全: DashMap + RwLock 无锁设计

模块结构

src/matching/
├── mod.rs              # 模块入口,重导出 qars 类型
├── engine.rs           # ExchangeMatchingEngine 核心实现
├── auction.rs          # 集合竞价增强
├── trade_recorder.rs   # 成交记录器
└── core/
    └── mod.rs          # MatchingEngineCore (独立进程版本)

架构设计

系统架构图

                     ┌─────────────────────────────────────┐
                     │       ExchangeMatchingEngine        │
                     │                                     │
   OrderRequest      │  ┌─────────────────────────────┐   │
   ─────────────────>│  │      DashMap<String,        │   │
                     │  │        Arc<RwLock<          │   │
                     │  │          Orderbook>>>       │   │
                     │  └─────────────────────────────┘   │
                     │              │                     │
                     │              ▼                     │
                     │  ┌─────────────────────────────┐   │
                     │  │    qars::Orderbook          │   │   Success/Failed
                     │  │    ┌─────────┬─────────┐    │   │ ──────────────────>
                     │  │    │bid_queue│ask_queue│    │   │
                     │  │    │(买盘)   │(卖盘)   │    │   │
                     │  │    └─────────┴─────────┘    │   │
                     │  └─────────────────────────────┘   │
                     │                                     │
                     │  ┌─────────────────────────────┐   │
                     │  │      TradeRecorder          │   │   TradeRecord
                     │  │      (成交记录器)           │   │ ──────────────────>
                     │  └─────────────────────────────┘   │
                     └─────────────────────────────────────┘

数据流

1. 订单接收
   OrderRouter ──> ExchangeMatchingEngine.process_order()

2. 订单撮合
   process_order() ──> Orderbook.process_order()
                   ──> order_matching() [递归撮合]

3. 结果处理
   Success::Filled ──> TradeRecorder.record()
                   ──> TradeGateway.notify()

4. 行情更新
   lastprice 更新 ──> MarketDataBroadcaster

核心组件

ExchangeMatchingEngine

主撮合引擎,管理多个合约的订单簿。

#![allow(unused)]
fn main() {
pub struct ExchangeMatchingEngine {
    /// 合约代码 -> 订单簿映射
    orderbooks: DashMap<String, Arc<RwLock<Orderbook<InstrumentAsset>>>>,

    /// 成交记录器
    trade_recorder: Arc<TradeRecorder>,

    /// 合约昨收盘价
    prev_close_map: DashMap<String, f64>,

    /// 当前交易日
    trading_day: Arc<RwLock<String>>,
}
}

InstrumentAsset

合约资产类型,使用字符串哈希作为高效的 Copy 类型。

#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InstrumentAsset(u64);

impl InstrumentAsset {
    pub fn from_code(code: &str) -> Self {
        // 使用 DefaultHasher 生成稳定哈希
    }
}
}

Orderbook (来自 qars)

价格-时间优先的订单簿实现。

#![allow(unused)]
fn main() {
pub struct Orderbook<Asset> {
    pub asset: Asset,
    pub lastprice: f64,
    pub trading_state: TradingState,
    bid_queue: OrderQueue<Asset>,  // 买盘:价格降序
    ask_queue: OrderQueue<Asset>,  // 卖盘:价格升序
    sequence: AtomicU64,           // 订单ID生成器
}
}

撮合算法

价格-时间优先 (Price-Time Priority)

撮合规则:
1. 价格优先
   - 买单:高价优先(愿意出更高价的买方优先成交)
   - 卖单:低价优先(愿意接受更低价的卖方优先成交)

2. 时间优先
   - 相同价格时,先到的订单优先成交

买盘排序:价格降序 → 时间升序
┌─────────┬─────────┬─────────┐
│ 85200   │ 85100   │ 85000   │  ← 价格从高到低
│ ts=100  │ ts=101  │ ts=102  │  ← 同价格按时间
└─────────┴─────────┴─────────┘

卖盘排序:价格升序 → 时间升序
┌─────────┬─────────┬─────────┐
│ 85300   │ 85400   │ 85500   │  ← 价格从低到高
│ ts=200  │ ts=201  │ ts=202  │  ← 同价格按时间
└─────────┴─────────┴─────────┘

撮合流程

#![allow(unused)]
fn main() {
fn process_order(order: OrderRequest) -> Vec<OrderProcessingResult> {
    match order {
        NewLimitOrder { direction, price, volume, .. } => {
            // 1. 检查是否可撮合
            if can_match(direction, price) {
                // 2. 递归撮合直到无法继续
                order_matching(order, results);
            }

            // 3. 剩余数量进入队列
            if remaining_volume > 0 {
                store_new_limit_order(order);
                results.push(Success::Accepted { .. });
            }
        }
        CancelOrder { id, direction } => {
            // 撤单处理
            process_order_cancel(id, direction);
        }
        // ...
    }
}
}

成交类型

类型说明触发条件
Accepted订单被接受订单进入队列等待
Filled完全成交订单数量全部成交
PartiallyFilled部分成交订单数量部分成交
Cancelled已撤销撤单成功
Amended已修改改单成功

API参考

合约注册

#![allow(unused)]
fn main() {
/// 注册新合约
///
/// # 参数
/// - `instrument_id`: 合约代码(如 "cu2501")
/// - `prev_close`: 昨收盘价
///
/// # 返回
/// - `Ok(())`: 注册成功
/// - `Err(ExchangeError)`: 注册失败
pub fn register_instrument(
    &self,
    instrument_id: String,
    prev_close: f64,
) -> Result<(), ExchangeError>
}

订单处理

#![allow(unused)]
fn main() {
/// 处理订单请求
///
/// # 支持的订单类型
/// - NewLimitOrder: 限价单
/// - NewMarketOrder: 市价单
/// - CancelOrder: 撤单
/// - AmendOrder: 改单
///
/// # 返回
/// - Vec<OrderProcessingResult>: 处理结果列表
pub fn process_order(
    &self,
    instrument_id: &str,
    order: OrderRequest<InstrumentAsset>,
) -> Vec<OrderProcessingResult>
}

状态查询

#![allow(unused)]
fn main() {
/// 获取订单簿
pub fn get_orderbook(&self, instrument_id: &str)
    -> Option<Arc<RwLock<Orderbook<InstrumentAsset>>>>

/// 获取所有合约列表
pub fn get_instruments(&self) -> Vec<String>

/// 获取最新价格
pub fn get_last_price(&self, instrument_id: &str) -> Option<f64>

/// 获取昨收盘价
pub fn get_prev_close(&self, instrument_id: &str) -> Option<f64>
}

交易状态控制

#![allow(unused)]
fn main() {
/// 设置交易状态
///
/// # 状态类型
/// - PreAuctionPeriod: 集合竞价申报期
/// - AuctionOrder: 集合竞价下单期
/// - AuctionMatch: 集合竞价撮合期
/// - ContinuousTrading: 连续交易
/// - Closed: 休市
pub fn set_trading_state(
    &self,
    instrument_id: &str,
    state: TradingState,
) -> Result<(), ExchangeError>
}

性能指标

基准测试结果

指标测试值目标值状态
订单吞吐量~368,000 orders/sec> 100,000
撮合吞吐量~800,000 trades/sec> 100,000
单订单延迟 P503.09 μs< 50 μs
单订单延迟 P996.11 μs< 100 μs
撮合延迟 P502.22 μs< 50 μs
撮合延迟 P992.40 μs< 100 μs
深度撮合(100档)190.74 μs< 1 ms

内存使用

  • 单订单内存占用: ~128 bytes
  • 10万订单簿深度: ~15 MB
  • 100合约×1万深度: ~150 MB

测试覆盖

测试统计

test result: ok. 76 passed; 0 failed; 0 ignored

测试分类

类别测试数说明
基础功能24InstrumentAsset、Engine创建等
买卖撮合6买入/卖出基础场景
成交类型5完整/部分成交
撤单场景5撤单成功/失败
价格时间优先3优先级验证
订单类型4限价/市价/改单
交易状态3连续/集合竞价/休市
多账户撮合3跨账户成交
边界条件6异常场景处理
多标的压力3并发多合约
大规模订单3千/万级订单
吞吐量测试3性能基准
延迟测试3延迟统计
并发安全3多线程测试
极端场景4压力/极值测试

详细测试文档请参考:撮合引擎测试指南


相关文档