Python 算法交易实验63 关于回测

news2025/1/10 23:12:12

说明

项目结束了,这几天把量化第一版搭起来,量化很重要,现在可以迈出第一步了。首先要关注的是回测,和前不久写的这篇文章呼应,测试的确是一个相对独立,又非常重要的部件。过去比较少关注在方面上,所以现在要特别的加强。

内容

1 前言

量化的模型和策略方面我觉得还是不难的,而且每个人都可以有自己的思路,所以反而没啥好说。

我觉得建立回测服务是比较重要的,因为很多想法行不行的通,最好直接跑一个服务来测试。

1 以测试为导向,不仅是量化的要点,也是其他AI项目的第一规则

2 强调框架性,通过框架设计才能保证稳定、灵活,同时框架一定会带来管理和性能上的损耗,要平衡好。

3 通过微服务体系构建分布式的服务。

以上三点是通用的。

回到眼前这个具体的问题,如何构造一个测试方法+服务来快速的获取KPI,这些KPI足以证明模型的泛化性良好,这样才可以让我们放心的去用。

2 框架

对于一个完整的功能来说,必须要有框架设计。否则迟早要回头返工。

不考虑状态的框架,也是不完整的框架。

从强化学习或者模拟类优化(遗传算法)来看,算法的迭代和演进是需要”投石问路“的部分的。

假设未来算法在自动执行了,那么有80%会按照当前已知的最优路径前进,剩余的20%则会进行搜索,以便进行优化、纠偏等动作。

所以状态(State)、行为(Action)和回报(Return)是一个智能体的三元组,这个很精辟。

除了把框架当成智能体,我们也会希望它按照清晰、固定的规则去可靠执行。

所以很有意思,在决策领域我们会看到规则和模型,前者是简单、清晰和固定的,而后者是复杂、隐晦和多变的;规则和模型的关系恰如现在非智能框架与智能框架的关系。

我觉得可以从人的角度来近似解释这两者的矛盾关系,叫「择善固执」。

在理想的状态下,我们择善了,然后固执下去,最终获得大丰收。实际情况是,我们很可能不知道什么是善。例如达芬奇在学画画时画的无数个鸡蛋,或者我在开始做人工智能时只盯着专业时间的累积,反复的用Python去搭建各种工具。

在我们的认知很有限时,可能只能通过很简单、很模糊的大方向做下去,通过不停的做某些事,让大脑和身体得到反馈,才能不断的在一条专业路线上不断前进。

在做的时候我们可能又要不停的想办法,在合理的时间内给到最好的结果,这就是择善。接着就会不断的提出设想、POC、推翻设想或接受设想。

很多功在事后发现是无用功,但我们不是先知。

所以我想,对于框架或者决策,都会有”傻“的部分和”聪明“的部分。这两者可以独立存在,又可以互相配合。

通过上面的逻辑推演、辩证,我认为:

  • 1 第一阶段还是出”傻“框架,可能只是人工枚举有限的状态,并指定一些规则(例如止盈止损)
  • 2 第二阶段会出”聪明“框架,这种框架是自适应的,这种框架也是不稳定的(主动随机)
  • 3 第三阶段既傻又聪明的框架,可以认为是那些企业家偶像或者管理者偶像:即具备了极大的远见,又能carry所有的难题,直到胜利

3 实现

先封一版吧。

先看结果,标的是沪深300指数, 每次限额5000元交易。信号用的是我之前开发的一版,可能不是非常完美,但问题是不大的。

