【手把手教你】使用Logistic回归、LDA和QDA模型预测指数涨跌
1
引言
机器学习(Machine Learning)是人工智能(AI)的重要组成部分,目前已广泛应用于数据挖掘、自然语言处理、信用卡欺诈检测、证券市场分析等领域。量化投资作为机器学习在投资领域内最典型的应用之一,已经越来越广泛的出现在我们的视野中。
机器学习可简单理解为利用统计模型或算法拟合样本数据并进行预测,其模型算法根据学习任务可以分为分类、回归和聚类。分类方法是对离散型随机变量建模或预测的监督学习方法。分类是按照某种标准给对象贴标签,再根据标签来区分归类。而所谓的学习,其本质就是找到特征与标签间的关系(mapping 即映射)。换句话说,分类预测模型是一个从输入特征到离散的输出标签之间的映射函数。分类方法常用的有朴素贝叶斯、分类树、支持向量机、KNN、集成学习(包括随机森林)和深度学习等。
股票指数涨跌的预测本质上是一个分类问题。机器算法有很多种,没有最好的模型,只有更适合解决当前问题的算法。当然,本文的目的不是寻找最优的算法,而是机器学习在分析预测的应用。基于此,本文以Logistic 回归(LR)、线性判别法(LDA)、 二次判别分析(QDA)模型为例,对上证综指的涨跌进行预测。后续推文将会应用其他可能更有效的算法,包括SVM、集成学习和深度学习等。
2
算法基本原理
逻辑回归(LR)
逻辑回归(Logistic Regression,LR)是广义线性回归分析模型之一,其本质属于分类问题,因此主要用于被解释变量为分类(离散,如0,1)变量的情形。在分类问题上,逻辑回归要优于线性回归,因为线性回归在拟合被解释变量为离散时会出现负概率的情况,会导致错误的样本分类。而逻辑回归采用对数函数将预测范围压缩到0与1之间,从而提升预测准确率。
假设L1,L2,…Ln为预测因子,LR模型使用对数公式对上涨(U)的条件概率建立以下模型:
一般使用最大似然法来拟合上述模型。关于逻辑回归的详细推导此处不再展开,想进一步了解的可以找本计量经济学入门教材学习(如伍德里奇的《计量经济学导论》)。机器学习库scikit-learn提供了估计模型的“黑盒子”。
线性判别法(LDA)
线性判别分析,全称Linear Discriminant Analysis (LDA)与LR的区别在于,LR使用对数函数将P(Y=U|L1,L2,...,Ln)建模为给定预测变量Li的响应Y的条件分布;在LDA中,给定Y,分别对Li变量的分布进行建模,并通过贝叶斯定理获得P(Y=U|L1,L2,...,Ln)。
本质上,LDA是通过假设预测变量来自多元高斯分布得出的。在计算出该分布的参数的估计值之后,可以将这些参数输入贝叶斯定理中,以便对观测值属于哪个类别做出预测。LDA假定所有类别共享相同的协方差矩阵。由于scikit-learn提供了拟合和预测方法,所以不用太担心对预测所需的分布或后验概率的公式不了解。
二次判别分析(QDA)
二次判别分析,英文全称是Quadratic Discriminant Analysis (QDA),与LDA密切相关。二者的区别在于,QDA的每个类别都可以拥有自己的协方差矩阵。当决策边界为非线性时,QDA通常会表现更好。LDA通常在训练观察次数较少时(即需要减少方差时)表现更好。另一方面,当训练集较大时(即,差异较小,则QDA表现良好)。一个或另一个的使用最终归结为偏差方差的权衡。与LR和LDA一样,scikit-learn提供了QDA的实现函数,因此我们只需要提供训练/测试数据即可进行参数估计和预测。
3
预测步骤
预测主要分为三个步骤:
第一,根据上证综指指数收益率的正负划分为上涨(1)和下跌(-1)两种类型,作为被解释变量。
第二,寻找合适预测因子。预测因子的选择,与预测方法的选择一样重要,对预测性能起到决定性作用。预测股市指数回报时,有很多潜在因素可供选择,并且有可用的统计检验可以证明每个因子的预测能力。但是本文的目的是为了展示预测的过程而非结果,因此在因子选择上不会作过多的分析。考虑到全球资本市场联系越来越紧密,本文使用全球几大主要指数(如道琼斯、日经225、德国DAX指数等)以及上证综指自身的滞后值作为预测因子。
第三,估计模型并对模型的预测性能进行评价。衡量预测准确率的方法有很多,包括均方差(Mean-Squared Error,MSE)、平均绝对离差(Mean Absolute Deviation,MAD)和均方根误差(Root-Mean-Squared Error,RMSE)等。本文关注的是预测准确次数的百分比,并进一步使用混淆矩阵和ROC曲线评价预测性能。
4
Python实现代码
#先引入后面可能用到的包(package)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
%matplotlib inline #正常显示画图时出现的中文和负号
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
获取数据
import datetime
import yfinance as yf
def get_data(stocks,start_date,end_date):'''stocks为股票代码和简称字典'''data=pd.DataFrame()for code,name in stocks.items():dd = yf.Ticker(code)data[name]=dd.history(start=start_date,end=end_date)['Close']data=data.iloc[2:,:].fillna(method='ffill')return data
StockIndexs = {'000001.SS':'上证综指','^DJI':'道琼斯','^IXIC':'纳斯达克','^N225':'日经225','^HSI' :'香港恒生','^FCHI':'法国CAC40', '^GDAXI':'德国DAX'}
#获取数据
start_date='2008-01-01'
end_date='2019-10-31'
data=get_data(StockIndexs ,start_date,end_date)
data.head()
#累计收益率
(data/data.iloc[0]).plot(figsize=(14,6))
plt.title('全球主要指数累计净值\n (2008-2019)',size=15)
plt.show()
#收益率相关性
ret=data.apply(lambda x : (x/x.shift(1)-1)*100).dropna()
sns.clustermap(ret.corr())
plt.title('全球主要指数相关性',size=15)
plt.show()
上图清晰地显示出,自金融危机(2008)以来,全球股价指数中,美国纳斯达克遥遥领先,累计涨幅接近四倍,而A股则不忍直视,十年净值从1跌至0.5附近,与中国过去十年经济的快速发展形成强烈反差。不过,换一种角度看,当前的价值洼地是不是意味着未来上涨的潜力更大呢?尤其是新一轮技术革命的兴起,拭目以待。另外,再来看一下全球各大指数收益率的相关性,从图中可以看出,道琼斯和纳斯达克相关系数、法国CAC40和德国DAX指数相关系数均超过0.9,而香港恒生指数、上证综指和日经225相关系数也比较高,为了减小预测因子之间由于高度相关性带来的偏差,本文只选择上证综指滞后1、2期、道琼斯、德国DAX和日经225指数的滞后一期值作为预测因子。
def get_variables(ret):
'''ret为上述指数收益率数据'''
df=pd.DataFrame()
df['lag1']=ret['上证综指'].shift(1)
df['lag2']=ret['上证综指'].shift(2)
df['DJ']=ret['道琼斯'].shift(1)
df['DA']=ret['德国DAX'].shift(1)
df['RJ']=ret['日经225'].shift(1)
#上涨用1表示,下跌(含0)为-1
df['direction']=np.where(ret['上证综指'].values>0,1.0,-1.0)
df=df.dropna()
return df
#引入机器学习库
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis as QDA
from sklearn.metrics import accuracy_score,classification_report,confusion_matrix,roc_curve
def fit_model(name, model, X_train, y_train, X_test, pred):"""使用LR, LDA 、QDA对数据进行模型拟合"""# Fit and predict the model on the training, and then test, datamodel.fit(X_train, y_train)pred[name] = model.predict(X_test)# 预测准确率score=accuracy_score(pred['Actual'], pred[name])print("%s模型: %.3f" % (name, score))
if __name__ == "__main__":#获取数据variables = get_variables(ret).loc[:'2017']# 涨跌方向为响应变量, 其余变量为自变量X = variables.iloc[:,:-1]y = variables.iloc[:,-1]# 把原始数据的40%作为测试数据,其余为训练数据#X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.4)#以2017年以前数据为训练集,2017年数据为测试集start_test = datetime.datetime(2017,1,1)X_train = X[X.index < start_test]X_test = X[X.index >= start_test]y_train = y[y.index < start_test]y_test = y[y.index >= start_test]# 创建预测数据框pred = pd.DataFrame(index=y_test.index)pred["Actual"] = y_test# 分别拟合LR, LDA 和QDA三个模型 print ("预测准确率:")models = [("LR", LogisticRegression(solver='liblinear')), ("LDA", LDA()), ("QDA", QDA())]for m in models:fit_model(m[0], m[1], X_train, y_train, X_test, pred)
预测准确率:
LR模型: 0.557
LDA模型: 0.566
QDA模型: 0.590
从模型的预测准确率来看,并不是很理想,三个模型中使用QDA的效果要好一些(可能因为训练数据集样本较多,而测试集分配较少),准确率也只有0.59,只比投掷硬币好一丁点。下面以QDA模型为例,使用混淆矩阵和ROC曲线对模型的预测性能作进一步评价,混淆矩阵图没有给出,ROC曲线图很直观,此处不过多分析。
model=QDA()
model.fit(X_train, y_train)
# 模型在测试数据集上的预测
pred = model.predict(X_test)
# 构建混淆矩阵
cm = pd.crosstab(y_test,pred)
cm
# 绘制混淆矩阵图
#sns.heatmap(cm, annot = True, cmap = 'GnBu', fmt = 'd')
print('模型的准确率为:\n',accuracy_score(y_test, pred))
print('模型的评估报告:\n',classification_report(y_test, pred))
模型的准确率为:0.59016
模型的评估报告:precision recall f1-score support-1.0 0.60 0.03 0.06 1011.0 0.59 0.99 0.74 143accuracy 0.59 244macro avg 0.59 0.51 0.40 244
weighted avg 0.59 0.59 0.46 244
# 计算正例的预测概率,而非实际的预测值,用于生成ROC曲线的数据
y_score = model.predict_proba(X_test)[:,1]
#fpr表示1-Specificity,tpr表示Sensitivity
fpr,tpr,threshold = roc_curve(y_test, y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)
# 绘制面积图
plt.figure(figsize=(8,6))
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC曲线 (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.title('QDA模型预测指数涨跌的ROC曲线',size=15)
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
plt.show()
5
结语
本文主要以逻辑回归(LR)、线性判别分析(LDR)、二次线性判别分析(QDR)为例,展示了机器学习算法在股价涨跌预测上的应用。模型预测效果不甚理想,并不代表机器学习算法的失效,主要原因可能是没有选择好合适的预测的因子,关于什么样的因子才是预测股指涨跌的最好因素留待读者自己去挖掘(这也是量化研究者孜孜不倦在追求的)。
最后,值得关注的是,人工智能本质上是一种非线性算法,非线性的拟合度一般会比较高,但是策略参数可能不稳健,容易出现过拟合的现象,一般只要神经元足够多,可以逼近任何一个函数。机器学习在消费者行为和诈骗行为的模式识别上成功率较高,主要是因为这些模式具有较长的持续期。然而,要利用这些算法对金融市场进行预测,效果则要大打折扣。主要原因可能是,相对于可以获取的大量相互独立的消费者行为和信用卡数据,我们能够获取的在统计学意义上的相互独立的金融数据的数量非常有限。此外,机器学习、深度学习是黑箱,但策略的改进依靠金融逻辑,最好能知道赚的谁的钱,策略为什么能赚钱。
参考资料:
1. scikit-learn官网:https://scikit-learn.org/stable/
2. Forecasting Financial Time Series - Part I:https://www.quantstart.com/articles/Forecasting-Financial-Time-Series-Part-1
3. 雅虎数据API:https://pypi.org/project/yfinance/
关于Python金融量化
专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取量化投资视频资料、量化金融相关PDF资料、公众号文章Python完整源码、量化投资前沿分析框架,与博主直接交流、结识圈内朋友等。
【手把手教你】使用Logistic回归、LDA和QDA模型预测指数涨跌相关推荐
- 手把手教你使用TensorFlow训练出自己的模型
手把手教你使用TensorFlow训练出自己的模型 一.前言 搭建TensorFlow开发环境一直是初学者头疼的问题,为了帮忙初学者快速使用TensorFlow框架训练出自己的模型,作者开发了一款基于 ...
- R语言用泊松Poisson回归、GAM样条曲线模型预测骑自行车者的数量
全文链接:http://tecdat.cn/?p=18550 我根据泊松Poisson回归.GAM样条曲线模型对一个十字路口的骑自行车者的数量进行预测(点击文末"阅读原文"获取完整 ...
- 逻辑回归模型预测股票涨跌
http://www.cnblogs.com/lafengdatascientist/p/5567038.html 逻辑回归模型预测股票涨跌 逻辑回归是一个分类器,其基本思想可以概括为:对于一个二分类 ...
- 今晚直播 | 谷歌资深工程师手把手教你使用TensorFlow最新API构建学习模型
目前,深度学习的研究和应用大受追捧,各种开源的深度学习框架层出不穷.TensorFlow 作为目前最受欢迎的深度学习框架,已经在 GitHub 上获得了 112194 个 star,受欢迎程序可见一斑 ...
- 【Clemetine】基于二项Logistic回归的电信客户流失预测
一.实验目的及要求 1.掌握Logistic回归分析的基本步骤.原理.软件实现.结果分析: 2.理解多重共线性的概念.原理及岭轨迹的软件实现: 3.了解高维数据分析的应用领域及分析方法. 二.实验仪器 ...
- 机器学习:Logistic回归处理用气象数据预测森林火灾的数据挖掘方法
文章目录 线性模型与回归 最小二乘与参数求解 1.一维数据: 2.多维数据 最大似然估计 Logistic回归 基本介绍 基于Logistic回归和Sigmoid函数的分类 基于最优化方法的最佳回归系 ...
- Logistic回归示例:从疝气病预测病马的死亡率
目录 准备数据:处理数据中的缺失值 测试算法:用Logistic回归进行分类 疝气病是描述马胃肠痛的术语.然而这种病并不一定源自马的肠胃问题,其他问题也可能引发马疝病. 此外,除了部分指标主观和难以测 ...
- 飞桨模型保存_手把手教你用飞桨做词向量模型 SkipGram
飞桨开发者说成员:肥猫.忆臻 在做 NLP 的任务时,一个非常 basic 的操作就是如何编码自然语言中的符号,例如词.短语,甚至词缀.目前流行的方法有大约三种: • 特征工程:这类方法依赖于手工特 ...
- 独家 | 手把手教你用Python的Prophet库进行时间序列预测
作者:Jason Brownlee 翻译:殷之涵 校对:吴振东 本文长度为4800字,建议阅读10+分钟 本文为大家介绍了如何在Python中使用由Facebook开发的Prophet库进行自动化的时 ...
最新文章
- WM_CHAR、WM_KEYDOWN和WM_SYSKEYDOWN消息
- 【转载】VSCode+OpenCV+C++配置
- Jsp(Java Server Pages)简介
- linux内核时间second,闰秒(leap second)和linux/unix时间
- salt 执行命令等待_saltstack异步执行命令
- mysql集群搭建教程-mysql+windows篇
- winscp 自动断开无法连接_winscp教程,winscp教程,看完就学会的winscp教程
- ief12执行一次js才有效_陈列到底多久调一次才有效?
- python实现电脑程序自动化_python基于pywinauto实现PC客户端自动化
- python nose框架_Python测试框架nose的介绍
- pbewithmd5anddes算法 对应.net_常用插值算法详解
- SQL--存储过程+触发器 对比!
- 单调队列(数列中长度不超过k的子序列和的最值)
- 热烈庆贺:一个月,由70名升级为60名!
- 初高级分析师的能力和工具体系,指标雷达图!
- 打印日历程序php,C++实现的一个打印日历程序
- 毕设看的硕博士论文速记
- 软件学报zotero文献格式
- 京东后台模板导入SKU报格式错误
- 第一章 kotlin基础知识