![量化交易学习笔记(十三)——第一个策略回测程序v11](http://p2.ttnews.xyz/loading.gif)
v11是第一个策略回测程序的最后一个版本,将对策略参数进行优化。
很多财经书籍里都指出,不同股票、不同书籍都有个各自的特点和节奏,因此使用同一策略参数应用于所有的交易是不明智的。
在之前的例子中,我们尝试了使用了简单移动均值指标,周期参数选定为15,v11将对这个参数进行优化,通过优化找出简单移动均值的最佳周期数。程序的主要修改部分为在向cerebro添加策略时使用如下代码:
<code>strats
=cerebro.optstrategy(
TestStrategy,
maperiod
=range(10, 31))
/<code>
这样backtrader就会将将简单移动均值所选取的周期数从10到31进行逐个尝试,通过计算最终收益,便可以选择出最优的参数。
v11输出为:
<code>2020
-02
-04
,
(MA
Period
10
)
Ending
Value
99852.22
2020
-02
-04
,
(MA
Period
11
)
Ending
Value
99914.55
2020
-02
-04
,
(MA
Period
12
)
Ending
Value
99946.91
2020
-02
-04
,
(MA
Period
13
)
Ending
Value
99948.27
2020
-02
-04
,
(MA
Period
14
)
Ending
Value
99957.74
2020
-02
-04
,
(MA
Period
15
)
Ending
Value
99990.11
2020
-02
-04
,
(MA
Period
16
)
Ending
Value
99990.11
2020
-02
-04
,
(MA
Period
17
)
Ending
Value
100031.43
2020
-02
-04
,
(MA
Period
18
)
Ending
Value
100031.43
2020
-02
-04
,
(MA
Period
19
)
Ending
Value
99985.39
2020
-02
-04
,
(MA
Period
20
)
Ending
Value
100003.41
2020
-02
-04
,
(MA
Period
21
)
Ending
Value
99977.38
2020
-02
-04
,
(MA
Period
22
)
Ending
Value
99990.39
2020
-02
-04
,
(MA
Period
23
)
Ending
Value
99985.39
2020
-02
-04
,
(MA
Period
24
)
Ending
Value
100036.74
2020
-02
-04
,
(MA
Period
25
)
Ending
Value
100036.74
2020
-02
-04
,
(MA
Period
26
)
Ending
Value
100022.75
2020
-02
-04
,
(MA
Period
27
)
Ending
Value
100022.75
2020
-02
-04
,
(MA
Period
28
)
Ending
Value
100022.75
2020
-02
-04
,
(MA
Period
29
)
Ending
Value
100022.75
2020
-02
-04
,
(MA
Period
30
)
Ending
Value
99977.52
/<code>
通过上面的输出信息我们就可以清晰地看到,选择不同周期参数时最后的资产情况。本例中,当周期参数选择为24和25时,可以获得最大收益。
程序v10-优化:
<code>from __future__
import (absolute_import, division, print_function, unicode_literals) import datetime import os.path import sys import backtrader as btclass
TestStrategy
(bt
.Strategy
): params = ( ('maperiod'
,15
), ('printlog'
, False), )def
log
(
self
, txt, dt=None, doprint = False):''
' 策略的日志函数'
''
if
self
.params.printlogor
doprint:
dt = dtor
self
.datas[0
].datetime.date(0
) print('%s, %s'
% (dt.isoformat(), txt))def
__init__
(
self
):self
.dataclose =self
.datas[0
].closeself
.order = Noneself
.buyprice = Noneself
.buycomm = Noneself
.sma = bt.indicators.SimpleMovingAverage(self
.datas[0
], period =self
.params.maperiod)def
notify_order
(
self
, order):if
order.statusin
[order.Submitted, order.Accepted]:return
if
order.statusin
[order.Completed]:if
order.isbuy():self
.log('BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f'
% (order.executed.price, order.executed.value, order.executed.comm))self
.buyprice = order.executed.priceself
.buycomm = order.executed.commelse:
self
.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f'
% (order.executed.price, order.executed.value, order.executed.comm))self
.bar_executed = len(self
) elif order.statusin
[order.Canceled, order.Margin, order.Rejected]:self
.log('Order Canceled/Margin/Rejected'
)self
.order = Nonedef
notify_trade
(
self
, trade):if
not
trade.isclosed:
return
self
.log('OPERATION PROFIT, GROSS %.2f, NET %.2f'
% (trade.pnl, trade.pnlcomm))def
next
(
self
):self
.log('Close, %.2f'
%self
.dataclose[0
])if
self
.order:
return
if
not
self
.position:
if
self
.dataclose[0
] >self
.sma[0
]:self
.log('BUY CREATE, %.2f'
%self
.dataclose[0
])self
.order =self
.buy()else:
if
self
.dataclose[0
]self
.sma[0
]:self
.log('SELL CREATE, %.2f'
%self
.dataclose[0
])self
.order =self
.sell()def
stop
(
self
):self
.log('(MA Period %2d) Ending Value %.2f'
% (self
.params.maperiod,self
.broker.getvalue()), doprint = True) cerebro = bt.Cerebro() strats = cerebro.optstrategy( TestStrategy, maperiod = range(10
,31
)) modpath = os.path.dirname(os.path.abspath(sys.argv[0
])) datapath = os.path.join(modpath,'../../TQDat/day/stk/000001.csv'
) data = bt.feeds.GenericCSVData( dataname = datapath, fromdate = datetime.datetime(2019
,10
,1
), todate = datetime.datetime(2020
,2
,29
), nullvalue =0
.0
, dtformat = ('%Y/%m/%d'
), datetime =0
, open =1
, high =2
, low =3
, close =4
, volume =5
, openinterest = -1
) cerebro.adddata(data) cerebro.broker.setcash(100000.0
) cerebro.addsizer(bt.sizers.FixedSize, stake =100
) cerebro.broker.setcommission(commission=0
.001
) cerebro.run(maxcpus =1
)/<code>