{'total_win': 13247.159999999996,
 'total_loss': -3199.1800000000003,
 'orders': 74,
 'avg_npr': 135.7835135135135,
 'np_sum': 10047.98,
 'mid_hold_days': 7.0,
 'total_hold_days': 740,
 'all_days': 3504,
 'money_usage': 0.21118721461187215,
 'monthly_win_loss':    buy_yymon    loss      win      net  win_loss_ratio
 0    2013-05    0.00    95.15    95.15             inf
 1    2014-01    0.00   113.73   113.73             inf
 2    2014-11    0.00   711.40   711.40             inf
 3    2014-12    0.00   723.00   723.00             inf
 4    2015-01 -273.60   137.72  -135.88            0.50
 5    2015-03    0.00  1384.86  1384.86             inf
 6    2015-04    0.00   703.84   703.84             inf
 7    2015-06 -548.83     0.00  -548.83            0.00
 8    2015-07 -738.23  1203.84   465.61            1.63
 9    2015-08 -393.78   264.10  -129.68            0.67
 10   2015-09    0.00   240.89   240.89             inf
 11   2015-11    0.00   464.76   464.76             inf
 12   2016-01  -44.29   192.74   148.45            4.35
 13   2016-02    0.00   261.10   261.10             inf
 14   2016-03    0.00    67.36    67.36             inf
 15   2016-05    0.00    26.66    26.66             inf
 16   2018-02    0.00   257.48   257.48             inf
 17   2018-07    0.00   218.70   218.70             inf
 18   2018-08    0.00    57.68    57.68             inf
 19   2018-09    0.00   128.52   128.52             inf
 20   2018-10    0.00   173.43   173.43             inf
 21   2019-02    0.00   430.75   430.75             inf
 22   2019-03    0.00   403.74   403.74             inf
 23   2019-05  -26.74   113.72    86.98            4.25
 24   2019-06    0.00   249.26   249.26             inf
 25   2019-09    0.00    96.89    96.89             inf
 26   2019-12    0.00    65.36    65.36             inf
 27   2020-02    0.00   446.12   446.12             inf
 28   2020-03    0.98     0.00     0.98            0.00
 29   2020-06    0.00   875.37   875.37             inf
 30   2020-07 -252.60   165.60   -87.00            0.66
 31   2020-08    0.00   167.04   167.04             inf
 32   2020-09    0.00   178.57   178.57             inf
 33   2020-11    0.00   199.40   199.40             inf
 34   2020-12    0.00   337.80   337.80             inf
 35   2021-01    0.00   465.90   465.90             inf
 36   2021-02 -195.25     0.00  -195.25            0.00
 37   2021-03 -278.40   197.10   -81.30            0.71
 38   2021-04    0.00   156.50   156.50             inf
 39   2021-05    0.00   110.47   110.47             inf
 40   2021-07    0.00   114.00   114.00             inf
 41   2021-08    0.00   116.10   116.10             inf
 42   2021-09    0.00    33.80    33.80             inf
 43   2021-12    0.00   126.90   126.90             inf
 44   2022-01  -42.20     0.00   -42.20            0.00
 45   2022-03    0.00   277.08   277.08             inf
 46   2022-04 -148.32     0.00  -148.32            0.00
 47   2022-06    0.00   208.73   208.73             inf
 48   2022-09 -257.92     0.00  -257.92            0.00
 49   2022-10    0.00   264.36   264.36             inf
 50   2022-12    0.00    19.64    19.64             inf,
 'yearly_result':   buy_yy     loss      win      net  win_loss_ratio
 0   2013     0.00    95.15    95.15             inf
 1   2014     0.00  1548.13  1548.13             inf
 2   2015 -1954.44  4400.01  2445.57            2.25
 3   2016   -44.29   547.86   503.57           12.37
 4   2018     0.00   835.81   835.81             inf
 5   2019   -26.74  1359.72  1332.98           50.85
 6   2020  -251.62  2369.90  2118.28            9.42
 7   2021  -473.65  1320.77   847.12            2.79
 8   2022  -448.44   769.81   321.37            1.72}

资金曲线是这样的,过于理想以至于我会有点怀疑。
在这里插入图片描述

信号(模型)的事先放一放,问题不大。这里主要还是看构造了哪些对象来实现回测。

Naive

我不太喜欢用中括号引用数据,所以构造了一个简单的对象,可以用点来连接属性。

class Naive:
    def __init__(self):
        pass
    
    def dict(self):
        return self.__dict__

Order

Order是一个核心的功能对象。

  • 1 Order会引起资产的变化
  • 2 资产的变化可能会作用到Order
  • 3 Order本身也有一些简单的风控规则
  • 4 Order需要提供结果的分析

Order的主要属性:

  • 1 参数类属性。例如每个订单的止盈止损(上面的测试用了15%,-5%)
  • 2 过程变量。例如存放打开和关闭订单的列表
  • 3 每个时隙的数据 slot_data。(Naive实例)

Order的主要方法:

  • 1 setattr : 将每个时隙的数据刷新slot_data。
  • 2 buy: 按照时隙的高点买入。
  • 3 sell: 按照时隙的低点卖出。
  • 4 evaluate: 评估,以决定是否按照止盈止损规则卖出。
  • 5 analysis: 分析,得到一开始看到的结果。主要从整体盈利、盈亏比、中位持仓时间、整体持仓时间、按月和按年的盈亏情况来看。一看盈利能力,一看稳定性。

在使用时,buy只会根据signal来行动;而sell不仅会根据signal,还会根据evaluate中包含的规则。

  • 1 当signal为-1时,一定会强制全部卖出
  • 2 当signal为0或缺失,则进行风险判定,如果有触发规则的订单会被平掉。

Capital

一开始我以为是比较核心的,但实际上是简单的。

