Python量化交易05——基于多因子选择和选股策略(随机森林,LGBM)

article/2025/9/24 6:32:45

  参考书目:深入浅出Python量化交易实战


在机器学习里面的X叫做特征变量,在统计学里面叫做协变量也叫自变量,在量化投资里面则叫做因子,所谓多因子就是有很多的特征变量。

本次带来的就是多因子模型,并且使用的是机器学习的强大的非线性模型,集成学习里面的随机森林和LGBM模型,带来因子的选择策略和股票的选择策略。


由于股票数据的获取都需要第三方库或者是专业的量化投资框架,很多第三方库某些功能需要收费(Tushare),而免费的一些库(证券宝)获取的数据特征变量又没那么多。所以这里是用聚宽量化投资框架,是可以免费使用一些功能的(只需要注册一个账号)。这里获取数据就采用聚宽平台的功能了。


数据获取

本次使用沪深300作为股票池,选获取一些财务指标:

#创建query对象,指定获取股票的代码、市值、净运营资本
#净债务、产权比率、股东权益比率、营收增长率、换手率、
#市盈率(PE)、市净率(PB)、市销率(PS)、总资产收益率因子

#还是先导入jqdata和技术分析工具
import jqdata
from jqlib.technical_analysis import *
#同样选择沪深300成分股做股票池
stocks = get_index_stocks('000300.XSHG')q = query(valuation.code, valuation.market_cap,balance.total_current_assets- balance.total_current_liability,balance.total_liability- balance.total_assets,balance.total_liability/balance.equities_parent_company_owners,(balance.total_assets-balance.total_current_assets)/balance.total_assets,balance.equities_parent_company_owners/balance.total_assets,indicator.inc_total_revenue_year_on_year,valuation.turnover_ratio,valuation.pe_ratio,valuation.pb_ratio,valuation.ps_ratio,indicator.roa).filter(valuation.code.in_(stocks))
#将获得的因子值存入一个数据表
df = get_fundamentals(q, date = None)
#把数据表的字段名指定为对应的因子名
df.columns = ['code', '市值', '净营运资本', '净债务', '产权比率','非流动资产比率','股东权益比率', '营收增长率','换手率','PE','PB','PS','总资产收益率']
#检查结果
df.head()

 需要在聚宽的环境才能获得上面的数据,本地Python是出不来的。

设置一下股票代码作为索引,获取一些时间格式。

#将股票代码作为数据表的index
df.index = df.code.values
#使用del也可以删除列
del df['code']
#下面来把时间变量都定义好
today = datetime.datetime.today()
#设定3个时间差,分别是50天,1天和2天
delta50 = datetime.timedelta(days=50)
delta1 = datetime.timedelta(days=1)
delta2 = datetime.timedelta(days=2)
#50日前作为一个历史节点
history = today - delta50
#再计算昨天和2天前的日期
yesterday = today - delta1
two_days_ago = today - delta2

再然后获取一些技术指标数据:

#下面就获取股票的动量线、成交量、累计能量线、平均差、
#指数移动平均、移动平均、乖离率等因子
#时间范围都设为10天


df['动量线']=list(MTM(df.index, two_days_ago, timeperiod=10, unit = '1d', include_now = True, fq_ref_date = None).values())df['成交量']=list(VOL(df.index, two_days_ago, M1=10 ,unit = '1d', include_now = True, fq_ref_date = None)[0].values())df['累计能量线']=list(OBV(df.index,check_date=two_days_ago, timeperiod=10).values())df['平均差']=list(DMA(df.index, two_days_ago, N1 = 10, unit = '1d', include_now = True, fq_ref_date = None)[0].values())df['指数移动平均']=list(EMA(df.index, two_days_ago, timeperiod=10, unit = '1d', include_now = True, fq_ref_date = None).values())df['移动平均']=list(MA(df.index, two_days_ago, timeperiod=10, unit = '1d', include_now = True, fq_ref_date = None).values())df['乖离率']=list(BIAS(df.index,two_days_ago, N1=10, unit = '1d', include_now = True, fq_ref_date = None)[0].values())
#把数据表中的空值用0来代替
df.fillna(0,inplace=True)
#检查是否成功
df.head()

