一、回测系统的核心模块
做量化投资,回测系统就是你的实验室。我刚开始做回测时,以为就是拿历史数据跑一遍策略。后来踩了不少坑,才明白一个完整的回测系统,至少需要这几个核心模块。
1.1 数据管理模块
数据是回测的原材料。这个模块负责三件事:
- 数据获取:从交易所、数据商那里拉取行情数据
- 数据清洗:处理缺失值、异常值、复权调整
- 数据存储:用HDF5、Parquet或数据库存起来,方便快速读取
我个人习惯把日线数据存成Parquet格式,读取速度比CSV快10倍不止。嗯,这里要注意:数据对齐是个大坑,不同股票的交易日期可能不一样,必须统一处理。
1.2 策略逻辑模块
这就是你的交易想法。比如「当5日均线上穿20日均线时买入」。这个模块要足够灵活,方便你快速迭代策略。
我一般把策略拆成三个部分:
- 信号生成:根据因子或指标产生买卖信号
- 仓位管理:每次交易多少仓位,要不要加杠杆
- 风控规则:止损、止盈、最大回撤限制
1.3 交易执行模块
信号出来了,怎么模拟成交?这里要考虑:
- 滑点模型:实际成交价和信号价之间的差距
- 手续费:佣金、印花税、过户费
- 流动性限制:大单能不能成交?会不会把价格打飞?
我曾经在回测里忽略滑点,结果实盘时收益直接腰斩。说白了,回测里赚的钱,有一半是理想情况下的幻觉。
1.4 绩效分析模块
跑完回测,你得知道策略到底行不行。这个模块输出:
- 年化收益率、夏普比率、最大回撤
- 胜率、盈亏比、交易次数
- 收益曲线、回撤曲线、月度收益热力图
核心要点:这四个模块缺一不可。数据是基础,策略是灵魂,执行是现实,分析是镜子。
二、数据流设计
数据在回测系统里怎么流动?我画了一张图,你看完就明白了。
数据从左边进来,经过清洗、存储,然后被策略引擎调用。策略产生信号后,交给交易模拟模块执行,最后输出绩效分析结果。整个流程是单向的,但你可以随时回到策略模块调整参数。
我的经验:数据流设计时,一定要考虑增量更新。每天只拉取新增数据,而不是全量重跑。我见过有人每天全量下载A股数据,结果硬盘很快就爆了。
三、事件驱动架构 vs 向量化回测
这是回测系统设计里最核心的抉择。两种方式各有千秋,我分别说说。
3.1 事件驱动架构
说白了,就是模拟真实交易环境。系统按时间顺序处理一个个事件:
- 行情数据到达 → 触发信号计算
- 信号产生 → 触发订单生成
- 订单提交 → 触发成交回报
代码大概长这样:
class EventDrivenBacktest:
def __init__(self):
self.events = []
self.portfolio = Portfolio()
self.strategy = Strategy()
def run(self, data):
for bar in data:
# 处理市场数据事件
event = MarketEvent(bar)
self.events.append(event)
# 策略生成信号
signal = self.strategy.on_bar(bar)
if signal:
order_event = OrderEvent(signal)
self.events.append(order_event)
# 执行订单
fill_event = self.executor.execute(order_event)
self.portfolio.update(fill_event)
优点很明显:
- 更贴近真实交易,能处理复杂逻辑
- 支持异步操作,比如同时监控多个品种
- 容易扩展,加个风控模块很方便
缺点也有:
- 速度慢,尤其是回测几千只股票时
- 代码复杂度高,调试起来头疼
3.2 向量化回测
这种方式就暴力多了。一次性把整个历史数据算完,用矩阵运算代替循环。
import pandas as pd
import numpy as np
def vectorized_backtest(price_data, signals):
# 一次性计算所有信号
positions = signals.shift(1) # 第二天才执行
# 计算每日收益率
returns = price_data.pct_change()
strategy_returns = positions * returns
# 累计收益
cumulative = (1 + strategy_returns).cumprod()
return cumulative
你想想看,用向量化方式回测沪深300所有成分股,可能几秒钟就跑完了。而事件驱动可能要跑几分钟。
但向量化也有硬伤:
- 无法处理条件逻辑,比如「如果今天涨停,明天不买」
- 不能模拟订单簿、滑点等微观结构
- 对高频策略基本不适用
3.3 怎么选?
| 对比维度 | 事件驱动 | 向量化 |
|---|---|---|
| 执行速度 | 慢 | 快 |
| 代码复杂度 | 高 | 低 |
| 真实度 | 高 | 低 |
| 适用场景 | 复杂策略、高频 | 因子研究、低频 |
| 扩展性 | 好 | 差 |
避坑指南:我曾经在因子研究阶段就用了事件驱动,结果每天等回测结果等到下班。后来改成向量化,同样的工作10分钟搞定。记住:研究阶段用向量化,上线前用事件驱动做精细回测。
四、我的建议
如果你刚开始做回测系统,我建议这样:
- 先用向量化快速验证想法。写个几十行的脚本,看看因子有没有预测能力。
- 想法成熟了,再上事件驱动。加入滑点、手续费、流动性限制,看看策略在真实环境下的表现。
- 两个系统并存。向量化做研究,事件驱动做验证。我自己的系统就是双引擎架构。
其实说白了,没有完美的架构,只有适合你的架构。关键是要理解每种方式的优缺点,然后根据你的策略类型和开发阶段来选。
记住:回测系统的目标不是模拟得越真实越好,而是在「真实度」和「开发效率」之间找到平衡点。过度追求真实,可能让你在开发阶段就放弃了。