撮合引擎测试指南
版本: v0.2.0 更新日期: 2025-12-17 开发团队: @yutiansut @quantaxis
📋 目录
测试概述
测试统计
文件位置: src/matching/engine.rs
测试数量: 76 个
覆盖率: 100% 场景覆盖
运行时间: ~0.17s
测试原则
- 场景驱动: 每个测试对应一个具体的业务场景
- 详细注释: 包含场景描述、撮合逻辑、验证要点
- 独立性: 测试之间相互独立,可单独运行
- 确定性: 测试结果可重复、可预测
测试结构
#![allow(unused)] fn main() { /// 测试编号.场景名 - 简要说明 /// /// 场景: /// - 前置条件描述 /// - 操作步骤描述 /// - 期望结果描述 /// /// 撮合逻辑: /// - 详细的撮合过程说明 /// - 计算公式和验证点 #[test] fn test_scenario_name() { // Arrange: 准备测试环境 // Act: 执行被测操作 // Assert: 验证结果 } }
测试场景分类
场景覆盖矩阵
| 类别 | 场景数 | 覆盖范围 |
|---|---|---|
| 1. 基础功能 | 24 | InstrumentAsset、Engine创建、合约注册 |
| 2. 买卖撮合 | 6 | 买入/卖出、有/无对手盘、价格匹配/不匹配 |
| 3. 成交类型 | 5 | 完整成交、部分成交、多次成交、深度消耗 |
| 4. 撤单操作 | 5 | 正常撤单、不存在订单、买单撤销、卖单撤销 |
| 5. 优先级规则 | 3 | 买方高价优先、卖方低价优先、时间优先 |
| 6. 订单类型 | 4 | 限价单、市价单、改单 |
| 7. 交易状态 | 3 | 连续交易、集合竞价、休市 |
| 8. 多账户 | 3 | 跨账户成交、价格竞争、深度撮合 |
| 9. 边界异常 | 6 | 重复ID、最新价更新、空订单簿、大量订单 |
基础撮合测试
1.1 买入订单无对手盘
#![allow(unused)] fn main() { /// 场景:买单进入空订单簿 /// 期望:订单被接受,进入买盘队列等待 #[test] fn test_buy_order_no_counterparty_accepted() }
撮合逻辑:
买单: 价格84000, 数量10
卖盘: 空
结果: Success::Accepted
订单进入 bid_queue 等待
1.2 卖出订单无对手盘
#![allow(unused)] fn main() { /// 场景:卖单进入空订单簿 /// 期望:订单被接受,进入卖盘队列等待 #[test] fn test_sell_order_no_counterparty_accepted() }
1.3 买入订单有匹配卖单
#![allow(unused)] fn main() { /// 场景:买单价格 >= 卖单价格 /// 期望:立即成交 #[test] fn test_buy_order_with_matching_sell_filled() }
撮合逻辑:
卖单: 价格85000, 数量10 (先挂入)
买单: 价格85000, 数量10
撮合条件: 买价(85000) >= 卖价(85000) ✓
成交价格: 85000 (按对手价成交)
成交数量: 10
结果: 两方都 Success::Filled
1.4 买入价格低于卖出价格
#![allow(unused)] fn main() { /// 场景:买单价格 < 卖单价格 /// 期望:无法成交,双方都进入队列 #[test] fn test_buy_order_price_not_match_accepted() }
撮合逻辑:
卖单: 价格85000 (先挂入)
买单: 价格84000
撮合条件: 买价(84000) < 卖价(85000) ✗
无法成交,买单进入 bid_queue
成交类型测试
2.1 完全成交(数量相等)
#![allow(unused)] fn main() { /// 场景:买卖双方数量完全相等 /// 期望:双方都完全成交 #[test] fn test_exact_volume_match_both_filled() }
计算逻辑:
卖单: 数量10
买单: 数量10
成交: 10手
卖单状态: Filled (剩余0)
买单状态: Filled (剩余0)
2.2 部分成交(新单较小)
#![allow(unused)] fn main() { /// 场景:新订单数量 < 对手盘数量 /// 期望:新单完全成交,对手单部分成交 #[test] fn test_new_order_smaller_new_filled_opposite_partial() }
计算逻辑:
卖单: 数量20 (先挂入)
买单: 数量10 (新单)
成交: min(20, 10) = 10手
卖单状态: PartiallyFilled (剩余10)
买单状态: Filled (剩余0)
2.3 部分成交(新单较大)
#![allow(unused)] fn main() { /// 场景:新订单数量 > 对手盘数量 /// 期望:对手单完全成交,新单部分成交 #[test] fn test_new_order_larger_new_partial_opposite_filled() }
2.4 多次部分成交
#![allow(unused)] fn main() { /// 场景:新订单消耗多个对手盘订单 /// 期望:递归撮合直到无法继续 #[test] fn test_multiple_partial_fills_across_orders() }
撮合逻辑(递归):
卖单1: 价格85000, 数量5
卖单2: 价格85000, 数量5
买单: 价格85000, 数量8
第1轮: 买单(8) vs 卖单1(5) → 成交5, 买单剩余3, 卖单1完成
第2轮: 买单(3) vs 卖单2(5) → 成交3, 买单完成, 卖单2剩余2
2.5 吃掉整个深度
#![allow(unused)] fn main() { /// 场景:大单消耗多档卖盘 /// 期望:按价格优先顺序逐档成交 #[test] fn test_eat_entire_depth() }
撮合顺序:
卖盘深度:
├── 85000 × 5
├── 85100 × 5
└── 85200 × 5
买单: 85200 × 15
成交顺序(卖价升序):
1. 先以85000成交5手
2. 再以85100成交5手
3. 最后以85200成交5手
总成交: 15手
撤单测试
3.1 撤销未成交订单
#![allow(unused)] fn main() { /// 场景:撤销队列中等待的订单 /// 期望:返回 Cancelled #[test] fn test_cancel_pending_order() }
撮合逻辑:
1. 挂入买单,获取 order_id
2. 发送 CancelOrder { id: order_id, direction: BUY }
3. 从 bid_queue 中移除订单
4. 返回 Success::Cancelled
3.2 撤销不存在的订单
#![allow(unused)] fn main() { /// 场景:尝试撤销不存在的订单ID /// 期望:返回 Failed::OrderNotFound #[test] fn test_cancel_nonexistent_order() }
3.3 撤销买入订单
#![allow(unused)] fn main() { /// 场景:撤销买盘中的订单 /// 期望:从 bid_queue 中移除 #[test] fn test_cancel_buy_order() }
3.4 撤销卖出订单
#![allow(unused)] fn main() { /// 场景:撤销卖盘中的订单 /// 期望:从 ask_queue 中移除 #[test] fn test_cancel_sell_order() }
优先级测试
4.1 买方高价优先
#![allow(unused)] fn main() { /// 场景:多个买单,价格不同 /// 期望:高价买单优先成交 #[test] fn test_buy_higher_price_priority() }
验证逻辑:
买单A: 价格85000
买单B: 价格85100 ← 优先
买单C: 价格85200 ← 最优先
卖单进入时,先与最高价85200成交
4.2 卖方低价优先
#![allow(unused)] fn main() { /// 场景:多个卖单,价格不同 /// 期望:低价卖单优先成交 #[test] fn test_sell_lower_price_priority() }
4.3 同价格时间优先
#![allow(unused)] fn main() { /// 场景:相同价格的多个订单 /// 期望:先到的订单优先成交 (FIFO) #[test] fn test_same_price_time_priority_fifo() }
验证逻辑:
买单1: 价格85000, ts=100 ← 先到
买单2: 价格85000, ts=101
买单3: 价格85000, ts=102
卖单进入时,先与 ts=100 的买单1成交
订单类型测试
5.1 限价单撮合
#![allow(unused)] fn main() { /// 场景:标准限价单撮合 /// 期望:按限定价格撮合 #[test] fn test_limit_order_matching() }
5.2 市价单立即成交
#![allow(unused)] fn main() { /// 场景:市价单进入有深度的订单簿 /// 期望:按对手最优价立即成交 #[test] fn test_market_order_fills_immediately() }
5.3 改单
#![allow(unused)] fn main() { /// 场景:修改已挂订单的价格或数量 /// 期望:返回 Amended #[test] fn test_amend_order() }
交易状态测试
6.1 连续交易状态
#![allow(unused)] fn main() { /// 场景:正常交易时段 /// 期望:订单可正常撮合 #[test] fn test_continuous_trading_state() }
6.2 集合竞价期间
#![allow(unused)] fn main() { /// 场景:集合竞价申报期 /// 期望:只接受限价单,不立即撮合 #[test] fn test_auction_period_limit_only() }
6.3 休市状态
#![allow(unused)] fn main() { /// 场景:市场关闭 /// 期望:拒绝所有订单 #[test] fn test_closed_market_rejects_all() }
多账户测试
7.1 不同账户间成交
#![allow(unused)] fn main() { /// 场景:账户A买单 vs 账户B卖单 /// 期望:正常撮合成交 #[test] fn test_multi_account_matching() }
7.2 多账户价格竞争
#![allow(unused)] fn main() { /// 场景:多个账户以不同价格挂买单 /// 期望:最高价账户优先成交 #[test] fn test_multi_account_price_competition() }
7.3 订单簿深度撮合
#![allow(unused)] fn main() { /// 场景:多账户形成订单簿深度 /// 期望:按价格优先级撮合 #[test] fn test_orderbook_depth_matching() }
边界条件测试
8.1 订单ID唯一性
#![allow(unused)] fn main() { /// 场景:连续提交多个订单 /// 期望:每个订单ID都唯一 #[test] fn test_duplicate_order_id_handling() }
8.2 最新价更新
#![allow(unused)] fn main() { /// 场景:成交后 /// 期望:lastprice 更新为成交价 #[test] fn test_lastprice_update_on_trade() }
8.3 空订单簿
#![allow(unused)] fn main() { /// 场景:订单簿完全为空 /// 期望:订单被接受进入队列 #[test] fn test_empty_orderbook_order_pending() }
8.4 连续多次成交
#![allow(unused)] fn main() { /// 场景:多次成交 /// 期望:lastprice 始终为最后成交价 #[test] fn test_lastprice_multiple_trades() }
8.5 大量订单
#![allow(unused)] fn main() { /// 场景:100买单 + 100卖单 + 大激进单 /// 期望:系统稳定,正确撮合 #[test] fn test_high_volume_orders() }
8.6 集合竞价执行
#![allow(unused)] fn main() { /// 场景:集合竞价撮合 /// 期望:按集合竞价规则成交 #[test] fn test_auction_execution() }
运行测试
运行所有撮合引擎测试
cargo test matching::engine::tests --lib
运行特定测试
# 运行买卖撮合相关测试
cargo test matching::engine::tests::test_buy --lib
cargo test matching::engine::tests::test_sell --lib
# 运行撤单相关测试
cargo test matching::engine::tests::test_cancel --lib
# 运行优先级相关测试
cargo test matching::engine::tests::test_priority --lib
cargo test matching::engine::tests::test_higher --lib
cargo test matching::engine::tests::test_lower --lib
查看测试输出
cargo test matching::engine::tests --lib -- --nocapture
运行单个测试
cargo test matching::engine::tests::test_buy_order_with_matching_sell_filled --lib
测试检查清单
新增测试时的检查项
- 测试名称清晰描述场景
- 包含场景说明注释
- 包含撮合逻辑说明
- 使用 Arrange-Act-Assert 结构
- 验证所有预期结果
- 测试可独立运行
- 无外部依赖
代码审查要点
- 边界条件是否覆盖
- 异常场景是否处理
- 并发场景是否考虑
- 性能影响是否评估