3. 第一个回测脚本:导入库、定义策略类、设置初始资金、运行回测、输出结果

本章将带领你编写第一个完整的 Backtrader 回测脚本。通过一个简单的“买入并持有”策略,你将掌握回测的五个核心步骤:导入库、定义策略类、设置初始资金、运行回测以及输出结果。这是后续所有复杂策略的基础骨架。

💡 学习目标:完成本章后,你将能够独立编写一个可运行的 Backtrader 脚本,并理解回测引擎的基本工作流程。

3.1 回测脚本的完整骨架

一个标准的 Backtrader 回测脚本通常包含以下五个部分,它们按顺序执行,缺一不可:

步骤 组件 说明
1 导入库 引入 backtrader 模块及所需的数据源、分析器等
2 定义策略类 继承 bt.Strategy,实现 next() 方法定义交易逻辑
3 设置初始资金 通过 cerebro.broker.setcash() 设定回测本金
4 运行回测 调用 cerebro.run() 执行策略
5 输出结果 打印最终资金、收益率等关键指标
回测脚本五步流程 导入库 定义策略类 设置初始资金 运行回测 输出结果 每个步骤对应一行核心代码,共同构成回测脚本的完整骨架

3.2 代码实现:逐行解析

下面是一个完整的“买入并持有”回测脚本。我们使用 Yahoo Finance 的历史数据(AAPL)作为示例数据源。

import backtrader as bt
import datetime

# 1. 定义策略类
class BuyAndHold(bt.Strategy):
    def next(self):
        # 如果没有持仓,则买入
        if not self.position:
            self.buy(size=100)  # 买入100股

# 2. 创建 Cerebro 引擎
cerebro = bt.Cerebro()

# 3. 添加数据
data = bt.feeds.YahooFinanceData(
    dataname='AAPL',
    fromdate=datetime.datetime(2020, 1, 1),
    todate=datetime.datetime(2020, 12, 31)
)
cerebro.adddata(data)

# 4. 添加策略
cerebro.addstrategy(BuyAndHold)

# 5. 设置初始资金
cerebro.broker.setcash(10000.0)

# 6. 运行回测
print('初始资金: %.2f' % cerebro.broker.getvalue())
cerebro.run()
print('最终资金: %.2f' % cerebro.broker.getvalue())

# 7. 输出结果
final_value = cerebro.broker.getvalue()
profit = final_value - 10000
print('净利润: %.2f' % profit)
print('收益率: %.2f%%' % (profit / 10000 * 100))

3.3 核心组件详解

3.3.1 策略类(Strategy)

策略类是回测的核心。它必须继承 bt.Strategy,并至少实现 next() 方法。next() 在每个交易日被调用一次,是交易逻辑的入口。

  • self.position:检查当前是否有持仓。
  • self.buy(size=100):以当日收盘价买入指定数量。
  • self.sell(size=100):卖出指定数量(本例未使用)。

3.3.2 Cerebro 引擎

Cerebro 是 Backtrader 的“大脑”,负责协调数据、策略、经纪商和分析器。主要方法包括:

方法 作用
adddata(data) 添加数据源
addstrategy(strategy) 注册策略类
broker.setcash(amount) 设置初始资金
run() 启动回测
broker.getvalue() 获取当前账户总价值

3.3.3 数据源(Data Feed)

Backtrader 支持多种数据源。本例使用 YahooFinanceData 在线获取数据。你也可以使用本地 CSV 文件:

data = bt.feeds.GenericCSVData(
    dataname='path/to/your/file.csv',
    dtformat='%Y-%m-%d',
    openinterest=-1
)
⚠️ 注意:在线数据需要网络连接。如果 Yahoo Finance 数据不可用,建议先下载为 CSV 文件再使用本地数据源。

3.4 运行结果解读

运行上述脚本后,控制台将输出类似以下内容:

初始资金: 10000.00
最终资金: 13650.00
净利润: 3650.00
收益率: 36.50%

这表示在 2020 年 1 月 1 日买入 100 股 AAPL 并持有至年底,账户从 10,000 美元增长至 13,650 美元,收益率为 36.50%。

回测结果对比 $10,000 初始资金 $13,650 最终资金 收益 +$3,650 收益率 +36.50%

3.5 常见问题与调试技巧

🔍 调试建议:
  • 数据加载失败:检查网络连接或改用本地 CSV 数据。
  • 策略未执行交易:确认 next() 方法中的条件是否满足(如 if not self.position)。
  • 资金未变化:检查 setcash() 是否在 run() 之前调用。
  • 打印输出:在 next() 中添加 print(self.datas[0].close[0]) 查看每日收盘价。

3.6 本章小结