量构实验室
量构教程

first line of backtest system

# 从零搭建量化回测系统:我的第一行代码该写什么?

> 本文是「回测系统开发」系列的第一篇,适合有Python基础、想入门量化系统开发的读者。

## 为什么要自建回测系统?

在使用聚宽、米筐等在线平台时,你可能会有这些困扰:

- **黑盒问题**:不知道回测引擎内部如何运作
- **灵活性受限**:无法自定义数据流和事件处理
- **性能瓶颈**:大规模回测时速度太慢
- **实盘对接**:从回测到实盘需要重新开发

自建回测系统可以解决这些问题,让你完全掌控整个流程。

## 回测系统的核心概念

一个最简单的回测系统需要三个核心组件:

1. **数据管理器(Data Handler)**:提供历史行情数据
2. **策略(Strategy)**:根据数据生成交易信号
3. **执行器(Executor)**:模拟订单执行和记录持仓

## 第一版代码:极简回测框架

让我们从一个最简单的例子开始:

```python
import pandas as pd
import numpy as np

class SimpleBacktest:
    """极简回测框架"""
    
    def __init__(self, data, strategy):
        self.data = data  # 历史数据
        self.strategy = strategy  # 策略函数
        self.positions = []  # 持仓记录
        self.trades = []  # 交易记录
        
    def run(self):
        """运行回测"""
        for i in range(len(self.data)):
            # 获取当前时刻的数据
            current_data = self.data.iloc[:i+1]
            
            # 策略生成信号
            signal = self.strategy(current_data)
            
            # 执行交易
            if signal != 0:
                self.execute_trade(i, signal)
                
        return self.calculate_performance()
    
    def execute_trade(self, idx, signal):
        """执行交易"""
        price = self.data.iloc[idx]['close']
        self.trades.append({
            'date': self.data.index[idx],
            'signal': signal,
            'price': price
        })
    
    def calculate_performance(self):
        """计算绩效"""
        if len(self.trades) < 2:
            return {'total_return': 0}
            
        # 简单计算:买入为+1,卖出为-1
        returns = []
        position = 0
        entry_price = 0
        
        for trade in self.trades:
            if trade['signal'] == 1 and position == 0:  # 买入
                position = 1
                entry_price = trade['price']
            elif trade['signal'] == -1 and position == 1:  # 卖出
                ret = (trade['price'] - entry_price) / entry_price
                returns.append(ret)
                position = 0
                
        total_return = sum(returns) if returns else 0
        
        return {
            'total_return': f"{total_return*100:.2f}%",
            'num_trades': len(self.trades) // 2,
            'avg_return': f"{np.mean(returns)*100:.2f}%" if returns else "0%"
        }


def simple_strategy(data):
    """简单双均线策略"""
    if len(data) < 20:
        return 0
        
    # 计算均线
    ma5 = data['close'].tail(5).mean()
    ma20 = data['close'].tail(20).mean()
    
    # 金叉买入,死叉卖出
    if ma5 > ma20 and data['close'].iloc[-2] <= data['close'].iloc[-7]:
        return 1  # 买入信号
    elif ma5 < ma20 and data['close'].iloc[-2] >= data['close'].iloc[-7]:
        return -1  # 卖出信号
    
    return 0


# 使用示例
if __name__ == "__main__":
    # 模拟数据
    dates = pd.date_range('2024-01-01', periods=100, freq='D')
    prices = 100 + np.cumsum(np.random.randn(100) * 2)
    data = pd.DataFrame({
        'close': prices
    }, index=dates)
    
    # 运行回测
    backtest = SimpleBacktest(data, simple_strategy)
    result = backtest.run()
    
    print("回测结果:")
    for key, value in result.items():
        print(f"  {key}: {value}")
```

## 代码解析

### 1. 数据流设计

```
历史数据 → Data Handler → Strategy → Executor → 绩效计算
```

这个流程是事件驱动回测的基础。每一根K线到来时:
1. 数据管理器推送新数据
2. 策略根据数据生成信号
3. 执行器模拟订单成交
4. 更新持仓和资金

### 2. 策略接口

策略函数接收历史数据,返回交易信号:
- `1`:买入
- `-1`:卖出
- `0`:无操作

### 3. 绩效计算

目前只实现了简单的收益率计算。生产级系统还需要:
- 最大回撤
- 夏普比率
- 胜率
- 盈亏比

## 下一步

这个极简框架帮助我们理解了回测的核心原理。接下来的文章将介绍:

1. **数据管理器优化**:接入真实数据源(Tushare、AKShare)
2. **策略框架设计**:支持多因子、多策略组合
3. **执行器完善**:滑点、手续费、市场冲击
4. **向量化回测**:用Pandas实现高速回测

## 总结

自建回测系统的第一步不是写复杂的代码,而是理解核心概念:

> **数据流 → 策略决策 → 订单执行 → 绩效评估**

掌握这个流程后,你可以逐步添加功能,最终构建出生产级的回测平台。

---

**参考代码**:完整代码已上传至 [GitHub](https://github.com)

**下篇预告**:《数据管理器设计:如何高效处理百万级行情数据》