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