当前位置: 首页 > article >正文

量化交易 - 聚宽joinquant - 多因子入门研究 - 源码开源

先看一下我们的收益: JoinQuant直达这里看看

 下面讲解原理和代码。

目录

一、是否为st

二、是否停牌

三、市值小、roe大

四、编写回测代码


今天来研究一下多因子回测模型,这里以‘市值’、‘roe’作为例子。

几个标准:沪深300里选股,市值小、roe大、排出st 停牌、定期调仓

一、是否为st

# 是否st
is_st_info = get_extras('is_st', ['000001.XSHE', '000018.XSHE'], start_date='2025-04-01', end_date='2025-04-10', df=True)
print(is_st_info)
            000001.XSHE  000018.XSHE
2025-04-01        False         True
2025-04-02        False         True
2025-04-03        False         True
2025-04-07        False         True
2025-04-08        False         True
2025-04-09        False         True
2025-04-10        False         True

然后我们改装成为函数

# 获取st股票
def get_st_stocks(stock_list, end_date, count):is_st_info = get_extras('is_st', stock_list, end_date=end_date, count=count, df=True)st_stocks = []for stock in stock_list:if is_st_info[stock].any():  # 检查该股票是否在任何一天为Truest_stocks.append(stock)return st_stocksx = get_st_stocks(['300956.XSHE', '300542.XSHE', '000018.XSHE'], end_date='2025-04-12', count=5)
print(x)

二、是否停牌

# 是否停牌
x = get_price(['300956.XSHE', '300542.XSHE'], count=5, end_date='2025-04-12', fields='paused',frequency='daily', skip_paused=False, panel=False)
print(x)
        time         code  paused
0 2025-04-07  300956.XSHE     0.0
1 2025-04-08  300956.XSHE     0.0
2 2025-04-09  300956.XSHE     0.0
3 2025-04-10  300956.XSHE     1.0
4 2025-04-11  300956.XSHE     1.0
5 2025-04-07  300542.XSHE     0.0
6 2025-04-08  300542.XSHE     1.0
7 2025-04-09  300542.XSHE     1.0
8 2025-04-10  300542.XSHE     1.0
9 2025-04-11  300542.XSHE     1.0

同样,我们改装成函数

# 是否停牌
def get_paused_stocks(stock_list, end_date, count):paused_info = get_price(stock_list, count=count, end_date=end_date, fields='paused', frequency='daily', skip_paused=False, panel=False)paused_stocks = []for stock in stock_list:if (paused_info[paused_info['code'] == stock]['paused'] == 1.0).any():  # 检查该股票是否在任何一天为1.0paused_stocks.append(stock)return paused_stocksx = get_paused_stocks(['000001.XSHE', '300956.XSHE', '300542.XSHE'], end_date='2025-04-12', count=5)
print(x)

 

三、市值小、roe大

获取某一天沪深300股票中yb天不停牌、不st,且满足市值和ROE排名前N的股票

from jqdata import *def get_mystocks(date, yb=63, N=20):"""获取某一天沪深300股票中yb天不停牌、不st,且满足市值和ROE排名前N的股票:param date: 指定日期:param yb: 多少天不停牌:param N: 排名前多少:return: 满足条件的股票代码列表"""# 获取沪深300的成分股hs300_stocks = get_index_stocks('000300.XSHG', date=date)# 获取股票的基本面数据q = query(valuation.code,valuation.market_cap,indicator.roe).filter(valuation.code.in_(hs300_stocks))df = get_fundamentals(q, date=date)#print(df.head())# 获取停牌股票paused_stocks = get_paused_stocks(hs300_stocks, end_date=date, count=yb)#print(paused_stocks)# 获取st股票st_stocks = get_st_stocks(hs300_stocks, end_date=date, count=yb)#print(st_stocks)# 获取剔除停牌和ST的股票代码列表all_paused_stocks = set(paused_stocks + st_stocks)# 从df中筛选出剔除停牌和ST的股票df = df[~df['code'].isin(all_paused_stocks)]# 对市值进行升序排名,对ROE进行降序排名df['market_cap_rank'] = df['market_cap'].rank(method='first', ascending=True)df['roe_rank'] = df['roe'].rank(method='first', ascending=False)df['composite_rank'] = df['market_cap_rank'] + df['roe_rank']# 按综合排名升序排序并选取前Ndf_sorted = df.sort_values(by='composite_rank', ascending=True).head(N)# 提取股票代码并返回mystocks = df_sorted['code'].tolist()return mystocksmystocks = get_mystocks('2024-12-31')
print(mystocks)
['300628.XSHE', '002555.XSHE', '000876.XSHE', '300394.XSHE', '603833.XSHG', '605117.XSHG', '300316.XSHE', '000975.XSHE', '000661.XSHE', '002007.XSHE', '601021.XSHG', '601799.XSHG', '300896.XSHE', '688082.XSHG', '000807.XSHE', '000408.XSHE', '300832.XSHE', '600570.XSHG', '002920.XSHE', '600066.XSHG']

 

