技术 | 使用AI的最新成果来预测股票市场变动(一)

今天给大家带来的文章是关于如何使用AI的最新成果来预测股票市场变动(一),第二部分将在之后发布。

主要有以下3个推荐理由:

1.使用了AI中许多比较前言的技术;

2.设计的面较广,技术指标、用NLP做基本面分析、PCA等等都有涉及;

3.整个项目系统完整,并且后续会进一步更新改进,尝试各种方法技术。

 

在这篇文章中,我将创建一个完整的程序来预测股价波动。我们将一起取得一些很好的效果。为了达成目的,我们将使用GAN,用LSTM作为生成网络,CNN作为辨别网络。使用LSTM的原因是因为我们尝试预测时间序列数据,为什么我们使用GAN并且以CNN作为辨别网络,后面会有专门的解释。

我们会深入每一步的具体细节,当然,最困难的一部分是GAN,要成功训练一个GAN最棘手的部分就是得到正确的超参数集。为此我们将是使用贝叶斯优化器(连同高斯过程)和强化学习来决定何时以及如何改变GAN的超参数。在构建强化学习时,将使用最新的进展,例如Rainbow 、PPO。

我们将使用到许多种输入数据。除了股票历史交易数据和技术指标,还将使用自然语言处理NLP的最新成果(BERT,基于transformer的双向编码表示器,一种NLP的迁移学习)来做舆情分析;使用Fourier transforms来提取整体趋势方向;使用Stacked autoencoders来识别高级特征;使用Eigen portfolios来查找相关资产;自回归移动平均模型(ARIMA)用于股票函数逼近,和许多别的技术,以便获得股票更多的信息、模式、依赖。正如我们所指,数据越多越好,预测股价变化是一个非常复杂的任务,所以对股票越了解,提升才会越高。

为了搭建所有的神经网络,我们将使用MXNet和他的高级接口-Glluon,并用多个GPU训练他们

1. 介绍:

精准的股市预测是一项复杂的工作,因为特定的一只股票向特定的方向移动是需要许多的事件和前提条件的。所以我们需要尽可能的挖掘出这些前提条件。

我们还需要做出几个重要的假设:

1.市场不是完全随机的

2.历史会重复

3.市场遵循人们理性的行为

4.市场非常完美

我们将尝试预测高盛公司(纽约证券交易所代码:GS)的价格走势。为此,我们将使用2010.1.1~2018.12.31的所有每日收盘价(其中七年用于训练,两年作为测试验证)。我们将互换者使用‘Goldman Sachs’和‘GS’两个术语。

2. 数据
 

需要了解是什么影响着GS的股价涨跌。因此,需要结合尽可能多的信息(从不同的方面和角度描述股票)。我们将使用1582天的每日数据也就是70%的数据来训练不同的算法,并预测之后的680天(测试数据)。然后我们将对预测结果和测试数据进行比较。每种数据(作为特征参考的)在之后的段落中会解释具体细节。从总体上来看,我们将用到:

① Correlated assets相关资产-其他的资产(任何类型,不只是股票,比如商品、外汇、指数、或者固定收益证券)。像高盛这样的大公司显然不会孤立的存在世界上,它会依赖于许多外界因素并相互互动,包括他的竞争对手,客户,全球经济,地缘政治形式,财政和货币政策,融资渠道等等,这些细节稍后将被一一列出。

② 技术指标-许多投资者是跟随技术指标的。我们将使用许多常用的指标作为独立特征。其中有:7日和21日均线,指数均线,动量效应,布林带,MACD。

③ 基本面分析-一个指示股票涨跌的非常重要特征。有两个特征可以用于基本面分析:1.用10-k、10-Q(季报、年报)来分析公司的情况,分析ROE(净资产收益率)和P/E(市盈率)等等(我们不会使用这个)2.新闻-新闻有可能会意味着即将发生的会使得股价涨跌的事件。我们将获取每天有关高盛公司的所有的新闻并提取分析出当天关于高盛公司的所有的舆论是有利的、中立的还是不利的(用0~1来打分)。因为许多投资者会阅读新闻,并据此做出投资决定,所以如果高盛公司今天的新闻非常有利,认为股票将大涨,那么这就是一个比较好的机会。一个关键点是,我们将在之后对每个特征去分析特征的重要性(feature Importance)(即其对GS股价的走势的指示性如何),并决定是否采用它。稍后详解。

为了能够精确的进行舆论预测,我们将涉及到自然语言处理(NLP),我们将使用BERT-谷歌最近发布的针对情绪分类、股票新闻舆情提取的NLP方法。

傅里叶转换(Fourier transforms)-针对每日的收盘价,我们将使用傅里叶转换来生成几个长期和短期的走向,通过这些转换我们将消除许多噪声(随机游走),并创建出实际股票走势的近似值。走势近似值可以帮助LSTM网络获得更精确的预测趋势。

自回归移动平均模型(ARIMA)-这是最流行的用来预测未来时间序列数据的技术之一(在前神经网络年代)。通过使用ARIMA,看看能不能得到一个重要的预测特征。

