• 量化交易学习笔记(9) 使用Hyperopt 对BOLL策略的超参数优化 横跨熊牛市实现百倍收益


    前言

    一文详解模型调参神器:Hyperopt,体验后真的很棒

    在实现量化交易策略后,对模型参数调优可以通过框架自带的调优器,也可自己些调优的小程序,或者一些参数调优的库,Hyperopt使用贝叶斯优化的形式进行参数调整,允许你为给定模型获得最佳参数,它可以在大范围内优化具有数百个参数的模型,Hyperopt功能强大,性能优异,所以本文带来Hyperopt对模型参数优化。

    BOLL策略

    • 介绍

    布林带宽度(Bollinger Band Width)是美国股市分析家约翰·布林于2010年发明,用于测量布林带(Bollinger Bands于1980年发明)上下轨道线之间的相对距离。它随带宽变窄而减小,而随着带宽放宽而增加。因为布林带基于标准差,所以带宽的波动幅度可以反映波动性,并且可视为波动率指标。布林带由三条不同的线组成,包括简单移动平均线及正负距离两个标准差的上下轨道线。可为日常股票交易决策提供参考依据,是金融市场常用的技术指标之一。

    • 信号

    在突破boll通道上轨买入
    在跌破boll通道下轨平仓

    -订单

    交易价格:昨日收盘价*(1 - C)
    止损价格: 交易价格*(1 - L)
    止盈价格:交易价格*(1 + S)
    交易量:min(可用资金/ SMA,交易量)

    数据回测

    初始化

    回测Value
    DOTUSDT_1h2020-08-24 到 2022-07-08
    boll周期9
    收益率228%

    在这里插入图片描述

    优化后

    回测Value
    DOTUSDT_1h2020-08-24 到 2022-07-08
    boll周期43
    收益率1726.07%
    在这里插入图片描述

    测试数据

    下面的数据有兴趣的小伙伴自行尝试

    {
        "策略名称":"BollStrategy",
        "运行时间":"12.786108616987864分钟",
        "数据源":"D:\\work\\git\\Tools\\static\\data\\SOLUSDT_1h.csv",
        "收益率":"163874.15299064145 %",
        "参数":{
            "period":278.34501260009176
        }
    }
    {
        "策略名称":"BollStrategy",
        "运行时间":"0.9963125467300415分钟",
        "数据源":"D:\\work\\git\\Tools\\static\\data\\OPUSDT_1h.csv",
        "收益率":"234.9051745737002 %",
        "参数":{
            "period":299.9132638182971
        }
    }
    {
        "策略名称":"BollStrategy",
        "运行时间":"13.492177633444468分钟",
        "数据源":"D:\\work\\git\\Tools\\static\\data\\KNCUSDT_1h.csv",
        "收益率":"5901.495375774953 %",
        "参数":{
            "period":142.0523650680161
        }
    }
    {
        "策略名称":"BollStrategy",
        "运行时间":"2.452657969792684分钟",
        "数据源":"D:\\work\\git\\Tools\\static\\data\\GMTUSDT_1h.csv",
        "收益率":"56170.06056933173 %",
        "参数":{
            "period":93.09081580846353
        }
    }
    {
        "策略名称":"BollStrategy",
        "运行时间":"64.45960373481115分钟",
        "数据源":"D:\\work\\git\\Tools\\static\\data\\ETHUSDT_30m.csv",
        "收益率":"754213.6102849536 %",
        "参数":{
            "period":235.62271521989342
        }
    }
    {
        "策略名称":"BollStrategy",
        "运行时间":"32.046370434761045分钟",
        "数据源":"D:\\work\\git\\Tools\\static\\data\\BTCUSDT_1h.csv",
        "收益率":"32261.19551698138 %",
        "参数":{
            "period":285.67352340101354
        }
    }
    {
        "策略名称":"BollStrategy",
        "运行时间":"30.425016216437022分钟",
        "数据源":"D:\\work\\git\\Tools\\static\\data\\BNBUSDT_1h.csv",
        "收益率":"839850.7548190868 %",
        "参数":{
            "period":271.69678493757556
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    代码

    Hyperopt 优化器

    class Optimizer:
    
        def __init__(self, data, space, strategy_func, max_evals=500, is_send_ding_task=False):
        	# 数据
            self.data = data
            # 迭代次数
            self.max_evals = max_evals
            # 是否把结果发送钉钉
            self.is_send_ding_task = is_send_ding_task
            # 策略参数
            self.params = None
            # 初始资金
            self.cash = 10000
            # 参数空间
            self.space = space
            # 添加策略函数
            self.strategy_func = strategy_func
    
        def target_func(self, params):
    
            cerebro = run_strategy(func=self.strategy_func, data=self.data,
                                   cash=self.cash, params=params)
            return -cerebro.broker.getvalue()
    
        def run(self):
            trials = Trials()
            self.params = fmin(fn=self.target_func, space=self.space, algo=tpe.suggest, max_evals=self.max_evals,
                               trials=trials)
            logging.info(self.params)
            return self.params
    
        def plot(self):
            run_strategy(func=self.strategy_func, data=self.data, params=self.params, is_show=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    Boll策略

    class BollStrategy(bt.Strategy):
        params = dict(
            is_log=False,
            period=20
        )
    
        def log(self, txt, dt=None):
            if self.p.is_log:
                dt = dt or self.datas[0].datetime.date(0)
                print('%s,%s' % (dt.isoformat(), txt))
    
        def __init__(self):
            # 指定价格序列
            self.dataclose = self.datas[0].close
            # 交易订单状态初始化
            self.order = None
            # 上轨
            self.lines.top = bt.indicators.BollingerBands(period=self.p.period).top
            # 下轨
            self.lines.bot = bt.indicators.BollingerBands(period=self.p.period).bot
    
        def get_buy_unit(self):
            size = self.broker.getcash() / self.data.high[0] * 0.5
            if size == 0:
                size = 0
            return size
    
        def next(self):
            # 检查订单状态
            if self.order:
                return
    
            # 检查持仓
            if not self.position:
                # 没有持仓,买入开仓
                if self.dataclose <= self.lines.bot[0]:
                    self.order = self.buy(size=self.get_buy_unit())
    
    
            else:
                # 手里有持仓,判断卖平
                if self.dataclose >= self.lines.top[0]:
                    self.close()
    
        def notify(self, order):
    
            if order.status in [order.Submitted, order.Accepted]:
                if order.status in [order.Submitted]:
                    self.log("提交订单......")
                if order.status in [order.Accepted]:
                    self.log("接受订单......")
                return
    
            # Check if an order has been completed
            # Attention: broker could reject order if not enougth cash
            if order.status in [order.Completed, order.Canceled, order.Margin]:
                if order.isbuy():
                    self.log('执行买入, %.2f' % order.executed.price)
                    gloVar['buy_count'] = gloVar['buy_count'] + 1
                elif order.issell():
                    self.log('执行卖出, %.2f' % order.executed.price)
                    gloVar['sell_count'] = gloVar['sell_count'] + 1
                self.bar_executed = len(self)
    
            self.log("订单完成......")
    
            # Write down: no pending order
            self.order = None
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    主程序

    
    if __name__ == '__main__':
        space = dict(
            period=hp.uniform("period", 10, 400)
        )
        opt = Optimizer(data=get_data("D:\\work\\git\\Tools\\static\\data\\DOTUSDT_1h.csv"),
    
                        strategy_func=add_bool_boll_strategy, space=space, max_evals=500)
        params = opt.run()
        print(params)
        opt.plot()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    总结

    目前从回测结果来看,该策略表现还行,把bool周期调大,减少开仓的次数,较小市场的波动,可持续性盈利。未来10年,实现财富自由,加油!!!!

  • 相关阅读:
    用SSH工具XShell连接谷歌云 root用户或普通用户
    一文读懂Embedding
    java计算机毕业设计高校毕业就业管理系统源码+mysql数据库+系统+lw文档+部署
    2022主流技术 Appium+IOS 自动化测试环境搭建
    华为WLAN配置攻击检测功能示例
    安装 Android Studio 2024.1.1.6(Koala SDK35)和过程问题解决
    并列句------六级
    Python-VBA编程500例-033(入门级)
    Golang 中的 errors 包详解:返回自定义 error 类型
    请收藏:流固耦合经验总结(一)
  • 原文地址:https://blog.csdn.net/weixin_43688870/article/details/126167903