如何编写自动化回测脚本

wen 实用脚本 2

从零到一:如何编写高精度自动化回测脚本(量化交易核心指南)


目录导读

  1. 为什么你需要一套“会说话”的回测脚本(数据陷阱与过度拟合)
  2. 回测脚本的四大核心模块拆解(数据、策略、执行、分析)
  3. 实战演练:Python + Pandas 编写一个简单均线策略回测
  4. 回测中的“隐形杀手”:未来函数与幸存者偏差
  5. 如何评估回测结果(夏普比率、最大回撤、盈亏比)
  6. 常见问题答疑(Q&A)
  7. 进阶优化:参数寻优与样本外测试

为什么你需要一套“会说话”的回测脚本?

如何编写自动化回测脚本

很多交易者高估了策略的“灵感”,却低估了验证的“科学”,手动在K线图上“看着”赚钱的策略,一旦写成代码回测,往往惨不忍睹,自动化回测脚本的价值在于:它用历史数据,无情地、可重复地、无情绪地检验你的每一个交易假设。 它回答的核心问题是:“如果过去10年我严格按照这个规则交易,最终是盈利还是爆仓?” 没有回测脚本的交易系统,就像没有风洞实验的飞机设计——起飞即坠毁。

回测脚本的四大核心模块拆解

一个标准、严谨的回测脚本,必须包含以下四个独立且清晰的模块:

  • 数据模块(Data Feeder): 负责加载、清洗、对齐历史数据,必须处理复权因子(前复权/后复权)、停牌标记、涨跌停限制。注意: 如果直接使用未复权价格计算收益率,回测结果会虚高。
  • 策略逻辑模块(Strategy Logic): 只定义“何时开仓、何时平仓、仓位多少”,这是纯数学规则,不得包含任何未来数据(如当天收盘价决定当天开盘执行,就是典型的未来函数)。
  • 撮合执行模块(Execution Engine): 模拟手续费、滑点、最小变动价位,流动性差的股票,滑点设置过小会导致回测盈利但实盘巨亏。
  • 绩效分析模块(Performance Analyzer): 输出净值曲线、年化收益、最大回撤、夏普比率、交易胜率等关键指标,并生成资金曲线图。

实战演练:Python + Pandas 编写一个简单均线策略回测

假设我们测试一个经典的“双均线金叉死叉”策略(5日均线上穿20日均线买入,下穿卖出),核心代码逻辑如下(伪代码精简版):

import pandas as pd
import numpy as np
# 步骤1:加载数据(假设df包含收盘价)
df = pd.read_csv('stock_data.csv', parse_dates=['date'])
df['returns'] = df['close'].pct_change()
# 步骤2:计算信号(注意用shift(1)避免未来函数!)
df['ma_fast'] = df['close'].rolling(5).mean()
df['ma_slow'] = df['close'].rolling(20).mean()
df['signal'] = 0
df.loc[df['ma_fast'] > df['ma_slow'], 'signal'] = 1  # 持币状态为1
df['position'] = df['signal'].diff().fillna(0)  # 1为买入,-1为卖出
# 步骤3:执行撮合(考虑万2.5手续费+1个滑点)
trade_unit = 0.001  # 手续费比例
slip_point = 0.01   # 滑点绝对数值
df['strategy_returns'] = df['position'].shift(1) * (df['returns'] - trade_unit - slip_point)
# 步骤4:绩效计算
df['equity_curve'] = (1 + df['strategy_returns']).cumprod()
sharpe = (df['strategy_returns'].mean() / df['strategy_returns'].std()) * np.sqrt(252)
max_drawdown = (df['equity_curve'] / df['equity_curve'].cummax() - 1).min()

上面的shift(1)是绝对高手的细节——它保证了我们用“昨天的信号”交易“今天的价格”,彻底杜绝了盘中偷看数据的问题。

回测中的“隐形杀手”:未来函数与幸存者偏差

  • 未来函数: 最常见的就是“收盘价确定买卖”却用全天最高价成交,解决方法是:所有信号必须基于开盘前的数据(即shift(1)shift(2))。
  • 幸存者偏差: 如果你只回测当前还在交易(未退市)的股票,你会错过那些已经退市的暴跌股,导致回测收益远高于实盘。正确做法: 使用历史某时间点的“全量成分股名单”(含已退市股票)。

如何评估回测结果?(拒绝单看收益率)

  • 最大回撤(MDD): 若回测最大回撤超过30%,心理上很难扛住,策略再好,拿不住也是废纸。
  • 夏普比率(Sharpe): 大于1.5算优秀,低于0.8直接放弃,它衡量的是“每冒一份风险能获得多少超额收益”。
  • 盈亏比与胜率: 胜率低于40%但盈亏比大于3,依然是好策略。不要迷信高胜率,那可能是“截断利润,让亏损奔跑”。

常见问题答疑(Q&A)

  • 问:回测收益率60%,实盘却亏损20%,为什么? 答: 主要检查三点:① 滑点设置是否过低(建议单边至少0.1%);② 是否在回测中使用了“当日开盘买入”但信号是“昨日收盘”计算;③ 是否剔除了ST、停牌、涨跌停无法买入的情况。
  • 问:多参数组合如何寻优,避免过拟合? 答: 采用“滚动窗口前推法(Walk-Forward)”,比如用2010-2019年数据找最优参数,用2020-2023年数据验证。若样本外表现大幅衰减,说明过拟合,永远不要用全量数据调参再全量数据回测。
  • 问:回测脚本运行太慢怎么办? 答: 避免使用循环遍历每一行,改用Pandas矩阵运算;或者用Numba加速;更专业的用vectorbt库,比普通循环快100倍以上。

进阶优化:参数寻优与样本外测试

不要手动试参数,使用GridSearchCVOptuna库自动寻优,但请记住一条铁律:参数越少,策略越稳健,一个需要3个以上参数的策略,大概率是数据挖掘的产物,把最优参数在完全“未见过的数据”(如2015年股灾、2020年疫情)上做样本外测试,只有这里赚钱,策略才算成立。

抱歉,评论功能暂时关闭!