在很多的 NLP 问题中,我们最终会把序列编码成一个固定大小的表示,然后将这个编码再解码成另一个序列。例如,我们可能会在文本中进行实体标记,从英文翻译成法语,或将音频转换成文本。在这些领域都出现了大量的工作,并且很多成果都取得了最先进的表现。
在我看来,NLP 与金融数据分析之间的最大不同在于,语言有一定的结构性,虽然这个结构性比较模糊难懂。另一方面,金融市场数据可能是没有任何结构可以学习的。
在这个文章中,我们假设金融市场数据是存在结构性的,当然这个假设可能是不成立的,我们这个文章可能也会直接推翻这个假设。我们按照 NLP 的语义编码模型来类比这个市场结构,如果你觉得这个想法没有意义,那么请阅读下去,我相信你会觉得会有意义的。
词向量
简而言之,我们可以用语言模型来描述所有的单词,并且在坐标图中进行显示,并且利用几何图形来捕捉单词之间的关联性。有一个经典的例子是 “King - man + woman = Queen” ,或者类似别的例子。
单词之间的几何关系
只需将这些单词放在一起,嵌入即可捕获公司与其CEO之间的几何图案。嵌入很酷,因为它们让我们以浓缩的方式表示信息。旧的表示单词的方式是持有一个向量(一个大的数字列表),它与我们知道的单词数量一样长,并且如果那是我们正在查看的当前单词,则在特定位置设置1。这不是一种有效的方法,也没有任何意义。使用嵌入,我们可以用固定数量的维度表示所有单词,比如300似乎多了,50个正好,然后利用它们的更高维度几何关系来理解它们。
下图显示了一个示例。嵌入式训练或多或少地在整个互联网上进行了培训。经过几天的密集计算,每个单词都嵌入在一些高维空间中。这个"空间"有一个几何,像距离这样的概念,所以我们可以问哪些词是紧密相连的。这是最接近青蛙的词。
根据Glove算法(一种字嵌入),Frog这个词的向量的最近邻居。注意它是如何知道你从未听说过的词,并捕捉它们与From的相似之处。
但我们可以嵌入的不仅仅是单词。我们可以做股票市场嵌入。
Market2Vec
我听说的第一个字嵌入算法是word2vec。我希望对股票市场产生同样的效果,不过我会使用不同的算法。我的输入数据是csv,第一列是日期,并且有4 * 1000列对应于1000股的高低开盘收盘价。那是我的输入向量是4000维度,这太大了。所以我要做的第一件事就是将它放入较低维度的空间,比如300。
你的面部表情,当付出额外的努力将4000个维度嵌入300时
如果你觉得把一个 4000 维度的向量压缩到 300 维度是一件很难的事,那么你就大错特错了。其实这很简单,我们只需要乘以一个矩阵,矩阵就相当于一个巨大的 excel 表格,每个单元格中都会有一个数字,并且不存在任何的格式。想象一下,我们有一个 4000 列和 300 行的 excel 表格,我们把这个表格与上面的 4000 维度向量进行相乘,那么我们就可以得到一个 300 维度的向量。这是最基础的线性代数知识,你肯定能明白。
那么,现在的难点就是如何去设置这个巨大的表格矩阵,“深度学习” 就是用在这个矩阵的初始化和更新上面。最终,这个电子表格矩阵将会是一个不错的转移矩阵,可以将我们的 4000 维度向量转换成一个简洁的 300 维度向量。
接下来,我们要做一些比较神奇的事,那就是激活函数。我们要给每一个值加上一个激活函数。将这个激活函数添加到每一个值上面,将每个值的大小归到 0 到 1 之间。那么,为什么这样做可以使得我们的向量更加特别,可以学习和理解更加复杂的事情。
那么接下来我们需要处理的重要的事就是如何去找到这个转移矩阵,使得我们可以损失更少的信息,将高维的股票向量转换成低维的股票向量。我们希望能利用这个向量来挖掘各个股票之间的相关性,也许我们会发现当某个行业下滑时,另一个行业的股票也会下滑。当然,我们可能也会发现一些别的特征,我认为这对我们将来的研究会非常有用。
语言模型
让我们先把股票向量放在一边,来谈谈语言模型。Andrej Karpathy 写了一篇很流行的文章 The Unreasonable effectiveness of Recurrent Neural Networks 。对这篇文章可以简单总结如下:
如果我们学习莎士比亚的作品,然后一个字一个字的进行学习。那么我们可以深度学习来学习一种语言模型。
在这种情况下,语言模型是一个魔术盒。你可以提供一句话的前面几个字符,模型就会告诉你下一个字符是什么。
如果我们把语言模型的预测结果重新输入到语言模型,那么我们模型将永远运行下去。
然后这个模型会产生一大堆看起来像莎士比亚风格的文字。然后,我们也可以将这个思想用在 Linux 源码上面,然后程序来产生代码。或者,我们可以用在几何代数课本上面,让程序来产生内容。
这个魔术盒的实现机制我们会在后续进行介绍,但是让我们先来假想一下,Karpathy 是利用前面的一些字符来预测下一个字符,那么我们是否可以根据之前的市场向量,来预测下一个市场表现、市场向量或者别的东西,而这个预测模型就是这个魔术盒。我们还没有决定我们想要预测的是什么,但是没有关系,因为我们不会将我们的输出反馈到我们的输入中。
走得更远
我想指出,从现在开始我们要开始深入的去分析深度学习。到目前为止,我们只是使用单层网络进行学习,也就是只是使用我们上面设计的按个 4000 * 300 的转移矩阵。接下来,我们会添加更多的层次,来设计一个深层的神经网络来设计这个市场向量,这就是深度学习。
所以,Karpathy 向我们介绍了一些 Linux 例子的输出,下面给出代码:
static void action_new_function(struct s_stat_info *wb){ unsigned long flags; int lel_idx_bit = e->edd, *sys & ~((unsigned long) *FIRST_COMPAT); buf[0] = 0xFFFFFFFF & (bit << 4); min(inc, slist->bytes); printk(KERN_WARNING "Memory allocated %02x/%02x, " "original MLL instead\n"), min(min(multi_run - s->len, max) * num_data_in), frame_pos, sz + first_seg); div_u64_w(val, inb_p); spin_unlock(&disk->queue_lock); mutex_unlock(&s->sock->mutex); mutex_unlock(&func->mutex); return disassemble(info->pending_bh);}请注意,它知道如何打开和关闭括号,并遵守缩进约定; 函数的内容正确缩进,多行printk语句具有内部缩进。这意味着这个神奇的盒子可以理解远程依赖。当它在print语句中缩进时,它知道它在print语句中,并且还记得它在函数中(或者至少是另一个缩进的范围)。那太疯狂了,这就很容易理解,能够捕获并记住长期依赖性的算法非常有用,因为......我们希望在市场中找到长期依赖关系。
神奇的黑匣子
那么这个神奇的魔术盒里面有什么呢?它是一种被称为 LSTM 的循环神经网络(RNN)。RNN 是一种深度学习算法,它擅长的是对序列进行操作(如字符序列)。在每一步,它对会对下一个字符进行预测,并且使用一个矩阵记性表示,就像我们之前看到的那样。因为 RNN 有一些内部的记忆,所以它可以记住一些以前看到的东西。它会使用这个内部记忆来决定下一次输入中应该如何操作。使用该内存记忆,RNN 可以记住它在一定范围内的内容,这就是我们为什么可以对输入文本进行预测处理。
一个基本的RNN
RNN的精美版本称为长期短期记忆(LSTM)。LSTM巧妙地设计了记忆机制,想彻底理解LSTM请看我们的另一篇文章《理解LSTM中的各种阀》
有选择地唤醒原来的记忆;
决定丢掉一些记忆;
决定输出多少记忆。
LSTM
所以,当一个 LSTM 看到一个 “{” ,并且对自己说“这个非常重要,我应该把它记住” 。而当它这样做时,它基本上就记住了这是一个嵌套的范围。一旦看到相应的 “}” ,它就会决定忘记原来的大括号,因此忘记它在一个嵌套的范围内。
我们可以将几个 LSTM 堆叠在一起,这样 LSTM 可以学习到更多的抽象概念。现在,前一个 LSTM 的输出变成了下一个 LSTM 的输入,每个 LSTM 会学习到更加抽象的数据。在上面的例子中,第一层的 LSTM 可能会学习由空格分割的字符,下一层可能会学习像(static void action_new_function)这样的字符类型,下一层可能会学习函数的概念以及参数等等。虽然 Karpathy 在博客中已经有非常好的说明例子了,但是要清楚的说明每一层的具体任务还是非常难的。
连接Market2Vec和LSTM
你可能会注意到,Karpathy 使用字符作为他模型的输入,而不是词嵌入(技术上是使用 0-1 编码)。但是,Lars Eidnes 在 Auto-Generating Clickbait With Recurrent Neural Network 文章中使用词嵌入来处理。
上图显示了他使用的网络。我们先不考虑 softmax 部分(这部分我们后续介绍),先来看看 LSTM 堆栈和模型的输入部分。我们发现模型的底部输入是一系列的单词向量(记住,一个词向量表示的是一个单词的语义)。Lars 输入一个字向量序列,其中每一个作用如下:
影响第一个 LSTM;
前一个 LSTM 的中间输出作为下一个 LSTM 的输入;
前一个 LSTM 输出的下一个字作为下一个 LSTM 的输入;
虽然我们要做同样的事情,但是可能有一点小小的区别,我们不是把字向量作为输入,而是我们的 Market2Vec ,这个市场向量就是我们之前描述出来的。
回顾一下,对于给定的时间点,MarketVectors 应该包含在这个时间点发生的市场情况的总和。通过 LSTM 的序列化,我们希望能够捕捉到市场上发生的一个长期依赖关系。通过几个 LSTM 的堆栈,我们希望可以得到更高层次的市场行为抽象数据。
股票主角登场
到目前为止,我们还没有谈到算法实际上是如何学习任何东西的,我们只讨论了我们将对数据进行的所有巧妙转换:把一个高维度的数据转换成低维度的数据。在接下来的文章中,我们会来具体讲解如何应用这个算法,但是请记住,正是因为前面的铺垫才使得后面的应用有了价值。
在Karpathy的例子中,LSTM的输出是一个向量,表示某个抽象表示中的下一个字符。在Eidnes的例子中,LSTM的输出是一个向量,表示下一个单词在某个抽象空间中的含义。两种情况下的下一步是将该抽象表示更改为概率向量,该列表表示每个字符或单词可能分别出现的可能性。这是SoftMax功能的工作。一旦我们有了可能性列表,我们就会选择最有可能出现的字符或单词。
当我们处理“市场预测”的问题时,我们需要问自己,我们真正想要预测的是市场的什么情况?我这里有一些自己的想法,大家可以参考一下:
1. 预测1000种股票中的每一支的下一个价格;
2. 在接下来的n分钟内预测一些指数(S&P,VIX等)的变化;
3. 预测未来n分钟内哪些股票将上涨超过x%;
4. 预测在接下来的n分钟内哪些股票将上涨/下跌2倍,而在此期间不会下跌/跌幅超过x%;
5. 预测VIX 在接下来的n分钟内上升/下降2倍,同时不会下降/上升超过x%。
第一和第二个就是回归问题,我们必须预测的是一个实际的数字而不是一个特定事件的概率(比如字符 n 出现或者市场上涨)。这个非常准确,但是不是我想做的事。
第三和第四是两个非常相似的问题,他们都要求预测一个事件(技术术语,就是一个类标签)。这个事件可能是接下来出现字母是 n ,或者接下来10分钟内某只股票是否会上升 5%,而不会下降超过 3%。第三和第四之间的权衡关系是,第三个问题更加常见,因此更容易学习到,而第四个问题更加有价值,它不但对利润有预测,而且对风险也有一定的约束。
第五个问题是我们在这篇文章需要解决的,这个问题跟第三个和第四个问题非常类似,但是它更加容易一些,因为我们有一些机制可以遵循。VIX 指数被称为恐怖指数,它代表了 S&P 500 指数的股票波动。它是通过观察指数中每个股票的隐含波动率得出来的。
为什么要预测VIX
那么我们为什么会去预测 VIX 这个指数呢?原因主要如下:
这只是一个数字,而不是 1000 支股票,这就使得我们在算法设计上会更加简单,计算成本也会降低很多;
这是多个股票的总结,所以跟大多数股票是相关的;
它不是单纯的对我们的输入数据进行线性组合。隐含的波动率是从一个非常复杂的非线性公式中计算出来的,而 VIX 是基于这个波动率再进行推导得出来的。如果我们可以进行预测,那么这将是一件非常酷的事。
这个是直接可以用来指导交易的额,如果我们真的可以设计出一个有价值的网络,那么我们就可以直接在线上使用它。
返回我们的LSTM和SoftMax输出
在未来几分钟内,我们如何使用之前的数据来预测 VIX 的变化呢?对于我们数据集中的每一个点,我会在 5 分钟后再次看到该数据点的 VIX 变化。如果在那段时间内上升了超过 1%,但是没有超过 0.5%。那么,我们的模型将输出 1,否则就是输出 0。然后我们会得到如下一系列的标签:
0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0 ....我们想利用之前压缩的市场向量,然后输入到 LSTM 模型中得出最终的概率结果,从技术上来分析,因为我们最终只要输出一个标签,我们也可以使用 sigmoid 函数,但是如果我们做二分类结果,还是建议使用 softmax 函数。
所以,在我们深入分析这个算法应用之前,让我们先来回顾一下我们已经学习了哪些内容:
我们以 1000 支股票的价格作为输入数据;
数据序列中的每一个时间点都是市场的一个快照反馈。我们使用一个压缩网络,将输入的 4000 维度压缩到 300 维度;
现在我们有一系列的股票市场向量,我们把这些股票向量输入堆栈 LSTM 中,然后按照每个时间步骤来进行学习。LSTM 会记住一些市场之前的有效信息,这些信息会影响后续的市场反馈;
我们将第一层 LSTM 的输出传递到另外的 LSTM 结构。这些结构会记住一些更高层次的抽象信息;
最后,我们会根据堆栈 LSTM 的最后输出,利用 softmax 函数来得到VIX 在接下来5分钟内上涨 1%,而不是下降 0.5%的具体股票;
这件事是如何学习的?
现在是最有趣的部分。我们现在所做的一切都可以被称为是一个前向的过程。当我们训练算法时,我们也会去做以上的那些步骤,然后部署到生产环境中使用它。现在我们需要讨论的是一个反馈的过程,这个反馈是我们需要在算法中进行学习的过程。
在训练的过程中,我们不仅准备了数年的历史训练数据,还手动准备了一系列的预测目标,0 和 1 都是我们对历史数据进行打的标签。
为了学习,我们需要将市场数据输入我们的神经网络,并且将网络的输出结果和我们的标签数据进行对比,最后得到一个损失值,这个对比函数就是一个损失函数。在我们的例子中这个对比比较简单,我们可以将我们的损失函数设计如下:
ERROR =(∑((预先计算) - (预测概率)))^(1/2)实际发生的和我们预测的差异的平方和的平方根。
这就是一个损失函数。也就是说,我们可以去计算出深度学习模型的输出值与准确值之间的误差有多大。根据这些误差,我们可以利用一些更新函数来更新一整个网络的权重,从而得到一个比较好的模型。
该更新过程会一直更新到模型的开始,所以模型会不断的调整我们的 MarketVectors 向量,以便我们的 MarketVectors 可以表示更多的信息。
LSTM 模型可以选择去记住哪些内容和忘记哪些内容,以便模型可以分析那些与我们任务最相关的量。
LSTM 模型还可以学习数据的更加抽象表示,以便模型学习数据更多的特征。
这一点是非常让我吃惊的,因为深度学习可以学习那么多负责和抽象的东西。我们从前都没有接触过这种模型。
其他想法
对于这个项目我还有一些更加深入的想法,一些我可能还会尝试的想法,并且我认为这些想法对实际项目时有用的。
市场流动性和资金的有效利用
一般来说,特定市场的流动性越高资金的利用效率越高。我认为这是一个鸡与蛋之前的循环,而市场变得更加的流动,它能够吸收更多的资本交易,并且资本收到的损害最小。随着市场变得更加流动,更多的资本可以在市场中使用,你会发现更多复杂的交易玩家会进入市场。
一个快速的推论是,在一个比较不流动的市场中,竞争并不是那么复杂,所以这样的机制可能会带来机会,我会在这样的市场尝试交易。
股票市场的新应用
这些算法的知识和架构对计算机领域是比较陈旧的,但是在股票金融领域的应用是一个全新的应用。我们假设一些顶级玩家已经在使用这些技术进行套利,并且可能已经很长一段时间了。但是正如我前面提到的,他们可能是在一个流动性很大的市场进行套利工作,他们需要很大的市场资金规模,这样才能去平摊他们的运营成本。我认为,下一次的市场应用会在那些流动性比较小的市场,这些市场还没有被开发完全,存在很大的套利空间。
多个时间帧
虽然我在上面提到的是输入一个单通道的数据流,但我认为一个更加有效的训练方法是在多个时间通道上面对市场数据进行训练。也就是说,我目前采用的是 30 秒采样一次,我希望网络可以解决几个小时的数据依赖关系。
我不知道这个想法是否有意义,但是我认为如果我们可以将计算成本降低到一定程度,那么我们可以把多个时间点进行融合训练。这个融合模型的训练我还在思考中,目前有点困难。
MarketVectors
当我们在自然语言处理中,使用的词向量模型都是在一个预训练模型之上进行微调的。但是在我们的情况下,没有一个预训练好的市场向量可以使用,也没有一个明确的算法去进行训练。
我原来的想法是使用一个自动编码器来进行训练,就好像这篇论文,但是端到端的训练好像看起来更加酷。
更重要的考虑是,端到端的序列模型在机器翻译领域已经比较成熟了,也就是说我们可以把一些文本编码成一个向量,并且进行解码。在这种观点下,我所描述的整个架构本质上就是一个编码器,但是我还没有真正的设计出一个解码器。
但是,对于网络的第一层,我想设计一个特殊层,即我们需要把输入的 4000 维度向量降维到一个 300 维度的向量。通过这些低维度的向量,我们需要去找到各个股票之间的一些关联度。
另一个替代的方向是对每个 LSTM 输入一个数据,然后编码成一个输出向量。但我认为这个可能是无效的,因为各个数据模型之间的相关度会下降很多,并且这种方法会需要 10 倍的计算资源,比较浪费。但是从另一方面来说,这种架构可以多个 GPU 进行训练,可以提高一点速度。
CNN
最近,字符级的机器翻译方面出现了很多的论文。这篇论文带给了我很多的启发,因为这篇文章试图采用 CNN 来解决长距离的依赖关系,而不是 RNN 。我还没有深入的去阅读这篇论文,但是我们可以假想一下,我们把每个股票当做一个通道(类似于 RGB图像的三个通道),然后把每个通道输入卷积模型中进行卷积操作,从而来捕捉市场的长期依赖信息。这种方法跟他们从字符级别上进行语义编码的方式是相同的。
上一篇:买房,还是买股票?