【python量化交易】qteasy使用教程07——创建更加复杂的自定义交易策略
创建更加复杂的自定义交易策略
- 使用交易策略类,创建更复杂的自定义策略
- 开始前的准备工作
- 本节的目标
- 继承Strategy类,创建一个复杂的多因子选股策略
- 策略和回测参数配置,并开始回测
- 本节回顾
使用交易策略类,创建更复杂的自定义策略
qteasy
是一个完全本地化部署和运行的量化交易分析工具包,Github地址在这里,并且可以通过pip安装:
$ pip install qteasy -U
qteasy
具备以下功能:
- 金融数据的获取、清洗、存储以及处理、可视化、使用
- 量化交易策略的创建,并提供大量内置基本交易策略
- 向量化的高速交易策略回测及交易结果评价
- 交易策略参数的优化以及评价
- 交易策略的部署、实盘运行
通过本系列教程,您将会通过一系列的实际示例,充分了解qteasy
的主要功能以及使用方法。
开始前的准备工作
在开始本节教程前,请先确保您已经掌握了下面的内容:
- 安装、配置
qteasy
—— QTEASY教程1 - 设置了一个本地数据源,并已经将足够的历史数据下载到本地——QTEASY教程2
- 学会创建交易员对象,使用内置交易策略,——QTEASY教程3
- 学会使用混合器,将多个简单策略混合成较为复杂的交易策略——QTEASY教程4
- 了解自定策略的基础——QTEASY教程5 ,QTEASY教程6
在QTEASY文档中,还能找到更多关于使用内置交易策略、创建自定义策略等等相关内容。对qteasy
的基本使用方法还不熟悉的同学,可以移步那里查看更多详细说明。
qteasy
的内核被设计为一个兼顾高速执行以及足够的灵活性的框架,理论上您可以实现您所设想的任何类型的交易策略。
同时,qteasy
的回测框架也做了相当多的特殊设计,可以完全避免您无意中在交易策略中导入"未来函数",确保您的交易策略在回测时完全基于过去的数据,同时也使用了很多预处理技术以及JIT技术对内核关键函数进行了编译,以实现不亚于C语言的运行速度。
不过,为了实现理论上无限可能的交易策略,仅仅使用内置交易策略以及策略混合就不一定够用了,一些特定的交易策略,或者一些特别复杂的交易策略是无法通过内置策略混合而成的,这就需要我们使用qteasy
提供的Strategy
基类,基于一定的规则创建一个自定义交易策略了。
本节的目标
在本节中,我们将介绍qteasy
的交易策略基类,通过一个具体的例子详细讲解如何基于这几个基类,创建一个只属于您自己的交易策略。为了说明
继承Strategy类,创建一个复杂的多因子选股策略
在这个例子中,我们使用
import qteasy as qt
import numpy as npdef market_value_weighted(stock_return, mv, mv_cat, bp_cat, mv_target, bp_target):""" 根据mv_target和bp_target计算市值加权收益率,在策略中调用此函数计算加权收益率"""sel = (mv_cat == mv_target) & (bp_cat == bp_target)mv_total = np.nansum(mv[sel])mv_weight = mv / mv_totalreturn_total = np.nansum(stock_return[sel] * mv_weight[sel])return return_totalclass MultiFactors(qt.FactorSorter):""" 开始定义交易策略"""def __init__(self, pars: tuple = (0.5, 0.3, 0.7)):"""交易策略的初始化参数"""super().__init__(pars=pars, par_count=3, # 策略的可调参数有三个par_types=['float', 'float', 'float'], # 参数1:大小市值分类界限,参数2:小/中bp分界线,参数3,中/大bp分界线par_range=[(0.01, 0.99), (0.01, 0.49), (0.50, 0.99)],name='MultiFactor',description='根据Fama-French三因子回归模型估算HS300成分股的alpha值选股',strategy_run_timing='close', # 在周期结束(收盘)时运行strategy_run_freq='m', # 每月执行一次选股(每周或每天都可以)strategy_data_types='pb, total_mv, close', # 执行选股需要用到的股票数据data_freq='d', # 数据频率(包括股票数据和参考数据)window_length=20, # 回测时的视窗长度为20天use_latest_data_cycle=True, # 设置使用最新的数据reference_data_types='close-000300.SH', # 选股需要用到市场收益率,使用沪深300指数的收盘价计算,因此设置HS300指数的收盘价作为参考数据传入max_sel_count=10, # 最多选出10支股票sort_ascending=True, # 选择因子最小的股票condition='less', # 仅选择因子小于某个值的股票lbound=0, # 仅选择因子小于0的股票ubound=0, # 仅选择因子小于0的股票 )def realize(self, h, **kwargs):""" 策略的选股逻辑在realize()函数中定义"""size_gate_percentile, bp_small_percentile, bp_large_percentile = self.pars# 读取投资组合的数据PB和total_MV的最新值pb = h[:, -1, 0] # 当前所有股票的PB值mv = h[:, -1, 1] # 当前所有股票的市值pre_close = h[:, -2, 2] # 当前所有股票的前收盘价close = h[:, -1, 2] # 当前所有股票的最新收盘价# 读取参考数据(r)market_pre_close = r[-2, 0] # HS300的昨收价market_close = r[-1, 0] # HS300的收盘价# 计算账面市值比,为pb的倒数bp = pb ** -1# 计算市值的50%的分位点,用于后面的分类size_gate = np.nanquantile(mv, size_gate_percentile)# 计算账面市值比的30%和70%分位点,用于后面的分类bm_30_gate = np.nanquantile(bp, bp_small_percentile)bm_70_gate = np.nanquantile(bp, bp_large_percentile)# 计算每只股票的当日收益率stock_return = pre_close / close - 1# 根据每只股票的账面市值比和市值,给它们分配bp分类和mv分类# 市值小于size_gate的cat为1,否则为2mv_cat = np.ones_like(mv)mv_cat += (mv > size_gate).astype('float')# bp小于30%的cat为1,30%~70%之间为2,大于70%为3bp_cat = np.ones_like(bp)bp_cat += (bp > bm_30_gate).astype('float')bp_cat += (bp > bm_70_gate).astype('float')# 获取小市值组合的市值加权组合收益率smb_s = (market_value_weighted(stock_return, mv, mv_cat, bp_cat, 1, 1) +market_value_weighted(stock_return, mv, mv_cat, bp_cat, 1, 2) +market_value_weighted(stock_return, mv, mv_cat, bp_cat, 1, 3)) / 3# 获取大市值组合的市值加权组合收益率smb_b = (market_value_weighted(stock_return, mv, mv_cat, bp_cat, 2, 1) +market_value_weighted(stock_return, mv, mv_cat, bp_cat, 2, 2) +market_value_weighted(stock_return, mv, mv_cat, bp_cat, 2, 3)) / 3smb = smb_s - smb_b# 获取大账面市值比组合的市值加权组合收益率hml_b = (market_value_weighted(stock_return, mv, mv_cat, bp_cat, 1, 3) +market_value_weighted(stock_return, mv, mv_cat, bp_cat, 2, 3)) / 2# 获取小账面市值比组合的市值加权组合收益率hml_s = (market_value_weighted(stock_return, mv, mv_cat, bp_cat, 1, 1) +market_value_weighted(stock_return, mv, mv_cat, bp_cat, 2, 1)) / 2hml = hml_b - hml_s# 计算市场收益率market_return = market_pre_close / market_close - 1coff_pool = []# 对每只股票进行回归获取其alpha值for rtn in stock_return:x = np.array([[market_return, smb, hml, 1.0]])y = np.array([[rtn]])# OLS估计系数coff = np.linalg.lstsq(x, y)[0][3][0]coff_pool.append(coff)# 以alpha值为股票组合的选股因子执行选股factors = np.array(coff_pool)return factors
策略和回测参数配置,并开始回测
定义好上面的策略之后,就可以开始进行回测了,我们需要在qteasy
中创建一个交易员对象,操作前面创建的策略:
shares = qt.filter_stock_codes(index='000300.SH', date='20190501') # 选择股票池,包括2019年5月以来所有沪深300指数成分股
# 设置回测的运行参数
qt.config(mode=1, # mode=1表示回测模式invest_start='20160405', # 回测开始日期invest_end='20210201', # 回测结束日期asset_type='E', # 投资品种为股票asset_pool=shares, # shares包含同期沪深300指数的成份股trade_batch_size=100, # 买入批量为100股sell_batch_size=1, # 卖出批量为整数股trade_log=True, # 生成交易记录)# 开始策略的回测alpha = MultiFactors() # 生成一个交易策略的实例,名为alpha
op = qt.Operator(alpha, signal_type='PT') # 生成交易员对象,操作alpha策略,交易信号的类型为‘PT',意思是生成的信号代表持仓比例,例如1代表100%持有股票,0.35表示持有股票占资产的35%
op.op_type = 'stepwise' # 运行模式为步进模式
op.set_blender('1.0*s0', "close") # 交易策略混合方式,只有一个策略,不需要混合
op.run() # 开始运行
本节回顾
相关文章:

【python量化交易】qteasy使用教程07——创建更加复杂的自定义交易策略
创建更加复杂的自定义交易策略 使用交易策略类,创建更复杂的自定义策略开始前的准备工作本节的目标继承Strategy类,创建一个复杂的多因子选股策略策略和回测参数配置,并开始回测 本节回顾 使用交易策略类,创建更复杂的自定义策略 …...

SpringBoot整合SpringScurity权限控制(菜单权限,按钮权限)以及加上SSH实现安全传输
文章目录 项目地址: 一、md5 与 先进的哈希算法的区别1.1. 安全性问题1.2. 设计目的1.3. 功能特性1.4. 适用性1.5. 总结 二、数据传输安全和数据加密实现:2.1 生成证书:2.2、在springboot中进行集成2.2.1 配置证书:2.2.2. 强制使用…...

力扣每日一题119:杨辉三角||
题目 简单 给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1]示例 2: 输入: rowIndex 0 输出: [1]示例 3: 输入: rowIndex 1 输出…...

AI语音模型PaddleSpeech踩坑(安装)指南
PaddleSpeech简介 PaddleSpeech 是基于飞桨 PaddlePaddle 的语音方向的开源模型库,用于语音和音频中的各种关键任务的开发,包含大量基于深度学习前沿和有影响力的模型。 PaddleSpeech安装步骤 提示:要找到一个合适的PaddleSpeech版本与pad…...

如何更好地使用Kafka? - 运行监控篇
要确保Kafka在使用过程中的稳定性,需要从kafka在业务中的使用周期进行依次保障。主要可以分为:事先预防(通过规范的使用、开发,预防问题产生)、运行时监控(保障集群稳定,出问题能及时发现&#…...

数据可视化训练第四天(模拟投掷筛子并且统计频次)
投掷一个筛子 import matplotlib.pyplot as plt from random import randint import numpy as npclass Die:"""模拟投掷筛子"""def __init__(self,num_sides6):self.num_sidesnum_sidesdef roll(self):return randint(1,self.num_sides)num1000…...

4.1 编写程序,从键盘接收一个小写字母,然后找出他的前导字符和后续字符,再按顺序显示这三个字符
方法一: 运行效果: 输入B,输出显示ABC;输入A,输出显示AB 思路: 1、通过键盘输入接收一个字母。 2、将输入的字母减去1,得到前导字符,然后输出。 3、将输入的字母加上1,得…...
(Java)心得:LeetCode——18.四数之和
一、原题 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复): …...

网络编程套接字详解
目录 1. 预备介绍 2.网络字节序 3.udp网络程序 4.地址转换函数 5.udp网络编程 1.预备介绍 1.1源IP地址和目标IP地址 举个例子: 从北京出发到上海旅游, 那么源IP地址就是北京, 目标IP地址就是上海. 1.2 端口号 作用: 标识一个进程, 告诉OS这个数据交给那个进程来处理; (1)…...
蓝桥杯备战11.歌唱比赛
P5738 【深基7.例4】歌唱比赛 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> #define endl \n #define int long long using namespace std; const int N 2e710,M 1e310; int a[N],sum[N];signed main() {//std::ios::sync_with_stdio(0),cin.…...
微信小程序中的图像奥秘:图片与Base64的华丽变身记
微信小程序中的图像奥秘:图片与Base64的华丽变身记 基本概念解析图片与Base64的关系为何转换 图片转Base64实战微信小程序使用wx.getImageInfo获取图片信息图片转换为Base64注意 Base64转图片直接在小程序页面显示云开发环境转换注意 遇遇问题排查思路结语引发讨论 …...

【35分钟掌握金融风控策略25】定额策略实战2
目录 基于收入和负债的定额策略 确定托底额度和盖帽额度 确定基础额度 基于客户风险评级确定风险系数 计算最终授信额度 确定授信有效期 基于收入和负债的定额策略 在实际生产中,客户的收入和负债数据大多无法直接获得,对于个人的收入和负债数据&…...
我和爬虫的故事
文章目录 爬虫简介个人经历未来总结 爬虫简介 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外…...

常用的简单友好的工单系统(免费)- WGCAT
最近在项目中,有工单系统的需求场景,所以想寻找一款轻量简单的运维工单软件,主要用来记录和处理工作中的一些故障、维护,主要用来记录设备的维护状态,包括服务器、主机、交换机那些 WGCAT,是一款简单轻量的…...

使用Pycharm编写Python程序时对基本类结构中方法的重写的两种初步操作方式
使用Pycharm编写Python程序时对基本类结构中方法的重写的两种初步操作方式 Python和其他一些高级面向对象的编程语言中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改&…...
HTTP URL 详解
概述 URL 提供了一种定位因特网上任意资源的手段,大多数 URL 语法都由以下九个结构的通用格式组成: <scheme>://<user>:<password><host>:<port>/<path>;<params>?<query>#<frag> 方案&#…...
Python 原生爬虫
Python 描述代码 描述 爬网站的页面配合正则表达式设置定时任务 仅学习参考,切勿使用其他用途 代码 import re import schedule import timefrom urllib.request import urlopenclass Spider:def __init__(self):# 初始化代码...pass# self.start_schedule()# 需要…...

数据结构---经典链表OJ
乐观学习,乐观生活,才能不断前进啊!!! 我的主页:optimistic_chen 我的专栏:c语言 点击主页:optimistic_chen和专栏:c语言, 创作不易,大佬们点赞鼓…...
HTML_CSS学习:CSS像素与颜色
一、像素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>像素</title> </head><style>.atguigu1{/*单位可以是cm,但不能是m,dm*/width: 1cm;height: 1cm;background-c…...

华为交换机配置导出备份python脚本
一、脚本编写思路 (一)针对设备型号 主要针对华为(Huawei)和华三(H3C)交换机设备的配置备份 (二)导出前预处理 1.在配置导出前,自动打开crt软件或者MobaXterm软件&am…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...