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)  # 遍历所有数据

博客内容只用于交流学习,不构成投资建议,盈亏自负!

个人博客:http://coderx.com.cn/(优先更新)
项目最新代码:https://gitee.com/sl/quant_from_scratch
欢迎大家转发、留言。有微信群用于学习交流,感兴趣的读者请扫码加微信!
如果认为博客对您有帮助,可以扫码进行捐赠,感谢!

微信二维码微信捐赠二维码
在这里插入图片描述在这里插入图片描述
### 关于周志华《机器学习》(西瓜书)第二章的学习笔记 #### 模型评估与选择概述 模型评估与选择是机器学习领域的重要组成部分,旨在通过合理的方法评价不同模型的表现并挑选最优者。这一过程不仅涉及如何衡量单个模型的好坏,还包括怎样对比多个候选方案以做出最佳决策。 #### 偏差、方差和噪声的概念解析 偏差度量了学习算法的期望预测与实际结果之间的差距,反映了算法自身的拟合精度;方差描述的是相同规模训练集变化引起的学习效果波动情况,体现了数据扰动带来的影响;而噪声则设定了给定任务下所有可能采用的学习方法能达到的最佳预期泛化误差界限,揭示了问题本身固有的复杂性和挑战性[^2]。 #### 性能度量指标——P-R图及其应用 为了更直观地展示各类分类器的工作特性,通常会绘制精确率-召回率(Precision-Recall, P-R)曲线来辅助分析。当面对多组实验结果时,可以通过观察这些图形相互间的位置关系来进行优劣评判:如果某条曲线始终位于另一条之上,则表明前者具有更好的整体表现;而对于那些存在交点的情况,则需进一步计算各自下方区域面积大小作为判断依据之一。此外,“平衡点”作为一种特殊的性能测度,在特定条件下也能提供有价值的参考信息[^3]。 #### 偏差-方差分解理论简介 该理论为理解学习算法的一般化能力提供了框架性的指导思路,通过对平均测试错误率实施拆分操作,可以深入剖析导致过拟合现象背后的原因所在,并据此探索改进措施的方向。具体而言,总误差由三部分构成——不可约减误差点(即噪声)、平方形式表达出来的偏差项以及线性累加而成的方差成分[^4]。 ```python import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics import precision_recall_curve, auc def evaluate_model_performance(model, X, y): """ 计算并返回PR曲线下面积(AUC),用于量化模型的整体性能。 参数: model (object): 已经训练好的分类模型实例。 X (array-like of shape (n_samples, n_features)): 测试特征矩阵。 y (array-like of shape (n_samples,)): 对应的真实标签向量。 返回: float: PR AUC得分。 """ # 划分训练集/验证集 X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2) # 使用训练集拟合模型 model.fit(X_train, y_train) # 获取验证集中各观测对应的概率估计值 probas_pred = model.predict_proba(X_val)[:, 1] # 绘制PR曲线并求得AUC分数 precisions, recalls, _ = precision_recall_curve(y_val, probas_pred) pr_auc_score = auc(recalls, precisions) return pr_auc_score ```
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值