Files
sanguo_quant_live/joinquant_articles/article_03.txt
T

180 lines
4.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
标题: 量化回测中的常见陷阱及规避方法
链接: https://www.joinquant.com/view/community/detail/3
分类: 回测
================================================================================
# 量化回测中的常见陷阱及规避方法
## 一、过拟合陷阱
### 1.1 什么是过拟合
过拟合是指策略在历史数据上表现优异,但在实盘或样本外数据上表现糟糕的现象。
**表现特征**
- 历史回测收益率很高,但样本外测试急剧下降
- 参数微调对结果影响巨大
- 交易次数过多,过度优化
### 1.2 规避方法
**方法1:样本外验证**
```
三段式回测验证:
- 训练集:60%数据(用于策略开发和参数优化)
- 验证集:20%数据(用于参数验证和策略选择)
- 测试集:20%数据(最终验证,只能用一次)
```
**方法2:参数敏感性分析**
不要只看最优参数,要分析参数周围的表现:
```python
# 参数敏感性测试
for param in range(5, 30, 5):
# 测试不同参数下的策略表现
result = backtest(strategy, param=param)
print(f'参数{param}: 收益率{result['return']}, 夏普比率{result['sharpe']}')
```
**方法3:简化策略逻辑**
- 避免过多的条件判断
- 减少参数数量
- 策略逻辑应该有经济学或行为金融学解释
## 二、幸存者偏差
### 2.1 什么是幸存者偏差
幸存者偏差是指回测时只使用了当前还在上市的股票,而忽略了已经退市的股票,导致回测结果过于乐观。
**影响**
- 高估策略收益率
- 低估策略风险
- 实盘表现远不如回测
### 2.2 规避方法
**在聚宽平台上的正确做法**
```python
# 使用包含退市股票的完整数据集
from jqdata import *
def get_stock_pool(date):
# 获取指定日期的指数成分股(包含当时的成分股,而不是当前的)
return get_index_stocks('000300.XSHG', date=date)
# 或者使用all_securities获取所有股票(包含退市的)
all_stocks = list(all_securities)
```
**注意事项**
- 不要使用当前的股票池回测历史数据
- 使用`get_index_stocks`时要指定日期参数
- 考虑ST股票、停牌股票的处理
## 三、未来函数陷阱
### 3.1 什么是未来函数
未来函数是指在策略中使用了当时还无法获得的数据。
**常见类型**
1. 使用未来的财务数据
2. 知道未来的最高价、最低价进行交易
3. 使用停牌后的数据
### 3.2 规避方法
**检查清单**
```
1. 数据获取日期检查
- 确保使用的数据在交易决策时间点之前
2. 避免"先知先觉"
- 不要使用未来才能知道的信息
3. 模拟真实决策流程
- 按照实际交易时的信息获取顺序编写策略
```
**示例对比**
```python
# 错误示例(使用未来数据)
def handle_data(context, data):
for stock in g.stock_pool:
# 获取未来一天的数据(这在实际交易中是不可能的)
future_price = get_price(stock, count=1, end_date=context.current_date + timedelta(days=1))
if future_price > data[stock].close:
order(stock, 100)
# 正确示例
def handle_data(context, data):
for stock in g.stock_pool:
# 只使用当前及之前的数据
hist = history(20, '1d', 'close', [stock])
current_price = data[stock].close
ma20 = hist.mean()
if current_price > ma20:
order(stock, 100)
```
## 四、交易成本低估
### 4.1 常见问题
- 忽略交易手续费
- 低估滑点影响
- 不考虑市场冲击成本
### 4.2 规避方法
**合理设置交易成本**
```python
def initialize(context):
# 设置手续费
set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
# 设置滑点
set_slippage(FixedSlippage(0.002)) # 0.2%的固定滑点
```
**成本参考**
- 买入佣金:万分之三
- 卖出佣金:万分之三 + 千分之一印花税
- 滑点:0.1% - 0.5%(根据股票流动性调整)
## 五、实践案例
某投资者的教训:
**回测表现**
- 年化收益率:60%
- 最大回撤:15%
- 夏普比率:2.5
**实盘表现**3个月):
- 实际收益率:-5%
- 最大回撤:20%
**问题诊断**
1. 过拟合:参数过度优化,只在特定历史时期表现好
2. 幸存者偏差:回测时只用了当前股票,没考虑退市股票
3. 交易成本低估:回测时设置的成本过低
**改进措施**
1. 采用三段式回测验证
2. 使用包含退市股票的完整数据集
3. 提高交易成本设置
4. 简化策略逻辑,减少参数
---
**总结**:回测陷阱是量化交易中最常见的问题,需要从数据质量、策略逻辑、回测设置等多方面进行严格把关。记住:"回测表现只是起点,实盘验证才是关键"。