21、系统测试:单元测试、集成测试、压力测试、模拟盘测试
做市系统写完了,代码能跑起来,就万事大吉了?
说实话,我见过太多团队,代码写完直接上实盘,结果被行情一冲就崩了。我自己早期也吃过这个亏——一个订单管理的bug,让系统在盘口剧烈波动时重复撤单,亏了不少手续费。从那以后,我对测试这件事,再也不敢马虎。
今天我们就聊聊做市系统的测试。说白了,就是四个层次:单元测试、集成测试、压力测试、模拟盘测试。每一层都有它的意义,缺一不可。
核心观点:测试不是浪费时间,而是保护你的资金安全。一个没有经过充分测试的做市系统,本质上就是在赌运气。
21.1 单元测试:把每个零件都检查一遍
单元测试,就是测试系统里最小的可测试单元。比如一个计算订单价格的函数、一个校验参数的模块、一个风控规则。
我个人习惯,每个核心函数都要写单元测试。为什么?因为做市系统里,很多逻辑是环环相扣的。一个函数算错了价格,后面所有逻辑都会跟着错。
哪些东西必须测?
- 价格计算函数:比如根据盘口数据计算最优报价,要测各种边界情况
- 订单管理模块:创建订单、取消订单、查询订单状态,每个操作都要验证
- 风控规则:最大持仓限制、最大订单金额、最大撤单频率,这些规则必须准确
- 数据解析模块:行情数据、成交回报,格式对不对,字段全不全
我的小技巧:写单元测试时,不要只测正常情况。多想想「如果行情数据突然为空怎么办?」「如果交易所返回了错误码怎么办?」。这些异常情况,才是真正容易出bug的地方。
举个例子,一个简单的价格计算函数测试:
// 测试:根据盘口计算最优买价
function test_calculate_bid_price() {
// 正常情况
let orderbook = { bids: [[100, 10], [99, 20]], asks: [[101, 15], [102, 10]] };
let price = calculate_bid_price(orderbook, 5);
assert_equal(price, 100); // 应该取最优买价
// 盘口为空的情况
orderbook = { bids: [], asks: [] };
price = calculate_bid_price(orderbook, 5);
assert_equal(price, null); // 应该返回null
// 盘口深度不足的情况
orderbook = { bids: [[100, 1]], asks: [[101, 15]] };
price = calculate_bid_price(orderbook, 5);
assert_equal(price, null); // 深度不够,不报价
}
21.2 集成测试:看看零件能不能配合工作
单元测试过了,不代表系统就能正常工作。为什么?因为模块之间要配合。比如行情模块把数据传给策略模块,策略模块再传给订单模块,中间任何一个环节出问题,整个链条就断了。
集成测试,就是把这些模块串起来,看看它们能不能协同工作。
集成测试的重点:
- 数据流是否通畅:行情数据能不能正确传递给策略模块
- 接口是否匹配:模块之间的输入输出格式是否一致
- 时序是否正确:先收到行情,再计算策略,最后下单,这个顺序不能乱
- 错误处理是否到位:一个模块出错了,其他模块能不能正确处理
注意:集成测试最容易发现「接口不匹配」的问题。我曾经遇到过一个情况:行情模块返回的价格是字符串类型,但策略模块期望的是浮点数。单元测试各自都过了,但一集成就报错。这种问题,集成测试一跑就能发现。
21.3 压力测试:看看系统能扛多大压力
做市系统,最怕的就是行情剧烈波动。平时风平浪静,系统跑得稳稳的。但一旦行情爆发,订单量暴增,系统可能就扛不住了。
压力测试,就是模拟极端行情,看看系统能不能撑住。
压力测试要测什么?
| 测试项 | 说明 | 目标 |
|---|---|---|
| 高并发订单 | 模拟大量订单同时到达 | 系统不崩溃,订单不丢失 |
| 高频行情 | 模拟行情数据快速更新 | 策略能及时响应,不延迟 |
| 网络延迟 | 模拟网络不稳定、延迟高 | 系统能正确处理超时和重连 |
| 资源耗尽 | 模拟内存、CPU、连接数耗尽 | 系统有保护机制,不崩溃 |
我个人习惯,压力测试要跑到正常负载的 5-10倍。比如平时每秒处理100笔订单,那就压到每秒500-1000笔。只有这样才能发现系统的瓶颈在哪里。
避坑指南:我曾经压测时发现,系统在每秒300笔订单时还能正常处理,但到了500笔时,内存占用突然飙升。后来一查,是某个缓存模块没有设置上限,导致数据越积越多。这种问题,不压到极限是发现不了的。
21.4 模拟盘测试:在真实环境中跑一遍
单元测试、集成测试、压力测试都过了,是不是就可以上实盘了?
别急,还有最后一步:模拟盘测试。
模拟盘测试,就是把系统接入交易所的模拟环境(或者用历史数据回放),用真实的市场数据来跑。这时候,系统会像实盘一样运行,但不会产生真实的交易。
模拟盘测试的价值:
- 验证策略逻辑:在真实行情下,策略能不能按预期运行
- 检查订单流程:从下单到成交到回报,整个流程是否顺畅
- 发现隐藏问题:有些问题在模拟环境中不会出现,但在真实行情下就会暴露
- 积累运行数据:记录系统的运行日志,方便后续分析和优化
我的建议:模拟盘测试至少跑 1-2周。不要只跑一两天就急着上实盘。因为有些问题,比如周末的行情、月末的结算、节假日的特殊规则,只有跑足够长的时间才能遇到。
21.5 测试流程总结
这四个层次的测试,不是互相替代的关系,而是层层递进的关系。我习惯用下面这张图来表示:
你看,从单元测试到模拟盘测试,是一个逐步递进的过程。每一层都解决了不同的问题,每一层都不可或缺。
最后提醒一句:不要跳过任何一层测试。我见过有人觉得「单元测试太麻烦,直接上模拟盘吧」,结果模拟盘跑了一周,发现一个基础函数算错了,所有数据都得重来。嗯,这种教训,一次就够了。