共计 1657 个字符,预计需要花费 5 分钟才能阅读完成。
为什么 A 股回测容易失真?
在 A 股市场做量化回测,经常会遇到结果与实盘差距大的问题。这主要源于几个特殊机制:

- 涨跌停限制 :当股票价格触及涨跌停板时,实际无法成交,但简单回测可能忽略这一点
- T+ 1 交易制度 :当日买入的股票次日才能卖出,直接影响策略周转率
- 频繁停牌 :A 股停牌现象普遍,回测需剔除停牌日数据
- 除权除息 :未复权的价格数据会导致计算错误
技术方案选型:向量化 vs 事件驱动
1. Pandas 向量化回测
适合因子选股类策略,特点:
- 整体计算通过矩阵运算完成
- 代码简洁,运行速度快
- 适合处理截面数据(cross-section)
典型代码结构:
# 示例:简单动量策略
returns = df['close'].pct_change(20) # 20 日收益率
selected = returns[returns.rank() > 0.9] # 选择前 10%
2. 事件驱动架构
适合高频、复杂交易规则场景:
- 模拟真实订单流
- 可以精细控制交易逻辑
- 但开发复杂度高
class EventEngine:
def process_order(self, event):
if event.type == 'MARKET':
self.execute_at_best_price(event)
核心实现模块
数据清洗实战
处理 A 股原始数据的典型问题:
# 处理涨跌停(假设已获取涨停价数据)def filter_trading_day(df):
# 剔除停牌日
df = df[df['volume'] > 0]
# 标记涨跌停
df['is_limit_up'] = df['close'] >= df['up_limit']
df['is_limit_down'] = df['close'] <= df['down_limit']
return df
因子标准化
使用 z -score 标准化因子:
from scipy.stats import zscore
factors = ['pe_ratio', 'pb_ratio']
for f in factors:
df[f'{f}_z'] = zscore(df[f])
完整的交易成本模型
# 佣金 + 印花税 + 滑点模型
def calc_transaction_cost(amount, price):
commission = max(5, amount * 0.0003) # 万 3,最低 5 元
tax = amount * 0.001 if amount > 0 else 0 # 卖出印花税
slippage = amount * 0.0002 # 2 个滑点
return commission + tax + slippage
性能优化技巧
内存映射加速
处理大 CSV 文件时:
import pandas as pd
df = pd.read_csv('big_data.csv', memory_map=True)
多进程回测
from multiprocessing import Pool
def backtest_strategy(params):
# 回测逻辑
return sharpe_ratio
with Pool(4) as p:
results = p.map(backtest_strategy, param_list)
避坑指南
避免未来函数
常见错误:
# 错误写法:使用了未来数据
df['signal'] = df['close'].shift(-1) > df['close']
正确做法:
# 只能使用历史数据
df['signal'] = df['close'] > df['close'].shift(1)
处理 T + 1 制度
在回测中需要延迟一天执行卖出:
# positions 记录持仓
today_buy = signals['buy']
positions = today_buy.shift(1) # 次日才能卖出
开放式思考题
- 当策略在 2017-2019 年表现优异但在 2020 年后失效,可能是什么原因?
- 如何设计检测指标来识别过度拟合的策略?
- 对于低频基本面策略,日线回测足够吗?是否需要考虑季度报告发布时间差?
写在最后
搭建一个可靠的 A 股回测系统需要持续迭代。建议从简单策略开始,逐步增加市场微观结构因素的考量。回测只是第一步,实盘中的市场冲击成本、流动性变化等还需要通过模拟盘进一步验证。
正文完
