01-回测理论

预计学习时间:1 小时

难度:⭐⭐

核心问题:什么是回测?为什么要回测?回测能告诉我们什么?


什么是回测?

定义

回测(Backtesting):用历史数据模拟交易过程,验证投资策略在过去的表现。

简单来说,就是”如果当时用了这个策略,会赚多少钱?

┌────────────────────────────────────────────────────────────────┐
│                        回测的基本思路                          │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  历史数据                策略规则                模拟交易        │
│  ├─ 价格                 ├─ 买入条件            ├─ 何时买      │
│  ├─ 成交量               ├─ 卖出条件            ├─ 买多少      │
│  ├─ 财务数据             ├─ 仓位管理            ├─ 何时卖      │
│  └─ 其他信息             └─ 风控规则            └─ 结果如何    │
│                                                                │
└────────────────────────────────────────────────────────────────┘

一个简单的类比

想象你在训练一个自动驾驶系统:

步骤自动驾驶量化投资
1收集道路数据收集历史行情数据
2设定驾驶规则设定交易策略
3用历史录像测试算法用历史数据回测策略
4评估安全性/效率评估收益/风险
5实车路测模拟盘/实盘交易

关键点:历史测试(回测)≠ 实际表现(路测/实盘)


回测的核心目的

1. 验证 Alpha 的存在性

Alpha(超额收益):策略收益超出基准收益的部分。

# 假设:低波动率股票未来表现更好
# 回测目的:这个假设在历史上是否成立?
 
策略年化收益 = 15%
基准年化收益 = 10%
Alpha = 5%
 
# 这 5% 是真实的 Alpha 还是运气?
# 回测帮助我们判断

核心问题:策略赚的钱是靠能力还是靠运气

2. 评估风险收益特征

回测不仅告诉我们”赚多少”,还告诉我们”怎么赚”和”可能亏多少”:

风险指标说明
最大回撤历史上最惨的亏损是多少
波动率收益的稳定性如何
Sharpe 比率承担单位风险获得的收益
胜率盈利交易占比

3. 估计交易成本

策略的毛收益(不考虑成本)和净收益(扣除成本)可能天差地别:

策略毛收益:    +20%
交易成本:      -8%  # 高频策略可能更高
实际净收益:    +12%

# 如果成本 > 收益,策略就不可行

4. 优化策略参数

回测可以帮助找到”最优”参数:

# 移动平均线策略
# 参数:短期均线周期、长期均线周期
 
# 测试不同组合
短期参数 = [5, 10, 20, 30]
长期参数 = [30, 60, 120, 250]
 
# 回测找到历史表现最好的参数组合

⚠️ 警惕:参数过度优化是回测陷阱之一(详见第05节)


回测的完整流程

┌─────────────────────────────────────────────────────────────────────┐
│                        回测完整流程图                               │
└─────────────────────────────────────────────────────────────────────┘

  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
  │  数据准备 │ →  │ 信号生成 │ →  │ 组合构建 │ →  │ 执行模拟 │
  └──────────┘    └──────────┘    └──────────┘    └──────────┘
       │                │                │                │
       ↓                ↓                ↓                ↓
  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
  │ 价格数据 │    │ 模型预测 │    │ 仓位分配 │    │ 订单成交 │
  │ 基准数据 │    │ 规则信号 │    │ 风控约束 │    │ 成本计算 │
  │ 股票池   │    │           │    │           │    │ 持仓更新 │
  └──────────┘    └──────────┘    └──────────┘    └──────────┘
                                                    │
                                                    ↓
                                            ┌──────────┐
                                            │ 绩效评估 │
                                            └──────────┘
                                                    │
                                                    ↓
                                            ┌──────────┐
                                            │ 分析报告 │
                                            │ 可视化   │
                                            └──────────┘

阶段详解

阶段1:数据准备

import pandas as pd
 
# 需要的数据
- 价格数据:开高低收 (OHLC)
- 成交量数据
- 基准数据(如沪深300)
- 股票池(哪些股票可以交易)
- 停牌/涨跌停信息
- 复权因子(价格调整)

