Python量化交易学习笔记(24)——策略多参数优化

笔记(13)中介绍了在策略中对单个参数进行优化的实现方法,本文将介绍对策略中的多个参数进行优化的方案。

笔记(14)中介绍的均线交叉策略为例,实现不同长期、短期均线参数组合的优化测试,回测股票为000001平安银行,回测周期为2018年1月1日至2020年4月15日。

  • 方案1——使用多个list
    在向cerebro中添加策略时,使用list来定义长期、短期均线的取值:
strats = cerebro.optstrategy(
        SmaCross,
        pfast = [5, 10, 15],
        pslow = [20, 30, 60])

在策略类中的init函数中,使用相应的参数:

    params = dict(
        pfast=5,  # 短期均线周期
        pslow=10   # 长期均线周期
    )
    def __init__(self):
        sma1 = bt.ind.SMA(period=self.p.pfast)  # 短期均线
        sma2 = bt.ind.SMA(period=self.p.pslow)  # 长期均线
        self.crossover = bt.ind.CrossOver(sma1, sma2)  # 交叉信号

在上面的代码中,短期均线会依次取5、10、15三个值,长期均线会依次取20、30、60三个值,这样就会形成3*3=9种组合,执行程序后输出如下:

(Fast Period   5, Slow Period  20) Ending Value 101321.23
(Fast Period   5, Slow Period  30) Ending Value 109934.13
(Fast Period   5, Slow Period  60) Ending Value 116776.70
(Fast Period  10, Slow Period  20) Ending Value 107225.67
(Fast Period  10, Slow Period  30) Ending Value 107899.79
(Fast Period  10, Slow Period  60) Ending Value 110485.50
(Fast Period  15, Slow Period  20) Ending Value 95051.12
(Fast Period  15, Slow Period  30) Ending Value 104954.36
(Fast Period  15, Slow Period  60) Ending Value 106075.20
  • 方案2——使用tuple(元组)的list
    在向cerebro中添加策略时,将长期、短期均线的取值组成一个tuple,将所有的待测取值构建成tuple的list:
strats = cerebro.optstrategy(
        SmaCross,
        period = [(5, 10), (20, 100), (2, 10)])

在策略类中的init函数中,使用相应的参数:

    params = dict(
        period = (5, 10), # 元组,(短期均线周期,长期均线周期)
    )
    def __init__(self):
        sma1 = bt.ind.SMA(period=self.p.period[0])  # 短期均线
        sma2 = bt.ind.SMA(period=self.p.period[1])  # 长期均线
        self.crossover = bt.ind.CrossOver(sma1, sma2)  # 交叉信号

在上面的代码中,短期均线和长期均线会形成了3个组合供测试优化,执行程序后输出如下:

(Fast Period   5, Slow Period  10) Ending Value 92377.83
(Fast Period  20, Slow Period 100) Ending Value 107292.25
(Fast Period   2, Slow Period  10) Ending Value 90157.66

方案1和方案2在使用时稍有区别:

  • 方案1对所有参数的所有取值形成的所有组合都会进行回测
  • 方案2仅针对给定的参数组合进行回测

策略多参数优化代码(方案2):

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import datetime  # 用于datetime对象操作
import os.path  # 用于管理路径
import sys  # 用于在argvTo[0]中找到脚本名称
import backtrader as bt # 引入backtrader框架

# 创建策略
class SmaCross(bt.Strategy):
    # 可配置策略参数
    params = dict(
        period = (5, 10), # 元组,(短期均线周期,长期均线周期)
    )
    def __init__(self):
        sma1 = bt.ind.SMA(period=self.p.period[0])  # 短期均线
        sma2 = bt.ind.SMA(period=self.p.period[1])  # 长期均线
        self.crossover = bt.ind.CrossOver(sma1, sma2)  # 交叉信号
    def next(self):
        if not self.position:  # 不在场内,则可以买入
            if self.crossover > 0:  # 如果金叉
                self.buy()  # 买入
        elif self.crossover < 0:  # 在场内,且死叉
            self.close()  # 卖出
    def stop(self):
        print('(Fast Period %3d, Slow Period %3d) Ending Value %.2f' %
         (self.params.period[0], self.params.period[1], self.broker.getvalue()))
cerebro = bt.Cerebro()  # 创建cerebro
# 先找到脚本的位置,然后根据脚本与数据的相对路径关系找到数据位置
# 这样脚本从任意地方被调用,都可以正确地访问到数据
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(2018, 1, 1),
        todate = datetime.datetime(2020, 4, 15),
        nullvalue = 0.0,
        dtformat = ('%Y-%m-%d'),
        datetime = 0,
        open = 1,
        high = 2,
        low = 3,
        close = 4,
        volume = 5,
        openinterest = -1
        )
# 在Cerebro中添加价格数据
cerebro.adddata(data)
# 设置启动资金
cerebro.broker.setcash(100000.0)
# 设置交易单位大小
cerebro.addsizer(bt.sizers.FixedSize, stake = 5000)
# 设置佣金为千分之一
cerebro.broker.setcommission(commission=0.001)
# 添加策略
strats = cerebro.optstrategy(
        SmaCross,
        period = [(5, 10), (20, 100), (2, 10)])
cerebro.run(maxcpus = 1)  # 遍历所有数据

为了便于相互交流学习,新建了微信群,感兴趣的读者请加微信。
在这里插入图片描述

おすすめ

転載: blog.csdn.net/m0_46603114/article/details/105764025