第四章:系统架构设计——分层架构、模块划分、数据流设计、事件驱动模型
好,咱们进入正题。系统架构这东西,说白了就是给整个回测系统搭骨架。我见过太多人一上来就写代码,写到后面发现改不动、跑不快、查不了bug。嗯,今天我就把我在高频回测系统上踩过的坑、积累的经验,一次性讲清楚。
4.1 为什么必须分层?
先问个问题:你写回测代码时,是不是经常把数据读取、策略逻辑、订单管理全塞在一个大函数里?我以前也这么干过。结果呢?想换个数据源,改了一堆代码;想加个新策略,又得从头捋一遍逻辑。说白了,耦合太紧,牵一发动全身。
我个人习惯,把系统拆成四层:
- 数据层:负责行情数据的获取、清洗、存储
- 策略层:只做一件事——根据行情信号生成交易指令
- 执行层:把交易指令变成真实的订单,处理撮合逻辑
- 风控层:在订单出去之前,做最后一关检查
每一层只跟相邻层打交道。数据层不知道策略层在想什么,策略层也不关心订单怎么执行。这样改起来才舒服。
核心原则:高内聚、低耦合。每个模块只做自己该做的事,别越界。
4.2 模块划分——我踩过的坑
模块怎么分?我建议按职责来,而不是按功能来。举个例子:
| 模块名称 | 职责 | 输入 | 输出 |
|---|---|---|---|
| 行情引擎 | 接收并解析Tick/Bar数据 | 原始行情流 | 标准化行情事件 |
| 策略容器 | 加载策略、管理策略实例 | 行情事件 | 交易信号 |
| 订单管理器 | 维护订单状态、处理成交回报 | 交易信号 | 订单状态更新 |
| 资金管理器 | 计算持仓、盈亏、保证金 | 订单状态 | 资金快照 |
| 风控模块 | 检查下单限制、资金限制 | 交易信号 | 通过/拒绝 |
我曾经犯过一个错:把行情引擎和策略容器写在一起。结果想换一个数据源,策略逻辑也得跟着改。后来我学乖了,每个模块独立编译、独立测试。你想想看,这样改一个模块,其他模块完全不受影响,多省心。
4.3 数据流设计——让数据跑起来
数据流是系统的血脉。高频回测最怕什么?数据跑得慢、数据丢了、数据顺序乱了。我建议用事件驱动的方式组织数据流。
来看一个典型的数据流:
行情源 → 行情引擎 → 行情事件队列 → 策略容器 → 交易信号事件队列 → 风控模块 → 订单管理器 → 成交回报事件队列 → 资金管理器
每个箭头都是一个事件队列。为什么用队列?因为可以解耦。行情引擎只管往队列里塞事件,策略容器只管从队列里取事件。两者速度不一致?没关系,队列能缓冲。
小技巧:队列用无锁环形缓冲区实现,能大幅降低延迟。我在实盘回测中试过,比用Python的queue.Queue快3倍以上。
数据流里还有一个关键点:时间戳。每个事件都必须带上精确的时间戳,否则回测结果就是错的。我记得有一次,因为时间戳精度不够,回测出来的夏普比率比实盘高了0.5,差点误导了策略上线。
4.4 事件驱动模型——核心中的核心
事件驱动,说白了就是「有事件来了,才干活」。没有事件,系统就闲着。这跟高频交易的本质完全吻合——市场在动,我们才动。
事件驱动模型的核心组件有三个:
- 事件源:谁产生事件?行情引擎、策略容器、订单管理器都是事件源
- 事件总线:负责把事件分发给订阅者。我建议用发布-订阅模式
- 事件处理器:每个模块都是一个事件处理器,只处理自己关心的事件
举个例子,行情引擎产生一个Tick事件,事件总线把它发给策略容器。策略容器处理完后,产生一个交易信号事件,事件总线再把它发给风控模块和订单管理器。整个过程是异步的、非阻塞的。
避坑指南:我曾经在事件总线上用了全局锁,结果回测速度直接掉到原来的1/10。后来改成无锁队列+原子操作,才把性能拉回来。记住,高频场景下,锁是万恶之源。
4.5 架构图——一张图说清楚
下面这张SVG图,是我自己画的高频回测系统架构。你看一眼,就能明白整个系统的脉络。
你看,数据从底层往上流,经过每一层处理后,最终形成交易结果。每一层之间通过事件总线连接,互不干扰。这就是我推荐的分层+事件驱动的架构。
4.6 实战中的几个要点
最后,分享几个我在实战中总结的要点:
- 事件类型要标准化:我习惯用枚举定义所有事件类型,比如TickEvent、SignalEvent、OrderEvent、FillEvent。这样事件处理器可以快速判断事件类型,不用做字符串匹配。
- 日志要贯穿全流程:每个事件处理前后都要打日志。我遇到过因为日志没打全,查了一个星期的bug才发现是订单状态更新错了。
- 性能监控不能少:在事件总线上加一个性能计数器,统计每个事件的处理耗时。如果某个模块处理时间突然变长,说明有问题了。
- 回测和实盘用同一套架构:我见过有人回测用一套代码,实盘又重写一套。结果回测跑得飞起,实盘各种问题。记住,架构设计的目标就是让回测和实盘共用同一套核心逻辑。
一句话总结:分层架构让系统好改,事件驱动让系统快跑。两者结合,就是高频回测系统的基石。
好了,这一章就到这里。架构设计是地基,地基打好了,后面写代码才踏实。下一章咱们聊聊数据模块的具体实现,到时候我会把行情引擎的代码一行行拆给你看。
公众号:蓝海资料掘金营,微信deep3321