堆叠自编码器(Stacked autoencoders)-经过几十年的研究,人们已经发现了大部分之前提到的特征值(基本面分析、技术面分析,等等)。但或许还有一些我们没发现特征值。也许还有一些人们无法理解的潜在关联在大量的数据点,事件,资产,图表等等中。通过Stacked autoencoders(一种神经网络)我们可以通过计算机来找到一些新的影响股票走势的特征值。即使我们不能按人类的语言来理解它们,我们也可以将他们运用到GAN中。

对于期权定价的异常检测的深度无监督学习算法:我们将再使用一个特征-对于每天我们会加上高盛股票90天的看涨期权价格。期权价格包含了许多数据。期权合同的价值依赖于股票的未来价值(分析师为了得出最精准的看涨期权价格也会尝试对股价价格进行预测)。通过使用深度无监督学习(SOM自组织映射算法)我们将尝试发现出每天期权价格的异常。异常(比如价格剧烈的变化)可能意味着一个会对LSTM网络学习所有股价规则有帮助的事件。

之后,有了这么多特征,我们还需要执行几个重要的步骤:

1. 对数据的质量进行统计检查。如果我们的数据是有缺陷的,那么无论多么复杂的算法,结果都不会好。检查包括确保数据不会受到异方差性(heteroskedasticity),多重共线性(multicollinearity)或串行相关性(serial correlation)的影响。

2. 构建特征重要性检测(feature importance)。如果一个特征对于我们想要预测的股票没有解释力,那么就没有必要用来训练神经网络。我们将使用XGBoost(eXtreme Gradient Boosting),一种增强树回归算法。

3. 作为我们数据准备的最后一步,我们将通过主成分分析(PCA)创建Eigen portfolios(特征组合)来降低自动编码器(autoencoders)输出的特征的维度。

 

 

注意:这一节的目的是为了展示数据预处理过程和使用不同数据特征值的理由,因此我将只使用其中一部分子集(用来训练的)。

 

 

可视化近九年的股价,用垂直虚线来划分测试集训练集。

 

 

 

2.1 相关资产

正如之前所述,我们将使用其他资产作为特征值,不仅仅是GS的股票。

有哪些资产会影响到GS股票的走势呢?对公司有更好的了解对于选择合适的相关资产非常重要,比如公司的业务线,竞争格局,依赖关系,供应商和客户类型等。
 

1. 首先是和GS类似的公司,我们将会把JPMorgan Chase和Morgan Stanley,等公司加入数据集

2. 作为投资银行,高盛公司的发展依赖全球经济。经济不景气或者波动意味着没有并购M&As或者募股IPOs行为,并且可能限制自营收益。这就是为什么我们会包括全球经济指数。另外,我们还将包含LIBOR(以美元和英镑计价)利率,因为分析师需要考虑设定的这些利率和FI证券导致的经济冲击。

3. 每日波动率指数(Daily volatility index)-也是由于之前所述的原因。

4. 综合指数 - 如纳斯达克和纽约证券交易所(来自美国),FTSE100(英国),日经225(日本),恒生和BSE Sensex(亚太指数)指数

5. 货币-全球贸易经常受到货币变动的影响,因此使用一篮子货币(如美元兑日元,英镑兑美元等)作为特征。

总的来说,我们在数据集中有72个其他资产-每个资产的每日价格.

2.2 技术指标

前面已经解释了什么是技术指标以及我们为什么使用他们,所以直接跳到代码实现吧。我们将只为GS创建技术指标。
 

 

对于每个的交易日一共有12个技术指标,可视化这些指标最后400天的数据。


 


 

2.3 基本面分析

 

对于基本面分析,我们将对GS每天的新闻进行舆情分析。最后用sigmoid函数来得到一个0到1之间的结果。结果接近0表示为负面新闻报道,接近1表示正面新闻报道。对于每一天,我们将创建日平均分,并将其作为一个特征加入。

2.3.1.BERT

为了对新闻的正负面进行分类,我们将使用一种预先训练语言表示(pre-trained language representation)-BERT。

MXNet/Gluon中已经提供了预训练BERT模型。我们只需要实例化他们,并加上两个全连接层,通过softmax函数得到0~1之间的分数
 

 

这里不具体介绍BERT和NLP的细节,但如果有兴趣,请告诉我,我将专门介绍一下BERT,因为其在语言处理方面非常有用。
 

2.4. 对趋势分析进行傅里叶变换

傅里叶变换Fourier transforms通过一个函数并创建一系列有不同振幅和帧的正弦波。然后将正弦波结合在一起去接近原始的函数。数学上,傅里叶转换公式如下:

通过傅里叶变化可以提取GS股票的整体和局部趋势,并且降低一部分噪声。来看看它是如何工作的吧。
 


 

如图所示,傅里叶转换(Fourier transform)中使用的组成成分越多,就越接近真实股价的函数(用100个组成成分就几乎和原始函数一模一样了,红线和紫线已经重叠)。我们打算通过傅里叶变换(Fourier transform)获取长期和短期趋势,所以我们将分别使用3、6、9个组成成分。可以把使用3个组成成分的傅里叶转换(Fourier transform)看成是长期趋势。