这样就获得了很多X,即特征变量,即因子。

下面构建y,我们的响应变量是一个分类的变量,即是否获得了超过市场的平均回报的收益率,是的话为1,不是为0 。

这里使用前一日的收盘价除以前50天的收盘价 然后减去1,作为收益率的值,计算出那些收益率大于均值的样本股则y为1 ,否则为0 。

#获取股票前一日的收盘价
df['close1']=list(get_price(stocks, end_date=yesterday, count = 1,fq='pre',panel=False)['close'])
#获取股票50日前的收盘价
df['close2']=list(get_price(stocks,  end_date=history, count = 1,fq ='pre',panel=False)['close'])#计算出收益
df['return']=df['close1']/df['close2']-1
#如果收益大于平均水平,则标记为1
#否则标记为0
df['signal']=np.where(df['return']<df['return'].mean(),0,1)
#检查是否成功
df.head()

 可以看到最后一列是我们的响应变量y。


模型构建

将X和y都准备好。划分训练集和测试集,导入随机森林分类器。

#导入数据集拆分工具
from sklearn.model_selection import train_test_split
#导入随机森林分类器
from sklearn.ensemble import RandomForestClassifier
#把因子值作为样本的特征,所以要去掉刚刚添加的几个字段
X = df.drop(['close1', 'close2', 'return', 'signal'], axis = 1)
#把signal作为分类标签
y = df['signal']
#将数据拆分为训练集和验证集
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size = 0.2)
#创建随机森林分类器实例,指定random_state便于复现
clf = RandomForestClassifier(n_estimators=5000,random_state=100)
#拟合训练集数据
clf.fit(X_train, y_train)
#查看分类器在训练集和验证集中的准确率
print(clf.score(X_train, y_train),clf.score(X_test, y_test))

 

分类问题,所以采用随机森林分类器,然后进行拟合和评价。

可以看到在训练集上的准确率为100%,在测试集删高的准确率为0.9333,说明模型的拟合效果很不错。


 

 因子重要性

接下来使用随机森林的变量的重要性排序,原理是基础学习器决策树分裂时,若一个变量分裂时让损失函数下降得越多,说明这个变量越重要。

#为了便于观察,我们创建一个数据表
#数据表有两个字段,分别是特征名和重要性
#特征名就是因子的名称