数据质量决定回测质量 → Garbage In, Garbage Out

阶段2:信号生成

# 两种常见方式
 
# 方式1:规则信号
# 例如:价格 > 20日均线,买入
signal = price > ma(price, 20)
 
# 方式2:模型信号
# 例如:LightGBM 输出预测值
signal = model.predict(features)

阶段3:组合构建

# 从信号到持仓
signal → 排名 → 选股 → 分配权重
 
# 例如:Top-K 等权
# 选择预测值最高的 30 只股票,每只分配 1/30 权重

详见第02节

阶段4:执行模拟

# 模拟真实交易
- 订单生成(根据目标仓位)
- 成交判断(是否涨停/停牌)
- 成本计算(佣金、印花税、滑点)
- 持仓更新

阶段5:绩效评估

# 计算各类指标
- 收益率
- 风险指标
- 风险调整收益
- 交易统计

详见第04节


回测 vs 前向测试 vs 纸上交易 vs 实盘交易

类型数据来源目的可靠性
回测历史数据快速验证策略想法⭐⭐ 依赖假设
前向测试历史数据(滚动窗口)模拟实盘体验⭐⭐⭐ 更接近实盘
纸上交易实时数据(模拟盘)验证实盘可行性⭐⭐⭐⭐ 接近真实
实盘交易实时数据(真金白银)赚取收益⭐⭐⭐⭐⭐ 真实可靠

对比说明

回测 ←──────────────→ 前向测试
(历史一次性测试)    (滚动窗口模拟实盘)

纸上交易 ←──────────→ 实盘交易
(模拟资金)          (真实资金)

最佳实践

  1. 回测 → 纸上交易 → 小资金实盘 → 逐步放大
  2. 每一步都验证通过,再进入下一步

一个极简回测示例

用 20 行代码展示完整的回测流程:

import numpy as np
import pandas as pd
 
# ===== 1. 数据准备 =====
np.random.seed(42)
dates = pd.date_range('2020-01-01', '2023-12-31', freq='D')
n_stocks = 50
 
# 模拟价格数据(随机游走)
returns = np.random.randn(len(dates), n_stocks) * 0.02
prices = 100 * np.exp(np.cumsum(returns, axis=0))
prices_df = pd.DataFrame(prices, index=dates, columns=[f'S{i}' for i in range(n_stocks)])
 
# ===== 2. 信号生成 =====
# 简单策略:过去5天涨幅最小的股票,未来会反弹
momentum_5d = prices_df.pct_change(5)
signal = -momentum_5d.rank(axis=1)  # 跌越多排名越高
 
# ===== 3. 组合构建 =====
# Top-10 等权
def construct_portfolio(signal, top_k=10):
    top_stocks = signal.apply(lambda x: x.nlargest(top_k).index, axis=1)
    weights = pd.DataFrame(0, index=signal.index, columns=signal.columns)
    for date, stocks in top_stocks.items():
        weights.loc[date, stocks] = 1 / top_k
    return weights
 
target_weights = construct_portfolio(signal)
 
# ===== 4. 执行模拟 =====
# T+1,每日调仓
portfolio_value = pd.Series(1.0, index=dates[6:])  # 初始净值1
position = target_weights.shift(1).fillna(0)  # T+1
 
daily_returns = (prices_df.pct_change() * position).sum(axis=1)
portfolio_value = (1 + daily_returns).cumprod()
 
# ===== 5. 绩效评估 =====
total_return = (portfolio_value.iloc[-1] - 1) * 100
annual_return = (portfolio_value.iloc[-1] ** (252 / len(portfolio_value)) - 1) * 100
volatility = daily_returns.std() * np.sqrt(252) * 100
sharpe = (annual_return - 3) / volatility  # 假设无风险利率3%
 
print(f"""
=== 回测结果 ===
总收益率: {total_return:.2f}%
年化收益: {annual_return:.2f}%
年化波动: {volatility:.2f}%
Sharpe:   {sharpe:.2f}
""")