Capital的主要属性:

  • 1 参数类。损失和回撤。
  • 2 过程变量。有资产变化的时隙数据。

Capital的主要方法:

  • 1 drawback 看回撤
  • 2 cap_loss 看损失(本金)
  • 3 evaluate 调用以上两个方法

Signal

严格意义上这次并没有开发完整,但是框架也是很简单

Signal的主要属性:

  • 1 参数类。如状态, Test、Prod
  • 2 时隙数据。

Signal的主要方法:

  • 1 setattr: 刷新数据,在测试中做好了slot~signal字典,在生产中可能要读入一大批时隙特征。
  • 2 fake_predict:查字典式的给出时隙信号
  • 3 predict: 一个形式上统一的预测方法
  • 4 *model_predict: 本次没写,这个可以把模型放在本地来预测
  • 5 *api_predict: 本次没写,以web api方式获取信号(预测模型封装为服务)

Strategy

将Order、Capital和Signal三个对象结合起来,每次刷新数据后调用一次判断。将所有的回测数据整理好就可以进行了。

核心的一段调用代码

    # 执行流程
    def pass_process(self):
        if self.rule_result =='Pass':
            self.passattr()
            cur_signal = self.Signal.predict()

            if cur_signal ==1:
                print('>>signal 1')
                self.Order.buy()
            elif cur_signal == -1:
                print('>>signal -1')
                self.Order.sell(is_force=True)
            else:
                self.Order.evaluate()
                self.Order.sell()
            
            the_capital_change = self.Order.get_change_tuple()
            if the_capital_change:
                self.Capital.appendattr(the_capital_change)   

整体测试

a_strategy = Strategy(singal_dict=test_signal_dict1, init_cash=6000, capital_drawback_stop =-0.1, order_win_stop = 0.15, order_loss_stop = -0.05)

for i in tqdm.tqdm(range(len_of_trade)):
    tem_dict = dict(trade_df.iloc[i])
    a_strategy.process(tem_dict)
    if a_strategy.rule_result =='Stop':
        print('Stopped @ %i' %i)
        break

4 结语

有两点。

第一,这次测试使用对象化(OOP)去解决问题。现在看来我也可以适应这种方式,应该可以达到我期望的效果(更大规模的集成和效率提升)。

这次设计和测试的过程很短,有出现过一个小bug,查起来还挺麻烦的。所以后续除了要从设计上分开,调试和测试也应该分开来独立进行。

总体是好的。

第二,这次拍了一个测试的版本。后续把模型重塑一下应该就可以实战了,目前看来,这条路子是通的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/644352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据分析案例-航空公司满意度数据可视化

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

【瑞萨RA_FSP】ADC——电压采集

文章目录 一、ADC简介二、ADC的结构框图1. 电压输入范围2. 工作模式3. 转换过程顺序4. 触发源5. ADC转换时间6. 数据寄存器7. 电压转换 一、ADC简介 ADC即模拟数字转换器,ADC英文全称(Analog-to-digital converter), 是一种用于将…

Delphi XE10 dxLayoutControl 控件应用指南

Delphi XE10 dxLayoutControl 控件应用指南 DevExpress VCL套件是一套非常强大的界面控件,可惜关于Delphi开发方面的说明太少,有些控件使用起来一头雾水,不知从何下手。本节详细介绍在Delphi Xe10 Seattle中如何利用dxLayoutControl 控件来做…

MMENGINE.LOGGING

