天天看點

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)  # 周遊所有資料      
上一篇: Extjs-lesson2
下一篇: Python——類