输出示例

=== 回测结果 ===
总收益率: 12.34%
年化收益: 4.12%
年化波动: 18.56%
Sharpe:   0.06

这个例子虽然简单,但包含了回测的核心要素:

  1. ✅ 数据准备
  2. ✅ 信号生成
  3. ✅ 组合构建
  4. ✅ 执行模拟
  5. ✅ 绩效评估

回测的局限性

1. 历史不代表未来

┌────────────────────────────────────────────────────────────┐
│                    最危险的一句话                           │
├────────────────────────────────────────────────────────────┤
│                                                            │
│   "过去3年这个策略每年都赚20%,明年肯定也能赚!"            │
│                                                            │
│                        ❌ 错误!                           │
│                                                            │
└────────────────────────────────────────────────────────────┘

原因

  • 市场结构变化(交易规则、参与者、技术)
  • 策略容量限制(资金规模变大后失效)
  • 市场制度变化(T+0 改 T+1、涨跌停调整)

2. 回测假设 vs 实盘现实

假设实盘
所有订单都能成交涨跌停/停牌/流动性不足
成本是固定的冲击成本随资金规模增加
信号即时执行延迟、系统故障
市场微观结构可忽略实际影响很大

3. 过拟合风险

完美的回测曲线 = 可疑!

如果一个策略在回测中:
- 每个月都赚钱
- 回撤很小
- Sharpe > 3

→ 很可能过拟合了

详见第05节


良好回测系统的设计原则

1. 模块化设计

# 好的设计
class BacktestEngine:
    def __init__(self):
        self.data_loader = DataLoader()
        self.signal_generator = SignalGenerator()
        self.portfolio_builder = PortfolioBuilder()
        self.executor = Executor()
        self.evaluator = Evaluator()
 
    def run(self):
        # 各模块独立,可替换
        pass
 
# 不好的设计:全部写在一起,难以维护和调试

2. 可复现性

# 设置随机种子
np.random.seed(42)
 
# 记录所有参数
params = {
    'start_date': '2020-01-01',
    'end_date': '2023-12-31',
    'top_k': 30,
    'rebalance_freq': 'weekly',
}
 
# 保存完整的实验记录

3. 可视化和报告

一图胜千表

好的回测系统应该输出:
- 累计收益曲线
- 回撤图
- 月度收益热力图
- 滚动 Sharpe
- ...

4. 性能分析工具

# 不仅能跑回测,还能分析问题
- 哪个时期表现最差?
- 换手率是否过高?
- 哪些股票贡献最大?
- 交易成本占比多少?

核心知识点总结

┌────────────────────────────────────────────────────────────────┐
│                    01-回测理论 核心要点                         │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  1. 回测定义                                                   │
│     用历史数据模拟交易,验证策略有效性                          │
│                                                                │
│  2. 回测目的                                                   │
│     ├─ 验证 Alpha                                              │
│     ├─ 评估风险收益                                            │
│     ├─ 估计交易成本                                            │
│     └─ 优化策略参数                                            │
│                                                                │
│  3. 回测流程                                                   │
│     数据准备 → 信号生成 → 组合构建 → 执行模拟 → 绩效评估       │
│                                                                │
│  4. 关键认知                                                   │
│     ├─ 回测 ≠ 实盘                                             │
│     ├─ 历史不代表未来                                          │
│     └─ 完美的回测往往可疑                                      │
│                                                                │
│  5. 设计原则                                                   │
│     模块化、可复现、可视化、可分析                              │
│                                                                │
└────────────────────────────────────────────────────────────────┘

思考题

  1. 为什么一个在回测中表现完美的策略,在实盘中可能失败?
  2. 回测中哪些假设可能与实盘不符?
  3. 如何判断一个回测结果是可信的还是过拟合的?

下一步

现在你已经理解了回测的基本概念。接下来,让我们学习如何从信号构建投资组合

前往:02-投资组合构建