回测系统架构:核心组件与设计原则

做量化选股,回测系统就是你的实验室。我见过太多人,策略写得天花乱坠,一回测就露馅。说白了,不是策略不行,是回测系统本身有bug。今天咱们就把回测系统的骨架拆开看看。

一、回测系统的核心组件

一个完整的回测系统,至少包含四个模块:数据、策略、执行、分析。我个人习惯把它们比作「厨房流水线」——数据是食材,策略是菜谱,执行是炒菜,分析是试吃。

核心组件一览:

  • 数据模块:提供历史行情、财务数据、因子数据
  • 策略模块:定义选股逻辑、买卖规则、仓位管理
  • 执行模块:模拟交易撮合、处理滑点、手续费
  • 分析模块:计算收益、风险、归因、绩效指标

嗯,这里要注意:这四个模块必须解耦。我在项目中遇到过,有人把数据获取和策略逻辑写在一起,结果换数据源时整个重写,那叫一个痛苦。

二、数据模块:地基要稳

数据模块是回测的起点。你想想看,数据有偏差,后面全白搭。

数据模块的核心职责:

  • 数据清洗:处理缺失值、复权、停牌标记
  • 数据对齐:不同频率数据(日线、分钟线)的时间戳对齐
  • 数据缓存:避免重复读取,提升回测速度
  • 数据接口:支持本地CSV、数据库、API等多种来源

我的经验:数据清洗时,千万别忽略「未来数据」问题。我曾经用未复权的价格做回测,结果策略收益高得离谱——后来发现是复权因子泄露了未来信息。避坑指南:回测时只能用「当时能看到的数据」。

三、策略模块:灵魂所在

策略模块是量化选股的核心。说白了,就是「什么时候买、买什么、买多少、什么时候卖」。

策略模块的典型结构:

class MyStrategy:
    def __init__(self):
        self.position = {}  # 持仓
        self.cash = 1e6     # 初始资金
    
    def on_data(self, data):
        # 1. 计算信号
        signals = self.calc_signals(data)
        # 2. 生成交易指令
        orders = self.generate_orders(signals)
        return orders
    
    def calc_signals(self, data):
        # 选股逻辑:比如低市盈率+高ROE
        pass
    
    def generate_orders(self, signals):
        # 买卖规则:比如等权重买入前10只
        pass

我个人习惯把策略拆成「信号生成」和「交易执行」两层。这样换选股逻辑时,不用动交易规则。你想想看,如果哪天你想从「低市盈率」换成「动量因子」,只需要改 calc_signals 就行。

四、执行模块:模拟真实交易

执行模块最容易被人忽视。很多新手回测收益很高,一实盘就亏,问题就出在执行模块太理想化。

执行模块要考虑的细节:

  • 滑点模型:按成交额的0.1%-0.3%模拟
  • 手续费:佣金+印花税+过户费
  • 涨跌停限制:涨停买不进,跌停卖不出
  • 交易延迟:信号产生到成交的时间差

避坑指南:我曾经在回测中忽略了「停牌」处理。策略选到一只停牌股,回测系统直接按停牌价成交了。结果实盘时根本买不了,持仓比例全乱套。记住:停牌期间不能交易,这是铁律。

五、分析模块:用数据说话

分析模块负责把回测结果变成可理解的指标。我一般会看这几个维度:

指标类别 具体指标 说明
收益类 年化收益率、累计收益率 策略赚了多少
风险类 最大回撤、波动率、夏普比率 策略稳不稳
交易类 胜率、盈亏比、交易次数 策略活跃度
归因类 因子暴露、行业分布 收益从哪来

嗯,这里要注意:夏普比率高不代表策略好。我见过一个策略,夏普3.0,但最大回撤40%。说白了,高收益往往伴随高风险,得综合看。

六、回测系统的设计原则

做了这么多年回测系统,我总结出三条核心原则:

  1. 模块化:每个模块独立,可替换、可测试。数据模块换源,策略模块不用改一行代码。
  2. 可复现:同样的参数、同样的数据,每次跑结果必须一样。随机种子要固定,多线程要加锁。
  3. 防未来数据:回测时只能用历史数据,不能用未来信息。这是量化回测的底线。

设计原则口诀:

模块解耦好维护,复现结果靠种子。
未来数据是红线,实盘回测两回事。

七、回测系统架构图

下面这张图,是我自己画的一个回测系统架构。你看一眼,基本就明白各模块怎么配合了。

回测系统架构图 数据模块 清洗 · 对齐 · 缓存 策略模块 信号 · 规则 · 仓位 执行模块 撮合 · 滑点 · 费用 分析模块 收益 · 风险 · 归因 数据流 指令 成交记录 绩效反馈 数据模块 → 策略模块 → 执行模块 → 分析模块 → 反馈优化

这张图里,数据模块在最左边,策略模块在中间,执行模块在右边,分析模块在下面。箭头方向就是数据流动的方向。注意那条虚线——分析模块的绩效反馈可以回传给策略模块,用于参数优化。但切记:优化时要用样本外数据,否则就是过拟合。

我的习惯:每次回测完,我都会把分析模块的指标存一份JSON。这样方便对比不同参数、不同时间段的表现。你想想看,如果每次都要重新跑回测,那效率得多低。

好了,回测系统的核心组件和设计原则就聊到这儿。记住:模块化、可复现、防未来数据,这三点是回测系统的生命线。下次咱们聊聊数据模块的细节——怎么处理停牌、复权、以及那些坑人的「幸存者偏差」。


公众号:蓝海数据掘金营,微信deep3321