halo 的技术博客

返回

引言:为什么每个量化投资者都需要回测#

投资圈有一句经典的话:“没有经过回测的策略,就像没有地图的远行。“在量化交易的语境下,这句话更准确的说法是:回测是你用来欺骗自己的最容易的工具,也是最容易被误解的科学仪器

回测的价值不在于告诉你”这个策略能赚多少钱”,而在于帮你系统地理解一个策略在不同市场环境下的行为特征。好的回测让你在真金白银投入之前,已经预演过上百种可能的市场情景。

本文将手把手带你搭建一个基于Python和VectorBT的量化回测框架。不需要金融工程背景,不需要昂贵的Bloomberg终端——只需要Python基础 + 一颗愿意折腾的心。

为什么选VectorBT#

在Python量化回测的生态系统中,有几个主流选择:

框架优势劣势
Backtrader文档丰富、社区大速度慢、代码冗长
ZiplineQuantopian遗产、设计优雅已停止维护
VectorBT极致速度、向量化回测学习曲线稍陡
Backtesting.py轻量、易上手功能有限
自研框架完全可控开发成本高

VectorBT的独特优势在于向量化(Vectorization):它将回测计算从”逐行循环”升级为”一次性矩阵运算”,这意味着你可以在几秒内完成数百万次参数组合的回测——这在传统逐行回测框架中可能需要数小时甚至数天。

对于需要大量参数优化的量化策略来说,VectorBT是一个真正的Game Changer。

VectorBT与主流回测框架速度对比

环境搭建#

先上代码。在终端执行以下命令完成环境配置:

# 创建虚拟环境(推荐)
python3 -m venv quant-env
source quant-env/bin/activate

# 安装核心依赖
pip install vectorbt pandas numpy yfinance plotly
bash

验证安装:

import vectorbt as vbt
print(vbt.__version__)
python

如果输出版本号(2026年最新稳定版为1.6.x),说明环境就绪。

第一性原理:向量化回测到底在做什么#

在深入代码之前,理解VectorBT的核心思想非常重要。传统回测框架的思路是”模拟交易过程”:

for each day in date_range:
    if signal == BUY and no_position:
        buy()
    elif signal == SELL and has_position:
        sell()
plaintext

这种方法的缺点是:循环很慢,而且多参数优化时计算量呈指数级增长。

VectorBT的思路是”矩阵化一切”:

  1. 价格数据 → 矩阵
  2. 交易信号 → 布尔矩阵
  3. 持仓 → 累积矩阵
  4. 收益 → 逐元素运算

因为所有计算都在NumPy/Pandas层面以C语言速度执行,性能有了质的飞跃。

实战:搭建你的第一个回测框架#

Step 1: 获取数据#

import vectorbt as vbt
import pandas as pd
import numpy as np
from datetime import datetime

# 使用yfinance获取A股数据(示例:贵州茅台)
price = vbt.YFData.download(
    '600519.SS',
    start='2020-01-01',
    end='2026-06-01'
).get('Close')

print(f"数据长度: {len(price)} 天")
print(f"起始日期: {price.index[0]}")
print(f"结束日期: {price.index[-1]}")
python

Step 2: 定义交易信号#

# 双均线策略:快线(MA20)上穿慢线(MA60)买入,下穿卖出
fast_ma = vbt.MA.run(price, window=20).ma
slow_ma = vbt.MA.run(price, window=60).ma

# 生成入场和出场信号
entries = fast_ma > slow_ma  # 快线上穿慢线
exits = fast_ma < slow_ma    # 快线下穿慢线

# 去除重复信号:只在交叉瞬间触发
entries = entries.vbt.signals.fshift(1)  # 前移一位,T日收盘信号 → T+1日开盘执行
python

Step 3: 执行回测#

Step 4: 可视化回测结果#

# 资金曲线 + 买卖点
portfolio.plot().show()

# 更丰富的统计分析图
fig = vbt.IndicatorFactory.from_pandas(price).plot(
    trace_kwargs=dict(name='Close Price')
)

# 单独画出回撤曲线
portfolio.drawdown.plot(title='最大回撤分析').show()
python

双均线策略回测资金曲线示例

进阶:参数优化——让你找到最佳组合#

双均线策略的核心参数就是快线和慢线的窗口长度。MA(5,20)、MA(10,30)、MA(20,60)…无数个组合,哪个最好?

VectorBT的参数优化功能让这个问题变得简单:

这个网格搜索覆盖了 5×6 = 30 种参数组合,在VectorBT中执行只需不到1秒。如果用传统的逐行回测,30次完整回测可能需要几分钟。

关键洞察:热力图中夏普比率最高的那个格子,很可能只是过拟合的结果。真正好的参数组合通常是”高原型”——即周围区域的夏普比率都差不多高。如果一个参数组合的夏普比率远高于其邻居,那几乎可以确定是过拟合的产物。

避免回测陷阱:老手都踩过的坑#

回测做得好是科学,做不好是玄学。以下是几个最常见的误区:

1. 前视偏差(Look-ahead Bias)#

症状:策略在回测中表现完美,实盘一塌糊涂。 原因:你的信号计算”不小心”用到了未来数据。比如,用当天的收盘价去做当天的交易决策——现实中你不可能在收盘之前知道收盘价。 解决方案:所有信号必须用 shift(1) 前移,确保T日信号 → T+1日执行。

2. 幸存者偏差(Survivorship Bias)#

症状:回测只用了”现在还活着”的股票数据。 原因:已退市、被收购的股票不在数据集中,导致回测结果虚高。 解决方案:使用包含退市股票的历史数据库,或者在回测中加入随机退市模拟。

3. 过拟合(Overfitting)#

症状:参数优化后夏普比率惊人(比如3.0+),但out-of-sample表现跳水。 原因:你在用同一段数据做”训练”和”测试”。 解决方案

  • 必须划分训练集和测试集
  • 用Walk-forward分析(滚动窗口)
  • 参数空间越大,过拟合风险越高
# Walk-forward分析示例
# 将数据分为12个滚动窗口,每个窗口6个月
(in_sample, out_of_sample) = portfolio.total_return.vbt.rolling_split(
    n=12,             # 12个滚动窗口
    window_len=126,   # 每个窗口126个交易日(约6个月)
    set_lens=(84, 42) # 前4个月训练,后2个月验证
)
python

4. 忽略交易成本#

场景:你发现一个策略年化收益30%,狂喜。但实际上它每天交易5次,每次手续费0.1%,一年下来手续费就吃掉25%…白忙活。 教训:VectorBT的 feesslippage 参数不是摆设,永远填上

总结:从回测到实战的最后一公里#

搭建回测框架只是量化交易的起点。当你完成第一个回测之后,真正的工作才刚开始:

  1. 样本外验证:训练集的表现不算数,验证集才是你唯一该认真看的结果
  2. 计算交易成本:不只是手续费,还有冲击成本——你的买卖行为本身就会影响价格
  3. 小资金实盘:拿1-2万先跑3个月,观察实际滑点和回测滑点的差距
  4. 持续迭代:策略是会过期的。2025年好用的策略在2028年可能已经完全失效

量化交易不是”写一个能赚钱的程序然后躺着收钱”——它是持续的假设、验证、修正、再验证的循环。

VectorBT给了你一把很快的铲子,但能不能挖到金子,仍然取决于你对市场的理解和对风险的管理。

记住:没有完美的策略,只有不断进化的策略。

量化回测框架搭建实战:从零到第一笔虚拟交易
https://blog.halo26812.eu.org/blog/quant-backtesting-vectorbt-guide
Author halo
Published at 2026年6月9日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