四、编写回测代码

# 导入函数库
from jqdata import *
import datetime
import numpy as np# 策略初始化
def initialize(context):set_benchmark('000300.XSHG')set_option('use_real_price', True)log.set_level('order', 'error')set_order_cost(OrderCost(close_tax=0, open_commission=0, close_commission=0, min_commission=0), type='stock')g.t = 0g.tc = 15  # 调仓频率g.yb = 63  # 样本长度g.N = 20   # 持仓数量run_daily(market_open, time='open', reference_security='000300.XSHG')def market_open(context):now = context.current_dtbefore_1d_time = now - timedelta(days=1)end_date = before_1d_time.strftime("%Y-%m-%d")if g.t % g.tc == 0:mystocks = get_mystocks(end_date, g.yb, g.N)rebalance_position(context, mystocks)g.t += 1# 获取st股票
def get_st_stocks(stock_list, end_date, count):is_st_info = get_extras('is_st', stock_list, end_date=end_date, count=count, df=True)st_stocks = []for stock in stock_list:if is_st_info[stock].any():  # 检查该股票是否在任何一天为Truest_stocks.append(stock)return st_stocks# 是否停牌
def get_paused_stocks(stock_list, end_date, count):paused_info = get_price(stock_list, count=count, end_date=end_date, fields='paused', frequency='daily', skip_paused=False, panel=False)paused_stocks = []for stock in stock_list:if (paused_info[paused_info['code'] == stock]['paused'] == 1.0).any():  # 检查该股票是否在任何一天为1.0paused_stocks.append(stock)return paused_stocksdef get_mystocks(date, yb=63, N=20):"""获取某一天沪深300股票中yb天不停牌,且满足市值和ROE排名前N的股票:param date: 指定日期:param yb: 多少天不停牌:param N: 排名前多少:return: 满足条件的股票代码列表"""# 获取沪深300的成分股hs300_stocks = get_index_stocks('000300.XSHG', date=date)# 获取股票的基本面数据q = query(valuation.code,valuation.market_cap,indicator.roe).filter(valuation.code.in_(hs300_stocks))df = get_fundamentals(q, date=date)#print(df.head())# 获取停牌股票paused_stocks = get_paused_stocks(hs300_stocks, end_date=date, count=yb)#print(paused_stocks)# 获取st股票st_stocks = get_st_stocks(hs300_stocks, end_date=date, count=yb)#print(st_stocks)# 获取剔除停牌和ST的股票代码列表all_paused_stocks = set(paused_stocks + st_stocks)# 从df中筛选出剔除停牌和ST的股票df = df[~df['code'].isin(all_paused_stocks)]# 对市值进行升序排名,对ROE进行降序排名df['market_cap_rank'] = df['market_cap'].rank(method='first', ascending=True)df['roe_rank'] = df['roe'].rank(method='first', ascending=False)df['composite_rank'] = df['market_cap_rank'] + df['roe_rank']# 按综合排名升序排序并选取前Ndf_sorted = df.sort_values(by='composite_rank', ascending=True).head(N)# 提取股票代码并返回mystocks = df_sorted['code'].tolist()return mystocks"""
###################### 工具 ######################调仓:
先卖出持仓中不在 stock_list 中的股票
再等价值买入 stock_list 中的股票
"""
def rebalance_position(context, stock_list):current_holding = context.portfolio.positions.keys()stocks_to_sell = list(set(current_holding) - set(stock_list))# 卖出bulk_orders(stocks_to_sell, 0)total_value = context.portfolio.total_value# 买入bulk_orders(stock_list, total_value/len(stock_list))# 批量买卖股票
def bulk_orders(stock_list,target_value):for i in stock_list:order_target_value(i, target_value)

上面就是所有的源码了。

参考:这里

原文太老了,代码也比较繁琐,故简化很多。

相关文章:

量化交易 - 聚宽joinquant - 多因子入门研究 - 源码开源

先看一下我们的收益: JoinQuant直达这里看看 下面讲解原理和代码。 目录 一、是否为st 二、是否停牌 三、市值小、roe大 四、编写回测代码 今天来研究一下多因子回测模型,这里以‘市值’、‘roe’作为例子。 几个标准:沪深300里选股&am…...

本地缓存方案Guava Cache

Guava Cache 是 Google 的 Guava 库提供的一个高效内存缓存解决方案&#xff0c;适用于需要快速访问且不频繁变更的数据。 // 普通缓存 Cache<Key, Value> cache CacheBuilder.newBuilder().maximumSize(1000) // 最大条目数.expireAfterWrite(10, TimeUnit.MINUTES) /…...

虚拟列表react-virtualized使用(npm install react-virtualized)

1. 虚拟化列表 (List) // 1. 虚拟化列表 (List)import { List } from react-virtualized; import react-virtualized/styles.css; // 只导入一次样式// 示例数据 const list Array(1000).fill().map((_, index) > ({id: index,name: Item ${index},description: This is i…...

解释型语言和编译型语言的区别

Python 的执行过程通常涉及字节码&#xff0c;而不是直接将代码编译为机器码。以下是详细的解释&#xff1a; ### **Python 的执行过程** 1. **源代码到字节码**&#xff1a; - Python 源代码&#xff08;.py 文件&#xff09;首先被编译为字节码&#xff08;.pyc 文件&…...

猫咪如厕检测与分类识别系统系列【三】融合yolov11目标检测

✅ 前情提要 家里养了三只猫咪&#xff0c;其中一只布偶猫经常出入厕所。但因为平时忙于学业&#xff0c;没法时刻关注牠的行为。我知道猫咪的如厕频率和时长与健康状况密切相关&#xff0c;频繁如厕可能是泌尿问题&#xff0c;停留过久也可能是便秘或不适。为了更科学地了解牠…...

sql server 字段逗号分割取后面的值

在 SQL Server 中&#xff0c;如果你有一个字段&#xff08;字段类型通常是字符串&#xff09;&#xff0c;其中包含用逗号分隔的值&#xff0c;并且你想提取这些值中逗号后面的特定部分&#xff0c;你可以使用多种方法来实现这一点。这里我将介绍几种常见的方法&#xff1a; …...

FPGA 37 ,FPGA千兆以太网设计实战:RGMII接口时序实现全解析( RGMII接口时序设计,RGMII~GMII,GMII~RGMII 接口转换 )

目录 前言 一、设计流程 1.1 需求理解 1.2 模块划分 1.3 测试验证 二、模块分工 2.1 RGMII→GMII&#xff08;接收方向&#xff0c;rgmii_rx 模块&#xff09; 2.2 GMII→RGMII&#xff08;发送方向&#xff0c;rgmii_tx 模块&#xff09; 三、代码实现 3.1 顶层模块 …...

上篇:《排序算法的奇妙世界:如何让数据井然有序?》

个人主页&#xff1a;strive-debug 排序算法精讲&#xff1a;从理论到实践 一、排序概念及应用 1.1 基本概念 **排序**&#xff1a;将一组记录按照特定关键字&#xff08;如数值大小&#xff09;进行递增或递减排列的操作。 1.2 常见排序算法分类 - **简单低效型**&#xff…...

红宝书第三十四讲:零基础学会单元测试框架:Jest、Mocha、QUnit

红宝书第三十四讲&#xff1a;零基础学会单元测试框架&#xff1a;Jest、Mocha、QUnit 资料取自《JavaScript高级程序设计&#xff08;第5版&#xff09;》。 查看总目录&#xff1a;红宝书学习大纲 一、单元测试是什么&#xff1f; 就像给代码做“体检”&#xff0c;帮你检查…...

【JDBC-54.1】MySQL JDBC连接字符串常用参数详解

在Java应用程序中连接MySQL数据库时&#xff0c;JDBC连接字符串是建立连接的关键。一个配置得当的连接字符串不仅能确保连接成功&#xff0c;还能优化性能、增强安全性并处理各种连接场景。本文将深入探讨MySQL JDBC连接字符串的常用参数及其最佳实践。 1. 基本连接字符串格式…...

swagger 注释说明

一、接口注释核心字段 在 Go 的路由处理函数&#xff08;Handler&#xff09;上方添加注释&#xff0c;支持以下常用注解&#xff1a; 注解名称用途说明示例格式Summary接口简要描述Summary 创建用户Description接口详细说明Description 通过用户名和邮箱创建新用户Tags接口分…...

CST1019.基于Spring Boot+Vue智能洗车管理系统

计算机/JAVA毕业设计 【CST1019.基于Spring BootVue智能洗车管理系统】 【项目介绍】 智能洗车管理系统&#xff0c;基于 Spring Boot Vue 实现&#xff0c;功能丰富、界面精美 【业务模块】 系统共有三类用户&#xff0c;分别是&#xff1a;管理员用户、普通用户、工人用户&…...

【前端网络请求】XHR封装,支持文件上传、进度监控、混合字段传输

网络请求介绍 XMLHttpRequest(XHR)是前端开发中用于发起网络请求的基础技术。虽然现代开发中常用fetch或axios,但掌握XHR的封装技巧仍能让你更灵活地应对复杂需求。本文将通过一个可复用、功能全面的XHR封装工具,教你实现以下功能: 📤 文件上传(单个/多个文件)📊 实…...

# Shell脚本参数设计规范(DeepSeek指导)

Shell脚本参数设计规范&#xff08;DeepSeek指导&#xff09; 文章目录 Shell脚本参数设计规范&#xff08;DeepSeek指导&#xff09;A 我问&#xff1a;Q DeepSeek回答&#xff1a;**命令行参数表示规范****标准化表示示例**情况1&#xff1a;必选选项参数值情况2&#xff1a;…...

学习SqlSugar的跨库查询基本用法

使用SqlSugar操作数据库通常都是单库操作&#xff0c;跨库查询的情况要么是单个系统数据不完整&#xff0c;需要其它系统的关联业务数据支撑&#xff0c;要么就是需要整合汇总多个系统的数据进行数据数据分析、处理、展示。遇到上述情况&#xff0c;可以要求另外的系统提供查询…...

HTTP:五.WEB服务器

web服务器 定义:实现提供资源或应答的提供者都可以谓之为服务器!web服务器工作内容 接受建立连接请求 接受请求 处理请求 访问报文中指定的资源 构建响应 发送响应 记录事务处理过程 Web应用开发用到的一般技术元素 静态元素:html, img,js,Css,SWF,MP4 动态元素:PHP,…...

5.3 GitHub订阅系统核心架构解密:高并发设计与SQLite优化实战

GitHub Sentinel 分析报告功能实现:订阅管理核心逻辑解析 关键词:GitHub API 订阅管理, SQLite 数据库设计, RESTful API 开发, 原子操作封装, 异常处理机制 1. 订阅管理功能架构设计 订阅管理模块采用分层架构设计,通过清晰的接口隔离实现高内聚低耦合: #mermaid-svg-bW…...

CSI-PVController-volumeWorker

volumeWorker() 与claim worker流程一样&#xff0c;从volumeQueue中取数据&#xff0c;也就是取出的都是PV&#xff0c;如果informer中有这个pv&#xff0c;就进入update流程。 定义workFunc&#xff1a;首先&#xff0c;定义了一个匿名函数workFunc&#xff0c;这个函数是实…...

0基础 | 硬件滤波 C、RC、LC、π型

一、滤波概念 &#xff08;一&#xff09;滤波定义 滤波是将信号中特定波段频率滤除的操作&#xff0c;是抑制和防止干扰的重要措施。通过滤波器实现对特定频率成分的筛选&#xff0c;确保目标信号的纯净度&#xff0c;提升系统稳定性。 &#xff08;二&#xff09;滤波器分…...

图论基础理论

在我看来&#xff0c;想要掌握图的基础应用&#xff0c;仅需要三步走。 什么是图&#xff08;基本概念&#xff09;、图的构造&#xff08;打地基&#xff09;、图的遍历方式&#xff08;应用的基础&#xff09; 只要能OK的掌握这三步、就算图论入门了&#xff01;&#xff0…...

leaflet 之 获取中国某个行政区的经纬度边界(latLngBounds)

思路 在json文件中获取下面的四个点 组成东北,西南两组 { “southwest”: { “lat”: 35.950, “lng”: 120.000 },//西南方 “northeast”: { “lat”: 36.200, “lng”: 120.300 }//东北方 } 最西点经度&#xff08;minLng&#xff09; 最东点经度&#xff08;maxLng&#x…...

企业级低代码平台的架构范式转型研究

在快速迭代的数字时代&#xff0c;低代码平台如同一股清流&#xff0c;悄然成为开发者们的新宠。 它利用直观易用的拖拽式界面和丰富的预制组件&#xff0c;将应用程序的开发过程简化到了前所未有的程度。通过封装复杂的编程逻辑和提供强大的集成能力&#xff0c;低代码平台让…...

怎么免费下载GLTF/GLB格式模型文件,还可以在线编辑修改

​ 现在非常流行glb格式模型&#xff0c;和gltf格式文件&#xff0c;可是之类模型网站非常非常少 1&#xff0c;咱们先直接打开http://glbxz.com 官方glb下载网站 glbxz.com 2 可以搜索&#xff0c;自己想要的模型关键词 3&#xff0c;到自己想下载素材页面 4&#xff0c;…...

MyBatis 中 Mapper 传递参数的多种方法

# MyBatis Mapper 传递参数的多种方法及其优势 在使用 MyBatis 进行数据库操作时&#xff0c;Mapper 接口的参数传递是一个非常基础但又十分重要的部分。不同的参数传递方式适用于不同的场景&#xff0c;合理选择可以大大提高代码的可读性和维护性。本文将详细介绍几种常见的 …...

大模型到底是怎么产生的?一文揭秘大模型诞生全过程

前言 大模型到底是怎么产生的呢? 本文将从最基础的概念开始,逐步深入,用通俗易懂的语言为大家揭开大模型的神秘面纱。 大家好,我是大 F,深耕AI算法十余年,互联网大厂核心技术岗。 知行合一,不写水文,喜欢可关注,分享AI算法干货、技术心得。 【专栏介绍】: 欢迎关注《…...

2025年3月 Scratch图形化三级 真题解析 中国电子学会全国青少年软件编程等级考试

2025年3月Scratch图形化编程等级考试三级真题试卷 一、选择题 第 1 题 默认小猫角色&#xff0c;scratch运行程序后&#xff0c;下列说法正确的是&#xff1f;&#xff08; &#xff09; A.小猫的颜色、位置在一直变化 B.小猫在舞台中的位置在一直变化&#xff0c;颜色…...

判断两个 IP 地址是否在同一子网 C

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> // 将点分十进制的 IP 地址转换为 32 位无符号整数 unsigned int ip_to_uint(const char *ip) { struct in_addr addr; if (inet_pton(AF_INET, ip, &am…...

DHCP中继

前言&#xff1a; DHCP Relay即DHCP中继&#xff0c;它是为解决DHCP服务器和DHCP客户端不在同一个广播域而提出的 DHCP中继 DHCP协议依赖广播通信&#xff08;如客户端发送DHCP Discover报文&#xff09;&#xff0c;但广播报文无法跨越子网&#xff0c;因为&#xff1a; 路由…...

02 - spring security基于配置文件及内存的账号密码

spring security基于配置的账号密码 文档 00 - spring security框架使用01 - spring security自定义登录页面 yml文件中配置账号密码 spring:security:user:name: adminpassword: 123456yml文件中配置账号密码后&#xff0c;控制台将不再输出临时密码 基于内存的账号密码 …...

【贪心之摆动序列】

题目&#xff1a; 分析&#xff1a; 这里我们使用题目中给的第二个实例来进行分析 题目中要求我们序列当中有多少个摆动序列&#xff0c;摆动序列满足一上一下&#xff0c;一下一上&#xff0c;这样是摆动序列&#xff0c;并且要输出摆动序列的最长长度 通过上面的图我们可以…...