另一种降噪技术称为小波(wavelets),两者结果差不多,所以只使用傅里叶变换(Fourier transform)。

 

 

2.5 将自回归移动平均作为一个特征

ARIMA是一种用来预测时序数据的技术。我们将展示如何使用它,尽管其不会作为最终预测值,我们将其作为一种用来降噪的技术并通过它提取一些新的特征和规则模式。

 


 

通过图5可以看到,ARIMA给出了非常接近真实股价的结果。我们将使用ARIMA的预测价格作为LSTM网络的一个输入特征,因为我们想捕获到尽可能多的GS公司股票的特征和规则模式。我们使用测试集得到10.151的均方差,考虑到我们有如此多的测试数据,这个结果还不算坏,但我们仍然只将其作为LSTM的一个输入。

 

2.6 统计检查

 

确保高质量的数据对于我们的模型非常重要。为了确保数据合适,我们将进行几个简单的检查来确保我们获取和观察的结果是真实的,而不是由分布带有基本错误的底层数据获得的。
 

2.6.1  异方差性、多重共线性、串行相关性

 

条件异方差性(Conditional Heteroskedasticity):当误差项依赖于数据时会发生,比如误差项随着数据点一起增长。
多重共线性(Multicollinearity):当误差项(也称残差)相互依赖时发生

串行相关性(Serial correlation):一个特征可以由其他特征得到,完全依赖于其他特征。

因为这里比较简单就不展示代码了,我们主要还是关注深度学习部分,不过数据还是很有决定性的。

 

2.7 特征设计


 

加入了所有类型的数据后,对于2265个交易日,我们总共有112个特征值。1585个交易日作为训练数据。我们还将获得更多特征值通过自编码器

 

2.7.1. 特征重要性

有了如此多的特征值,我们需要考虑他们是否全都对于GS的股票的涨跌有指示性。比如:在数据集中我们包含了用美元计价的LIBOR率,因为我们认为LIBOR的变化可能意味着经济上的变化,并且有可能会影响GS股票的变化。但是我们不用自己去测试。目前已经有许多方法能够测试出特征的重要性,我们将使用到的就是XGBoost,因为他在分类和回归问题上都给出了最好的结果。

因为特征数据集十分的大,为了在这里展示,我们只使用技术指标。通过真实的特征重要性检测后,所有被选择的特征都会被证明有一定的重要性,所以在训练GAN时都不会被排除在外。


 

将训练损失和验证损失画出来,观察训练过程并检查是否有过拟合问题。

对于那些有股票交易经验的人来说,MA7,MACD,BB是重要的特征毫不惊讶。

我将同样的方法运用到整个数据集上-只不过训练过程更长,结果理解起来更复杂。


 

2.8 通过堆叠自编码器(Stacked Autoencoders)获得高级特征值

 

在我们开始自编码器之前,先研究一下一个可供选择的激励函数。

 

2.8.1 激励函数-GELU(Gaussian Error)
GELU-高斯误差线性单元是最近提出的-链接。在论文中,作者展示了几个在神经网络中用GELU比用ReLu好的实例。GELU也被用在我们之前新闻舆情分析的BERT中。

我们将在自编码器中使用GELU。

注意:下面展示了GELU的数学原理。因为GELU没有被作为激活函数来实现,所以我不得不在MXNet中自己编写。如果你按着代码将act_type='relu' 改为act_type='gelu' ,是不会工作的,除非你更改了MXNet中的实现。并为了访问GELU的MXNet实现,提交一个pull request。
 


 

可视化GELU、ReLU、LeakyReLU(主要用于GAN,我们也会使用到)


 

注意:之后,我将尝试用U-Net(链接)来实现,尝试通过卷积层提取更多关于股票的涨跌规则模式的特征。目前只用一个由全连接层构成的自动编码器。

现在回到自编码器,如下面所描述的(这个图只是原理图,并不是实际的层数和单元数。)

注意: 在之后的版本中我将尝试移除解码器的最后一层。通常,自编码器中编码器个数等于解码器个数。然而我们想要更高阶的特征值,所以我们可以跳过解码器的最后一层。在训练期间,我们将构建相同层数的编码器和解码器。但在得到输出时,我们使用最后一层旁边的一层,因为它包含了更高阶的特征值。


 

编码器和解码器都有三层,每层400个神经单元。


 

我们通过自编码器得到了112个特征值。因为我们只想要高级特征值,我们将对这112个特征使用主成分分析(PCA)得到一个特征组合(Eigen portfolio)。这会减少数据的维度。特征组合的描述能力和原始的112个特征值是一样的。

注意:这是纯实验性质的,不能百分百保证逻辑成立。因为AI和深度学习是一门艺术并且需要实验。
 

2.8.2 用主成分分析进行特征组合


 

为了解释80%的方差我们需要84个特征值。这个数量依然很多。所以目前我们将不包含自编码器得到的特征值。我将创建一个可得到中间层输出并且能与其他全连接层连接起来的自编码器架构。这样,我们将:

获得更高级的特征;

得到更少更有意义的特征值。

 

2.9. 用于期权定价的异常检测的深度无监督学习
 

后续进行解释