一、前言
多因子选股策略是一种应用十分广泛的选股策略,其基本思构想就是找到某些和收益率最相关的指标,找出股票收益率与各种指标之间的“关系”,借此“关系”建立股票组合,并期望该组合可以跑赢指数。
多因子回归是多因子选股策略最常用的方法,它用过去的股票的收益率对多因子进行回归,得到一个回归方程,然后把当下的因子数值代入回归方程得到未来股票的预期收益,最后以此为依据进行选股。
机器学习和多因子选股策略的结合,从实践的角度来看,机器学习所做的工作是在现有因子的数据集上建立模型,对股票收益率进行拟合,然后对模型进行评估和优化。
用机器学习做模型预测有一套基本流程:数据获取、数据预处理、模型训练、模型评估和模型预测。接下来本文沿着这套流程用python中的机器学习库sklearn完成一个简单的多因子回归的选股模型。
二、获取数据
机器学习所需数据主要有两个来源:网络爬虫和专业数据库,这里我们使用的数据为A股股票的历史数据,因此数据来源取自wind数据库。
原始数据包含了所有A股股票——以2018/06/30当日的股票为准,时间段选取1998/04/30至2018/06/30,每个月度每只股票取数十个不同的指标,以月末最后一日的数据作为截面数据保存。
由于数据过于冗杂,我们先对数据进行结构化降维,使用csv格式进行存储,每个月度的截面数据保存在一个csv文件中,文件名有序排列。每个csv文件中包含了该月份最后一日所有股票的部分基本信息、下一个月的收益率、和数十个指标因子的值。
三、数据预处理
首先是特征提取,特征提取这一步主要基于人的经验,对于指导股票投资的模型,则选取作出投资决策中经常考虑的一些数据指标。这里,我们选取以下几类指标进行考量:
估值指标:营业收入、净利润、净资产等
成长指标:营收同比增速、净利润同比增速等
财务指标:毛利率、资产周转率、经营性现金流等
杠杆指标:流动比率、现金比率等
流动性指标:N日日均换手率等
其他绝对指标:市值、股价、股东数、beta 等
情绪指标:wind评级、wind一直目标价等
技术指标:MACD、RSI、动量反转……
特征因子的选取对于模型的拟合结果和预测准确度有很大影响,因此特征因子要精挑细选。以上指标都是市场中各类投资者经常考虑的指标的总结,有效性有待商议,现在先从wind中提取出这些指标。
接下来是数据清洗,数据清洗需要做的是缺失值填充、数据标准化、数据降维等等。
由于从wind中所取得的指标有限,而且原始数据因为未上市、停牌、涨跌停等多种原因产生了很多空值、不可使用的数据,这部分因子的数值需要进行缺失值填充;部分指标属于绝对值类指标,不同公司间差异性较大,类似营业收入、净利润、现金流等因子,换做与其市值的比值后横向可比性更强;其他有些数据也因为各种原因存在着去极值、标准化和降维等需要。
下表为自1998年4月起的第244个月的csv文件部分截图,文件的列结构如下:
第1列:当前文件所属月份
第2列:wind股票代码
第3列:交易状态,1为正常交易,0为ST/停牌/次新股
第4列:下一个月超额收益率(相对于沪深300)
5列后:已完成数据预处理的特征因子70个
四、模型训练
1 、模块导入
该模型依赖的模块主要有:numpy,pandas和sklearn。
其中numpy是Python做数据处理常用的扩充程序库,主要用于支持高维数组与矩阵运算,同时针对数组运算提供大量的数学函数库;而pandas是基于numpy的高效数据模型库,由于为面板数据分析和时间序列分析提供了很好的支持,因此常备用作金融数据分析的基础工具包。
sklearn全称是scikit-learn,是谷歌开发的一个机器学习框架,是python重要的机器学习库。sklearn支持包括分类、回归、降维和聚类四大机器学习算法,还包含了特征提取、数据处理和模型评估三大模块。sklearn建立在NumPy和matplotlib库的基础上,利用这几大模块的优势,大大提高机器学习的效率,是机器学习领域最知名的python模块之一。
sklearn支持的机器学习方式:
1.Classification 监督学习-分类(预测未来变化方向)
2.Regression 监督学习-回归(预测未来变化幅度)
3.Clustering 非监督学习-聚类(选取相近的样本)
4.Dimensionality reduction 非监督学习-降维(选取有代表性的因子)
5.Model Selection 模型选择(选择更好的模型)
6.Preprocessing 数据预处理(如何选择特征,做预处理)
2 、参数设置
模型中所有参数都在这一部分进行定义,其中包含样本内数据集、样本外数据集、正反数据比例、验证集比例、随机数种子点、置信度、特征因子序列等等。具体参数如下:
1.month_in_sample = range(1,141+1) # 样本内数据月份范围
2.month_test = range(142,243+1) # 样本外数据月份范围
3.percent_select = [0.2,0.2] # 正例和反例数据的比例
4.percent_cv = 0.1 # 验证集比例
5.seed = 45 # 随机数种子点
6.logi_C = 0.0005 # 置信度
7.n_stock = 3625 # 现今股票数
8.n_stock_select = 10 # 选出股票数
9.parameters = ('EP':'bias') # 模型所使用的特征因子
这里的参数后期都可以根据不同需要进行调整,以获得更有效的模型。
3 、数据处理
对于数据,使用经典的内外划分方式,将整体数据集244个月的A股月数据分为两部分:
样本内数据,通过设定month_in_sample参数的值,选取1998年4月~2009年12月的数据,用于模型训练
样本外数据,通过设定month_test参数的值,选取2010年1月~2018年6月的数据,用于模型预测
对于样本内的数据,先进行数据的进一步清洗和整理,循环读取每一期的csv表:
1.根据parameters参数,从csv文件中读取相关因子数据,并保存在临时表
2.删除单元格有空值的股票
3.加入标签项,根据次月超额收益对个股打标签
4.根据percent_select的参数留下收益最高和最低的部分股票
5.将收益最好的股票打标签1,收益最差的股票打标签0
最终,得到的数据集data_in_sample为处理好的样本内数据集,可以用来进行模型训练,该数据集的部分截图展示如下。
4 、模型训练
模型训练前,先将样本内数据集再一次进行拆分,拆分为训练集和验证集,验证集的比例根据percent_cv参数确定,集合的拆分由train_test_split完成,因此具有随机性。
根据拆分出的训练集,对模型进行训练,模型训练使用sklearn中的函数model.fit。这里可用的模型很多,包括线性回归模型、支持向量机模型、SGD模型等等。这里以线性回归模型为例,在置信度为logi_C的水平下进行线性回归,经过机器学习得到拟合后的model。
五、模型评估
用此model对样本内数据集的训练集和验证集进行预测,sklearn中有专门的函数predict和decision_function对模型进行预测。
这样可以得到预测的涨跌标签值以及涨跌的概率,通过将预测数据和真实数据进行比较,metrics中有专门的函数accuracy_score可以进行矩阵直接的比较,最终得到两矩阵的相似性,可以理解为模型预测的准确率。
因此,若参数按上文中进行设置,可以得到的模型训练集的预测准确率为59%,验证集的预测准确度为58%,系统输出结果如下:
training set: accuracy = 0.59
cv set: accuracy = 0.58
六、策略构建
使用该model构建多因子选股策略:对于所有A股股票,以月度为频率,取parameters中定义的特征因子进行拟合,给出预测涨跌的概率,对预测涨跌概率进行排序,选取前n_stock_select个股票构建等权组合,进行买入。
七、策略预测
有了通过对训练集机器学习后确定的model,就可以对样本外的数据进行回测。在回测之前同样需要对样本外数据进行清洗和整理,然后按月循环带入model,给出每个月每只个股的涨跌预测以及涨跌概率的预测,并根据策略构建投资组合进行轮动。
回测部分需要有以下输出内容:
1.将预测涨跌概率的矩阵输出到PredResult.csv,
2.将股票组合的月收益率序列记录到return_test表,该表的部分展示如下图,
3.计算出投资组合在样本外预测月份的净值序列,输出到Value.csv。
八、策略评价
根据回测中得到的组合月度超额收益率return_test表,以及组合净值Value.csv,可以计算出该策略的超额年化收益、波动率和信息比率。本策略中,按上文设定的参数给出的投资组合各项指标,输出如下:
annualized excess return = 0.28
annualized excess volatility = 0.19
information ratio = 1.44
该策略组合的平均超额年化收益率为28%,平均年化收益波动率为0.19,信息比率IR为1.44,每承担1单位波动风险获得1.44的超额收益。
最后,绘制出回测时间段内,2010年1月~2018年6月,该选股策略下的投资组合净值曲线,输出如:
九、其他改进
1 、因子原因
特征因子的选择对于限行回归模型的有效性有着较大影响,本文的实例中将70个不同层面的特征因子一起放入了sklearn的线性模型中进行拟合,后续可以考虑有选择性的对模型进行带入,或许会有更好的拟合效果。
例如,在原模型的基础上,去掉技术指标类的特征因子,只保留基本面的特征因子,模型的预测能力和回测评价输出如下:
training set: accuracy = 0.57
cv set: accuracy = 0.57
annualized excess return = 0.25
annualized excess volatility = 0.17
information ratio = 1.46
反之,若只使用技术指标类的特征因子,完全不考虑基本面的指标,模型的预测能力和回测评价输出如下:
training set: accuracy = 0.58
cv set: accuracy = 0.57
annualized excess return = 0.10
annualized excess volatility = 0.29
information ratio = 0.33
2 、变量调参
可以根据model拟合后的预测准确率指标进行适当的参数调整,将下述输出指标进行优化。
trainingset: accuracy = 0.59
cv set: accuracy = 0.58
例如,将percent_select参数调整为[0.3,0.3],即选择前30%的股票作为正例,后30%的股票作为反例,对模型进行训练,模型的预测能力和回测评价输出如下:
training set: accuracy = 0.57
cv set: accuracy = 0.57
annualized excess return = 0.27
annualized excess volatility = 0.20
information ratio = 1.33
或者,将n_stock_select参数调整为50,即每一期使用model进行预测时选取前50只股票买入,模型的预测能力不会改变,但是回测评价输出如下:
annualized excess return = 0.24
annualized excess volatility = 0.18
information ratio = 1.34
再或者,将logi_C参数调整为0.005,即对拟合的置信度进行放宽,对模型进行训练,模型的预测能力和回测评价输出如下:
training set: accuracy = 0.59
cv set: accuracy = 0.57
annualized excess return = 0.29
annualized excess volatility = 0.21
information ratio = 1.41
3 、模型改进
线性回归模型虽然简单、对特征因子选取的依赖性较强,但也是可解释性、可控性较强的模型。除此之外,我们也可以引入其他模型,sklearn中包含了很多机器学习模块可供使用:
1.逻辑回归(可解释性更强,训练速度更快):
fromsklearn.linear_model import LogisticRegression
2.随机森林模型:from sklearn import tree
3.支持向量机模型(高维非线性拟合,训练速度慢):
fromsklearn.svm import SVC
4.K近邻算法:from sklearn import neighbors
5.多层神经网络(高频海量数据的机器学习,小题大做):
fromsklearn.neural_network import MLPClassifier
另一方面,模型的训练和检验方式,也有多种选择,除了交叉验证外,还有滚动训练回测、检验曲线等等。都可以作为后期模型改进可以尝试的方向。
来源:西藏信托
拓展阅读:
1.一个量化策略师的自白(好文强烈推荐)
2.学习Python量化有哪些书籍?这里有一份书单送给你
3.学了那么多技术指标为什么还不赚钱?从量化角度告诉你
4.最科学的仓位管理利器-凯利公式,从方法上胜过99%散户
5.网格交易法,一个不容易亏钱的投资策略(附源码)