factor_weight = pd.DataFrame({'features':list(X.columns),'importance':clf.feature_importances_}).sort_values(#这里根据重要程度降序排列,一遍遍找到重要性最高的特征by='importance', ascending = False)
#检查结果
factor_weight

 可以看到最重要的变量是技术指标平均差。这也是肯定的,因为平均差里面包含了过去和现在的股价信息最多,和我们的响应变量最为相似。

画图更加直观的查看变量重要性排序。

import seaborn as sns
plt.figure(figsize=(6,4),dpi=128)
sns.barplot(y=factor_weight['features'],x=factor_weight['importance'],orient="h")
plt.xlabel('重要程度')
plt.ylabel('因子名称')
plt.xticks(fontsize=10,rotation=35)
plt.title("因子重要性对比")
plt.show()

 和上面结论一样,技术指标平均差对我们的响应变量是否获得超额回报的影响最大,然后是公司本身的财务指标,营业收入增长率,净收运营资本等。


选股策略

接下来我们使用对于表格数据最强的机器学习方法,轻量梯度提升方法——LGBM模型,对我们的股票市值进行预测,然后选取实际值和预测值差距最大的股票作为选股策略。即选取价值被低估的股票。

此时y是股票市值,X是前面那些财务技术指标

X=df.iloc[:,1:-3]
y=df.iloc[:,0]

构建回归器

from lightgbm import LGBMRegressor
model = LGBMRegressor(n_estimators=100,objective='regression', random_state=0)
model.fit(X, y)
model.score(X, y)

 整体模型的拟合优度为86%,还不错。

用真实值减去预测值,然后进行排序,算的找出前10 的被低估的公司

diff = pd.DataFrame(np.array(y)-model.predict(X), index = y.index, columns = ['预测值和真实值的差值'])
#将该数据表中的值,按生序进行排列
diff = diff.sort_values(by = '预测值和真实值的差值', ascending = True)
#找到市值被低估最多的10只股票
diff.head(10)

 前十都是被低估了,负得越多说明被低估的越厉害。


 受限于框架的使用,该策略我本人没有进行回测检验其收益率。书上的收益率大概是年化6%,不高,但是也算不错了。

(本案例仅作为策略研究,不构成任何投资意见。)


http://chatgpt.dhexx.cn/article/w9VcPcS1.shtml

相关文章

LightGBM(lgb)详解

1. LightGBM简介 GBDT (Gradient Boosting Decision Tree) 是机器学习中一个长盛不衰的模型&#xff0c;其主要思想是利用弱分类器&#xff08;决策树&#xff09;迭代训练以得到最优模型&#xff0c;该模型具有训练效果好、不易过拟合等优点。GBDT不仅在工业界应用广泛&#…

[机器学习] 模型融合GBDT(xgb/lgbm/rf)+LR 的原理及实践

目录 一、原理 GBDT LR 是什么,用在哪 二、说明 GBDT LR 的结构 RF LR ? Xgb LR? GBDT LR 模型提升 三、实践 1 如何获得样本落在哪个叶子节点 2 举例 2.2.1 训练集准备 2.2.2 RFLR 2.2.3 GBDTLR 2.2.4 XgboostLR 2.2.5 单独使用RF, GBDT和Xgboost 2.2.6 …

xgboost 与 lgbm

相关性分析模型可行性报告 基于数值的模型-xgboost 简介 XGBoost是一个优化的分布式梯度提升库&#xff0c;旨在高效&#xff0c;灵活和便携。它在梯度提升框架下实现机器学习算法。XGBoost提供了一个并行树提升&#xff08;也称为GBDT&#xff0c;GBM&#xff09;&#xff…

一文彻底看懂LightGBM

本文适合有集成学习与XGBoost基础的读者了解LightGBM算法。 序 LightGBM是基于XGBoost的改进版&#xff0c;在处理样本量大、特征纬度高的数据时&#xff0c;XGBoost效率和可扩展性也不够理想&#xff0c;因为其在对树节点分裂时&#xff0c;需要扫描每一个特征的每一个特征值…

LGBM算法

LGBM 算法定义算法实践其他 算法概念 Light GBM is a gradient boosting framework that uses tree based learning algorithm。 传统的GBDT算法存在的问题&#xff1a; 如何减少训练数据 常用的减少训练数据量的方式是down sample。例如在[5]中&#xff0c;权重小于阈值的…

LGBM调参方法学习

一、了解LGBM参数&#xff1a; LGBM是微软发布的轻量梯度提升机&#xff0c;最主要的特点是快&#xff0c;回归和分类树模型。使用LGBM首先需要查看其参数含义&#xff1a; 微软官方github上的说明&#xff1a; https://github.com/Microsoft/LightGBM/blob/master/docs/Param…

使用线性回归、LGBM对二手车价格进行预测

使用线性回归、LGBM对二手车价格进行预测 目录 使用线性回归、LGBM对二手车价格进行预测说明 数据导入、查看和清洗数据说明导入训练集导入测试集合并数据查看数据整体情况处理数据检查并处理缺失变量 EDA年份和价格地区和价格前任里程和价格燃料类型和价格传动装置类型Mileage…

MFC VS2010 Open CASCADE新建自己的工程

最近磕磕绊绊的去尝试用open cascade建立自己需要的工程文件&#xff0c;终于成功了&#xff0c;一直从网上获取方法&#xff0c;今天自己写一点心得&#xff0c;分享给大家。 一、准备&#xff1a; 1、安装 open cascade &#xff0c; 我安装后目录是&#xff1a; C:\OpenCAS…

[C++] OpenCasCade空间几何库的模型展现

OpenCasCade是什么 Open CASCADE&#xff08;简称OCC&#xff09;平台是由法国Matra Datavision公司开发的CAD/CAE/CAM软件平台&#xff0c;可以说是世界上最重要的几何造型基础软件平台之一。开源OCC对象库是一个面向对象C类库&#xff0c;用于快速开发设计领域的专业应用程序…

MFC中使用OpenCasCade示例

目录&#xff1a; 一、OpenCasCade开发环境搭建 二、创建一个MFC应用程序 三、在MFC工程中添加代码 四、画个瓶子 一、OpenCasCade开发环境搭建 参见《OpenCasCade开发环境搭建》&#xff0c;这篇文章最后运行示例前所做的工作为以后开发OpenCasCade工程铺平了路&#xff…

HTML<HBuilder X>

一&#xff1a;网页基本标签元素 HTML常用标签(HTML不是一种编程语言&#xff0c;而是一种标记语言&#xff09;&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>文档标题</title> </head><…

Opencascade 开发 1章

序 这一系列的文章旨在介绍一个方便大家开始开发自己CAD的方法。需要指出的是&#xff0c;本人主要希望通过分享一些相关技术&#xff0c;提升国人软件自主的意识和途径。通过本文构建自己的CAD只是软件自主化的非常非常小的一步&#xff0c;希望大家在不停尝试的过程中有所提…

【OCC学习5】记录最新版本emcc编译occ的bug:opencascade-7.6.0/src/Standard/Standard_Time.hxx:29:25: error: redefinit

1. 在研究OCC与Webassembly结合使用&#xff0c;编译的时候遇到以下问题&#xff1a; C:/workspace/occ_wasm/opencascade-7.6.0/src/Standard/Standard_Integer.hxx:126:25: note: previous definition is here inline Standard_Boolean IsEqual (const Standard_Integer the…

NX二次开发CreateDialog函数在UI.hxx文件和WinUser.h中的冲突

NX二次开发CreateDialog函数在UI.hxx文件和WinUser.h中的冲突 在UG二次开发中&#xff0c;若使用MFC库&#xff0c;一旦加上#include<Afx.h>头文件&#xff0c;或者使用<windows.h>头文件下面这句话就报错 theDialog GetPoints::theUI->CreateDialog(theDlxF…

HLO--XLA

HLO: high level optimizer 高级优化器 XLA&#xff1a; XLA(Accelerated Linear Algebra)-加速线性代数&#xff0c;Google推出的高性能机器学习领域编译器&#xff08;编译型推理引擎&#xff09;&#xff0c;它可以在不更改源代码的条件下加速Tensorflow模型 提高TensorFlo…

C++:C++编译过程:看完还不懂C++编译过程来捶我

1&#xff1a;先看图 2&#xff1a;一个C源文件从文本到可执行文件经历的过程&#xff1a; gcc Hello.cpp 预处理阶段&#xff1a;gcc -E hello.c -o hello.i 对源代码文件中包含关系&#xff08;头文件&#xff09;&#xff0c;预编译语句&#xff08;宏定义&#xff09…

h计算机软件指什么,HXX 文件扩展名: 它是什么以及如何打开它?

解决难以打开 HXX 文件的问题 打开 HXX 文件过程中所遇到的常见问题 MacroMates TextMate 消失 尝试打开 HXX 时&#xff0c;你会遇到一条错误消息&#xff0c;例如 “%%os%% 无法打开 HXX 文件”。 如果是这种情况&#xff0c;通常是因为 你的计算机上没有安装 MacroMates Tex…

神器octotree

在Github上查看源代码的体验十分糟糕&#xff0c;尤其是从一个目录跳转到另一个目录的时候&#xff0c;非常麻烦。 直到遇到这款神器&#xff0c;相见恨晚&#xff01;&#xff01; 具体安装及使用步骤参考&#xff1a; https://www.cnblogs.com/12yang-ting/p/7485264.html …

有用的Chrome扩展介绍 - Octotree - GitHub code tree

明细&#xff1a; 安装之后&#xff0c;Github网站左边会自动出现类似Visual Studio Code的代码显示方式&#xff0c;可以通过树形结构方便地浏览代码&#xff0c;无需重复点击文件夹进入。 树形结构里的图标可以使用各种不同的风格显示&#xff1a; 快捷键&#xff1a;上箭头…