从开始学量化交易以来,我先后试了bt和pyalgotrade两个框架,都有一些问题。最近得知backtrader这个单机的量化投资回测框架,试了一下能装上,就尝试一下吧。本文是我看官方文档并进行尝试的记录。
文档地址: https://www.backtrader.com/docu/
这个框架的主要目标就是易用。
运行框架的基本步骤:
1.创建一个策略
①确定可能需要调整的参数。
②实现策略中需要的指标。
③写买入卖出逻辑。
2.创建一个回测引擎(Cerebro Engine)
①插入一个策略。
②加载并插入一个数据源。
③运行引擎。
④可视化回测结果(cerebro.plot())
安装: pip install backtrader
backtrader的两个基本概念:
1.Lines(不知道咋翻了)
数据源,指标和策略有Lines。一系列在时间上连续的数据点称为线。数据源含有”Open, High, Low, Close, Volume, OpenInterest”六条线,如果加上日期就是七条。
2.0索引
在一条Line中,当前值的索引为0。最后输出值的索引为-1。即当前时刻的索引为0,当前时刻之前的时刻的索引为-1。更早的时刻可以用-2,-3等获得。
默认的,引擎会在后台建立broker实例,还有默认的初始金额,是1万货币单位。如果没改变,就会使用默认值。这会简化使用。
设置初始资金,用cerebro.broker.setcash()函数。
框架使用的数据源为bt.feeds,支持雅虎金融,谷歌金融等格式,对于国内常用的tushare,先保存为DataFrame,再用bt.feeds.PandasData()转换成数据源。要求是有’open’,’high’,’low’,’close’,’volume’,’openinterest’六列,其中’openinterest’可设为0。另外DataFrame需要以datetime类型的date列为索引。建立以后用cerebro.adddata()将数据载入引擎。
现在就实现第一个策略了,每个交易日都输出股价现值。
1 | # coding:utf-8 |
1 | 初始资金:100000.00 |
框架的策略类有python的list数据,名为datas。其中第一个数据self.datas[0]是交易操作的默认数据并随策略保持同步。
self.dataclose = self.datas[0].close保存收盘价的地址。
在每次数据源更新时都会调用策略的next()成员函数。
接着在策略中增加一些逻辑。
1 | def next(self): |
连续两天下跌就买入。
1 | 初始资金:100000.00 |
现在的问题是不知道买单何时执行,成交价多少。
在默认情况下,购买self.datas[0]的证券,买入量固定为1股每次,框架在买入指令下达后的下一个交易日以开盘价执行交易,没有考虑交易成本。这些都可以改变的。
接下来考虑卖出。框架策略有position属性,保存仓位。买卖命令都返回created命令(还没有执行)。通过策略的notify方法可以得到交易状态改变的通知。数据源的每个bar的时间单位并没有确定,天,周,月等都可以。
下面修改策略,在买入5个交易周期后卖出。
1 | class TestStrategy(bt.Strategy): |
结果
1 | 初始资金:100000.00 |
下面再加上手续费,费率0.1%。
用cerebro.broker.setcommission(commission=0.001)
并在策略里输出手续费。
1 | class TestStrategy(bt.Strategy): |
结果
1 | …… |
注意因为最后一天仍然有持仓,所以最后的收益与每次交易后收益之和的累加有差异。
可以在策略中定义一些参数以配置策略。
用Python的tuple在策略类里定义
1 | params = ( |
然后在addstrategy中以参数形式给参数赋值。
cerebro.addstrategy(TestStrategy, myparam=20, exitbars=7)
可以用addsizer来设置交易量。
cerebro.addsizer(bt.sizers.FixedSize, stake=100)
把这些结合起来。
1 | # coding:utf-8 |
接下来就可以增加指标了。
下面考虑简单移动平均线策略:
收盘价高于均值就买入;如果有持仓,收盘价低于均值则卖出;同时只能有一个交易。
用bt.indicators.MovingAverageSimple
1 | # coding:utf-8 |
结果
1 | …… |
注意是从第15个交易日开始交易的。框架假设所使用的指标是已经准备好的,当指标没有准备好时,交易不会开始。
可视化,用cerebro.plot()完成。
为了画更多的图像,可以加入更多的均线等指标。
1 | # coding:utf-8 |
尽管交易逻辑没变,结果却变了,因为数据不一样了。2月25日才计算完所有指标开始交易。
最后来看看优化。不同的市场和交易品种可能有不同的参数。可以在一个范围内改变参数取值来看回测结果。但注意不要过度优化,那样好的结果只适合于特定的数据集。还是用上面的移动均线策略做例子,改变均线周期。
用cerebro.optstrategy(TestStrategy, maperiod = range(10, 31)) 来代替addstrategy()。
1 | # coding:utf-8 |
运行结果
1 | $ python first.py |
用17日均线收益最高。
更进一步的改进:自定义指标,设置Sizer(资金管理),交易类型(限价等)。
接下来打算看一遍官网的文档,写个回测实操下。
我发文章的三个地方,欢迎大家在朋友圈等地方分享,欢迎点“在看”。
我的个人博客地址:https://zwdnet.github.io
我的知乎文章地址: https://www.zhihu.com/people/zhao-you-min/posts
我的微信个人订阅号:赵瑜敏的口腔医学学习园地