昨天介绍了怎么用掘金量化做回测,今天介绍下怎么用backtrader来做回测,backtrader 是一个在量化界大名鼎鼎的量化回测框架,功能丰富,是量化交易初学者必学的量化回测框架。目前的话我也是刚入门,只会拿它做回测,还没研究出怎么把backtrader与掘金量化结合起来用backtrader直接跑仿真和实盘。
backtrader的官网:https://www.backtrader.com/
官网安装教程:https://www.backtrader.com/docu/installation/
官方的入门教程:https://www.backtrader.com/docu/quickstart/quickstart/
接下来以单均线策略介绍下怎么用backtrader结合掘金量化的数据跑回测:
导入掘金及backtrader库:
1 2
| from gm.api import * import backtrader as bt
|
设置掘金token
掘金token是用来访问掘金量化平台数据的凭证,点击掘金量化右上角的系统设置就能找到了。

1 2
| token='xxxxxx' set_token(token)
|
准备回测的数据
掘金量化有获取历史行情的接口history,具体的使用方法可以看其API文档。获取到数据后用bt.feeds.PandasData可以把它转化为backtrader的数据源。在这里我们选择的数据是沪深300ETF(510300)在2020年1月1日至2023年8月9日的数据。为啥是8月9日?因为这份代码是我那天写的。
1 2 3 4 5 6 7
| gmdata = history(symbol='SHSE.510300', frequency='1d', start_time='2020-01-01 09:00:00', end_time='2023-08-09 16:00:00', adjust=ADJUST_PREV, adjust_end_time='2023-08-09', df=True)
data=bt.feeds.PandasData( dataname=gmdata, datetime='eob' )
|
创建一个单均线策略
backtrader中可以用类来定义一个自定义策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| class SingleMAStrategy(bt.Strategy): params=( ('period',15), ) def log(self,txt,dt=None): dt=dt or self.datas[0].datetime.date(0) print('%s, %s' % (dt.isoformat(),txt)) def __init__(self): self.dataclose = self.data.close
self.order = None self.buyprice = None self.buycomm = None self.sma = bt.indicators.SimpleMovingAverage( self.data,period=self.params.period ) self.cross=bt.indicators.CrossOver(self.dataclose,self.sma) def notify_order(self,order): if order.status in [order.Submitted,order.Accepted]: return if order.status in [order.Completed]: if order.isbuy(): self.log( '买入已执行,价格为:%.2f,花费:%.2f,佣金:%.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: self.log( '卖出已执行,价格为:%.2f,花费:%.2f,佣金:%.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.bar_executed=len(self) elif order.status in [order.Canceled,order.Margin,order.Rejected]: self.log('Order Canceled/Margin/Rejected') self.order = None def notify_trade(self,trade): if not trade.isclosed: return self.log('当前盈亏 %.2f ,去除佣金后的盈亏 %.2f' % (trade.pnl,trade.pnlcomm)) def next(self): if self.order: return if not self.position: if self.cross==1: vol=self.broker.getvalue()/self.dataclose[0]//100*100 self.log('创建买单,%.2f' % self.dataclose[0]) self.log('vol:%.2f' % vol) self.order =self.buy(size=vol) else: if self.cross==-1: self.log('创建卖单,%.2f' % self.dataclose[0]) self.order=self.sell(size=self.position.size)
|
主程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(SingleMAStrategy) cerebro.adddata(data) cerebro.broker.setcash(100000) cerebro.broker.setcommission(commission=0.00015) print('初始时资金持仓:%.2f' % cerebro.broker.getvalue()) cerebro.run() print('结束时资金持仓:%.2f' % cerebro.broker.getvalue()) cerebro.plot(iplot=False)
|
执行结果
我是在jupyter里跑的,在jupyter里写代码的好处是调试方便,下面贴一下执行结果:


初始资金为10万元,回测结束后为11万3千6百38块7毛9。赚了1万多块钱。
执行后会调用matplotlib画一幅策略运行结果图,以方便查看策略的有效性

backtrader默认出的这个图虽然不太好看,但是信息量很大。接下来我将截取一部分图片来解释其含义:

图中的红线表示当前帐户内的现金,蓝线表示当前证券组合的价值。没有买入证券时,红蓝线重合,只显示红线,当买入证券后红线代表的现金会减少下降,蓝线代表的证券价值还会有原来的位置,不过会随着当前行情发生变化。

图中的红点和蓝点表示每次卖出时收获的净利润。红点表示净利润为负赔钱了,蓝点表示净利润为正赚钱了。

主图中就是股票的走势了,黑线是股票的每日收盘价,红线是我们的15日均线,绿色箭头是买入点(在国外绿为涨红为跌与A股是反着的)红色箭头是卖出点,下方的柱子是成交量,左边坐标轴是成交量的坐标轴,右边坐标轴是股价的坐标轴。

最下面的那条红线是我们计算的交叉点上穿下穿的CrossOver的值。
这一篇简单介绍了怎么用backtrader回测,backtrader相比直接用掘金量化会方便很多,而且它的图表信息量更大,更有助于我们排查策略的问题。
这一篇就到这里啦。欢迎大家点赞、转发、私信。
