今天这篇来讲一下backtrader的策略参数调优,这块有点像机器学习,一遍一遍地迭代,找出最佳的参数值。
还是以之前的单均线策略为例子,讲一下怎么找出收益最高时的均线的周期参数。
参数调优的原理就是在回测时,让程序把不同参数值一个个代入回测,然后根据每个参数所得到的最终收益来确定哪个参数是最优参数。
执行回测时,把addstrategy改为optstrategy,再加上参数的调优范围即可。如果是对指定值进行调优,可以用元组指定要回测的参数值,如果想对连续的一系列连续的参数值进行回测,可以用range来指定范围。
指定要回测的参数值:
1 2 3
| cerebro.optstrategy( SingleMAStrategy, period=(10,20,30,60,90))
|
指定要回测的参数范围:
1 2 3
| cerebro.optstrategy( SingleMAStrategy, period=range(10, 30))
|
主程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.optstrategy( SingleMAStrategy, period=(10,20,30,60,90)) cerebro.adddata(data) cerebro.broker.setcash(100000) cerebro.broker.setcommission(commission=0.00015) cerebro.run(maxcpus=1)
|
另外还要修改一下策略中的打印输出部分,屏蔽中间买卖过程信息,输出停止回测后的结果信息。
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
| 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.buyprice = order.executed.price self.buycomm = order.executed.comm else: pass self.bar_executed=len(self) elif order.status in [order.Canceled,order.Margin,order.Rejected]: pass self.order = None def notify_trade(self,trade): if not trade.isclosed: return 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.order =self.buy(size=vol) else: if self.cross==-1: self.order=self.sell(size=self.position.size) def stop(self): self.log('(MA Period %2d) Ending Value %.2f' % (self.params.period, self.broker.getvalue()))
|
回测数据不能用实时数据源,要用已经准备好的数据,不然跑完第一次回测后会卡住。
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' )
|
程序跑完后的结果如下:

可以看到,当均线的周期设置为10、20、30时都亏钱了,设置为60、90时赚钱了。在这几个参数中,period设置为90时赚的钱最多,最优参数为90。
这一篇就到这里啦。欢迎大家点赞、转发、私信。