MMENGINE.LOGGING 文章目录 MMENGINE.LOGGING[Print_log](https://mmengine.readthedocs.io/zh_CN/latest/api/generated/mmengine.logging.print_log.html "Print_log")[MMENGINE.LOGGING.LOGGER 源代码](https://mmengine.readthedocs.io/zh_CN/latest/_modules/mm…

Rust每日一练(Leetday0030) 合并有序数组、格雷编码、子集II

目录 88. 合并两个有序数组 Merge Sorted Array 🌟  89. 格雷编码 Gray Code 🌟🌟 90. 子集 II Subsets II 🌟🌟 🌟 每日一练刷题专栏 🌟 Rust每日一练 专栏 Golang每日一练 专栏 Py…

计算机网络-网络体系结构

目录 计算机网络的基本概念计算机网络的定义组成与功能计算机网络的分类按照网络的作用范围进行分类按照网络的使用者进行分类 计算机网络主要性能指标 计算机网络体系结构计算机网络协议、接口、服务等概念ISO/OSI 参考模型和 TCP/IP 模型OSI七层模型TCP/IP 模型封装与分用 计…

[Hadoop之Hive安装配置 第二篇 ]

前言: 记录一下Hive笔记 目录 前言: Hive的基本简介,使用场景介绍 安装地址: 官网的Hive文档地址: 官网 Hive 的教程地址 Hive安装涉及到的应用介绍 Hive安装步骤: 1.解压hive压缩包, tar -zxvf 压缩包,然后进入module目录 查看压缩的文件 ,并改名为hive 2. pwd查看当…

Paper | CenterPoint

CenterPoint paper 文章目录 CenterPoint paper摘要IntroductionRelated WorkCenterPointTwo-Stage CenterPoint Reference 论文链接:https://arxiv.org/pdf/2006.11275.pdf 代码链接:https://github.com/tianweiy/CenterPoint 摘要 该文章是Center-ba…

SpringBoot--日志

日志的作用? 记录用户登陆日志,方便分析用户是正常登陆还是恶意破解用户记录系统的操作日志,方便数据恢复和定位操作人记录程序的执行时间,方便为以后优化程序提供数据支持 日志是程序的重要组成部分,最重要的用途是…

Leetcode | 40 组合总和II

40 组合总和II 文章目录 40 组合总和II题目官方解法:回溯思路与算法 codeReference 题目 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能…

【哈佛积极心理学笔记】第12讲 写日记

第12讲 写日记 preparationincubation (take a break, need some rest time)evaluationelaboration JP Morgan’s quote, I can do a year’s work in 9 months but not in 12" a simple technique of intervation: journaling Postive emotions and painful emotions…

CSS基础学习--12 分组 和 嵌套 选择器

一、分组选择器 在样式表中有很多具有相同样式的元素 h1 {color:green; } h2 {color:green; } p {color:green; } 为了尽量减少代码&#xff0c;你可以使用分组选择器。 每个选择器用逗号分隔。 在下面的例子中&#xff0c;我们对以上代码使用分组选择器&#xff1a; <!DO…

windows下cmake的小白级入门使用教程(hello world)

想学习cmake&#xff0c;基于惯性思维&#xff0c;想先跑通一个“hello world”的例子&#xff0c;奈何网上教程一大把&#xff0c;有用的教程破费功夫寻找。大部分教程都没有从新电脑(重装系统后的电脑)的角度讲述步骤。 为了得到干净的电脑环境&#xff0c;研究了一段时间VMw…

【图像任务】Transformer系列.3

本文介绍3篇改进Transformer以实现不同图像任务的工作&#xff1a;少样本医学图像分割CAT-Net&#xff08;arXiv2023&#xff09;&#xff0c;高效图像重建等任务GRL&#xff08;CVPR2023&#xff09;&#xff0c;轻量视觉Transformer中的局部信息思考CloFormer&#xff08;arX…

根据指定条件和规则逐一判断两个数组中对应元素是否接近 numpy.isclose()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 根据指定条件和规则逐一判断 两个数组中对应元素是否接近 numpy.isclose() [太阳]选择题 请问关于以下代码的表述错误的是&#xff1f; import numpy as np a np.array([2, 7, np.nan]) b …

【RabbitMQ教程】前言 —— 消息队列介绍

&#x1f4a7; 【 R a b b i t M Q 教程】前言——消息队列介绍 \color{#FF1493}{【RabbitMQ教程】前言 —— 消息队列介绍} 【RabbitMQ教程】前言——消息队列介绍&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风…

力扣题库刷题笔记3--无重复字符的最长子串

1、题目如下&#xff1a; 2、个人Python代码实现如下&#xff1a; 代码如下&#xff1a; class Solution: def lengthOfLongestSubstring(self, s: str) -> int: temp "" #临时变量&#xff0c;记录当前连续不重复子串 out_put …

MEC | 条款1 仔细区别pointers和references

More Effective C&#xff08;MEC&#xff09; 文章目录 More Effective C&#xff08;MEC&#xff09;条款1 仔细区别pointers和references结论 本章描述 pointers 和 references 的差异&#xff0c;并告诉你它们适当使用时机。 条款1 仔细区别pointers和references pointers…

cxgrid显示海量数据

在默认情况下&#xff0c;cxgrid显示几万条以上的数据会很慢。怎么办&#xff1f; 交下面的属性设为TRUE以后&#xff0c;速度飞快。 但速度是快了&#xff0c;自动计算列的合计值这些功能却失效了&#xff0c;正所谓有得必有失&#xff01;

CSS基础学习--11 padding(填充)

一、定义 CSS padding&#xff08;填充&#xff09;是一个简写属性&#xff0c;定义元素边框与元素内容之间的空间&#xff0c;即上下左右的内边距。 当元素的 padding&#xff08;填充&#xff09;内边距被清除时&#xff0c;所释放的区域将会受到元素背景颜色的填充。 单独使…