backtrader内置的策略参数优化方法是暴力全量搜索方法,也就是遍历每个参数组合值。在参数很多,每个参数取值变化范围大的情况下,优化效率是很低的。
可以采用智能优化算法,比如粒子群优化等进行大规模参数优化。下面,我们用python开源算法库optunity来对backtrader策略参数进行优化。
我们的示例策略是一个简单的双均线策略,要优化两个参数,即两个均线移动窗口,目标是使得账户市值最大化。从Yahoo在线api取得微软股票日线数据,进行回测。
采用optunity中的粒子群算法来优化,代码如下:
- from datetime import datetime
- import backtrader as bt
- import optunity
- import optunity.metrics
- class SmaCross(bt.SignalStrategy):
- params = (
- ('sma1', 10), # 需要优化的参数1,短期均线窗口
- ('sma2', 30), # 需要优化的参数2,长期均线窗口
- )
- def __init__(self):
- SMA1 = bt.ind.SMA(period=int(self.params.sma1)) # 用int取整
- SMA2 = bt.ind.SMA(period=int(self.params.sma2)) # 用int取整
- crossover = bt.ind.CrossOver(SMA1, SMA2)
- self.signal_add(bt.SIGNAL_LONG, crossover)
- data0 = bt.feeds.YahooFinanceData(dataname='MSFT',
- fromdate=datetime(2011, 1, 1),
- todate=datetime(2012, 12, 31))
- def runstrat(sma1,sma2):
-
- cerebro = bt.Cerebro()
- cerebro.addstrategy(SmaCross, sma1=sma1, sma2=sma2)
- cerebro.adddata(data0)
- cerebro.run()
- return cerebro.broker.getvalue()
- # 执行优化,执行5次回测(num_evals,实战时回测次数要设大一些,比如100次),
- # 设置两个参数sma1,sma2的取值范围
- # solver_name可取算法包括 particle swarm,sobol,random search,cma-es,grid search
- opt = optunity.maximize(runstrat, num_evals=5,solver_name='particle swarm', sma1=[2, 55], sma2=[2, 55])
- # 得到最优参数结果
- optimal_pars, details, _ = opt
- print('Optimal Parameters:')
- print('sma1 = %.2f' % optimal_pars['sma1'])
- print('sma2 = %.2f' % optimal_pars['sma2'])
- # 利用最优参数最后回测一次,作图
- cerebro = bt.Cerebro()
- cerebro.addstrategy(SmaCross, sma1=optimal_pars['sma1'], sma2=optimal_pars['sma2'])
- cerebro.adddata(data0)
- cerebro.run()
- cerebro.plot()
optunity支持如下几种算法(solver),读者可以分别测试它们。
particle swarm,sobol,random search,cma-es,grid search
案例来自教程,百度网盘下载: