之前的《量化投资的利器:隐马尔可夫模型(三)》讨论了如何在监督式学习的场景下使用隐马尔可夫模型。在监督式学习(针对序列数据)里,搭建模型的训练数据为,其中表示事物的状态,它是能被观察的(训练数据里有这个变量)。但在现实生活中的很多情况下,变量是隐藏的、观测不到的,得到的训练数据里只有,如图1所示。
比如《量化投资的利器:隐马尔可夫模型(一)》中的例子:只能观察到小安每天的活动,并不知道每天的天气情况;又比如在股票市场,我们只能看到股票价格、成交量等信息,但无从知道当前股市的状态(分为牛市、熊市和震荡3种状态),这些场景都是所谓的非监督式学习,下面讲讨论如何在这些场景下使用HMM模型。
注:在Github上可以下载本文中所用到的训练数据和模型代码。
一、股票市场:非监督式学习
对于这种类型的数据,我们希望也能像之前一样,搭建模型预测变量(根据变量)。这是一个很困难的任务,因为这要求模型能像变魔术一样,“无中生有”地变成相应的来。比较经典的逻辑回归、支持向量学习机等判别式模型完全没办法处理这类型数据,但作为生成式模型的隐马尔可夫模型却能很好地完成这个建模任务。事实上,解决这种非监督式学习问题才是隐马尔可夫模型的设计初衷,也是这个模型最常用的使用方法。从文字上来讲,隐马尔可夫这个名字中的隐字就对应着变量不可观测这个事实。
隐马尔可夫模型是如何做到这一点的呢?要回答这个问题,我们先来看看在已知的情况下,隐马尔可夫模型是如何估计模型参数的。正如前面文章讨论的那样,隐马尔可夫模型估计模型参数的原则是最大似然估计法,就是最大化序列数据的联合概率P(X, y),如公式(1)所示,其中表示模型参数,表示训练数据。
在非监督学习中,变量是未知的,但依然可以类似地定义模型的似然函数,如公式(2)所示:
与监督式学习相比(公式(1)),变量从已知的训练数据变成了一类特殊的“模型参数”,但整个似然函数的“架子”(数学公式)还是不变的。针对这类似然函数,依然可以使用最大似然估计法的原则来估计模型参数以及被预测量。但与监督式学习相比,由于新加入了未知量,需要估计的“参数”个数更多了,所以需要用到特殊的估计算法:最大期望算法(Expectation-Maximization Algorithm,EM)。下面就以multinomial HMM为例介绍,如何在非监督式学习场景里使用EM算法估计模型参数。
- 在非监督式学习中,multinomial HMM的模型假设是不变的。因此,只要给定的取值(先不管这里给定的是否正确合理,事实上可以是随机生成的),那么就能像《量化投资的利器:隐马尔可夫模型(三)》中公式(1)那样估算相应的模型参数。
- 反过来,如果有了模型参数(同样地,先不管这些模型参数是否合理),就可以使用《量化投资的利器:隐马尔可夫模型(三)》里讨论的Viterbi算法得到相应的预测值。
数学上可以证明,如果将上面的两步重复交叉使用,就可以最终得到公式(2)的解。这就是EM算法,其中第一步被称为M step,而第二步被称为E step,具体如图2所示。
在讨论完有点艰深晦涩的模型理论后,我们重新回到股票市场,讨论如何使用隐马尔可夫模型对其建模。正如本节开头讨论的,将股票市场分为如下两层。
- 第一层是观察得到的股票市场特征包括5日的收益率、20日收益率、5日成交额增长率以及20日成交额增长率,用变量表示。
- 第二层是观察不到的市场状态,一共包含3种状态,分布是牛市、熊市和震荡(当然也可细分为更多的市场状态,这里仅以3种状态举例),用变量表示。
我们希望能搭建这样一个模型,它能根据一段时间的市场表现(变量),预测当前的市场状态以及未来一段时间的市场状态(变量)。在金融界,针对股票市场有一个很重要的假说,那就是有效市场假说[1]。这个假说的意思是当前的股票价格已经反映了所有历史信息的价值。换句话说,当前的市场状态已经完全包含了历史市场状态,因此在已知当前市场的条件下,未来和过去是相互独立的,即可以认为是一个马尔可夫链,这是使用隐马尔可夫模型的基础。除此之外,进一步假设在市场状态已知的情况下,股票的日收益率和成交量服从正态分布[2]。根据这些假设,搭建隐马尔可夫模型如下。
- 先验分布:正如上面的假设,这个分布是一个正态分布,而且显然在不同的市场环境下,日收益率和交易量对应的协方差矩阵显然是不一样的。因此,假设
- 初始分布:由于变量是离散的,因此假设(这和《量化投资的利器:隐马尔可夫模型(三)》中的multinomial HMM是一致的)。
- 转移矩阵,它表示3种状态间相互转移的可能性,于是假设矩阵的元素为(这和multinomial HMM也是一致的)。
由于这个隐马尔可夫模型是基于正态分布的,因此它在学术上被称为Gaussian HMM。
二、股票市场之代码实现
讨论完理论部分后,现在来看看具体的代码实现。本节将使用Gaussian HMM模型对上证指数的历史数据进行建模。所用数据是从2005-06-01到2017-08-28的上证指数以及相应的每日成交额(事实上,数据里还有每日最高最低价等有用信息,但为了表示简洁,本节的建模例子并不使用这些变量)。
对金融市场比较了解的读者会知道,中国的A股(也就是被人熟知的深市和沪市)开始于1990年12月19日,但A股在最初阶段并不是一个很成熟的金融市场,这主要表现在上市公司内部普遍存在“股权分置”的现象[3]。2005年6月开始的股改是一个标志性的事件,表明中国的A股市场与国际开始接轨,并逐步迈向成熟。这个时间点前后的股票市场是截然不同的两个市场,因此只使用股改开始后的数据进行建模。
除了具体价格,股票市场每天的成交额(买卖股票的总金额)也是反映市场状态的一个很重要的指标。通常认为,在牛市里成交额会逐步放大,而在熊市里成交额会极度萎缩。针对A股市场,在使用成交额这个数据时需要特别注意这一点。1990年至今(2017年),中国经历了人类历史上罕见的经济高速发展期。伴随着经济的快速增长,通货膨胀是不可避免的,比如1990年末的货币供应量M2为15 293.4亿,而2016年末的M2为1 550 100亿元,增长了大约100倍。因此,在利用成交额搭建模型时,需要使用通货膨胀率对其做相应的折现处理[4]。在本节的例子中,我们使用的是5日成交额增长率以及20日成交额增长率,这就很巧妙地避开了上述的通货膨胀问题。
虽然scikit-learn并没有实现将要使用的Gaussian HMM模型[5],但有比较成熟的开源方案:hmmlearn。它的安装方法很简单,只需运行“pip install -U --user hmmlearn”即可。
模型的代码实现很简单,如程序清单1(完整代码请参考stock_analysis.py)所示。
第三方库hmmlearn实现了3种用于非监督式学习的HMM模型,分别是Gaussian mixture HMM、multinomial HMM以及Gaussian HMM。本节将使用Gaussian HMM,它的具体实现为GaussianHMM,如第1行所示。
从原始数据中提取4个特征搭建模型,它们分别是5日的收益率(“r_5”)、20日收益率(“r_20”)、5日成交额增长率(“a_5”)以及20日成交额增长率(“a_20”),如第7行代码所示。
GaussianHMM里的参数“n_components”表示内在状态的个数,本例中这个值等于3,如第8行代码所示。
参数“covariance_type”表示先验分布里协方差矩阵的类型(在状态已知的情况下,特征服从正态分布)。这个值等于“full”表示在不同市场状态下协方差矩阵是不同的,而且可以是任意半正定对称矩阵(也就是说并不要求协方差矩阵是对角矩阵)。其他可能的取值为“spherical”(协方差矩阵为单位矩阵)、“diag”(协方差矩阵为对角矩阵)以及“tied”(不同状态下的协方差矩阵是一样的)。
参数“n_iter”则表示EM算法的最大循环次数。GaussianHMM的模型API与scikit-learn非常相似,如第9、10行代码所示,使用fit方法训练模型;使用predict方法对数据做预测。
程序清单1 Gaussian HMM
1 | from hmmlearn.hmm import GaussianHMM
2 |
3 | def getHiddenStatus(data):
4 | """
5 | 使用Gaussian HMM对数据进行建模,并得到预测值
6 | """
7 | cols = ["r_5", "r_20", "a_5", "a_20"]
8 | model = GaussianHMM(n_components=3, covariance_type="full", n_iter=1000)
9 | model.fit(data[cols])
10 | hiddenStatus = model.predict(data[cols])
11 | return hiddenStatus
根据模型的分类结果,将不同的状态的上证指数表示在不同的坐标系里可以得到如图3所示的结果,其中标记1为所有的市场交易数据,而标记2、3、4则是分类结果。图3表示模型的分类结果基本符合预期,比如在标记2中,股市上涨和下跌的比例大致相同,而且都在一个比较窄的区间内变化,因此对应的是震荡这个市场状态。类似地,可以推断出标记3表示的是熊市,而标记4表示的是牛市[6]。
基于上面的模型结果,很容易就能得到较为有效的量化交易策略,比如执行这样的策略就能获得不错的收益:若当天的隐藏状态是牛市(根据模型结果),则买入或继续持有股票,否则卖出股票或保持空仓。
如果实际生产中真的使用这个模型来做交易,你会沮丧地发现实际效果远不如历史数据的测算结果。这是因为隐马尔可夫模型的预测公式如下所示(程序清单1中第10行代码中的predict方法就是这么计算的):
也就是说,在测算历史数据时,预测变量时,就已经知道了后来的实际交易数据。这一点在实际生活中是不可能实现的,因为没有办法预知未来。因此,为了使模型的测算结果更加符合现实,需要循环地调用公式(3)来预测,而不是一次性地得到全部数据的预测结果。
三、广告时间
这篇文章的大部分内容参考自我的新书《精通数据科学:从线性回归到深度学习》。
李国杰院士和韩家炜教授在读过此书后,亲自为其作序,欢迎大家购买。
另外,与之相关的免费视频课程请关注这个链接
-
有效市场假说(efficient-market hypothesis)是金融学里最重要的理论之一。这个理论认为,投资者无法通过建模等技术手段从市场上获取超过平均水平的收益,也就是说对股票市场进行建模是无意义的。 ↩
-
金融学里常常假设市场是一个服从正态分布的随机游走,而且实际数据也大致符合这个假设。另外数学上对正态分布的处理也最为成熟,基于该分布进行建模可行性是最高的,因此传统的量化金融模型大多会使用这一假设。但在实际生活中,市场并不总是服从正态分布的,这会导致传统量化模型在特定条件下表现很差。由于金融市场离钱最近,即使很小的模型偏差也会导致巨大而直接的金钱损失,这就是所谓的“黑天鹅”事件。所以现代量化金融的研究重点是利用非正态的概率分布(non Gaussian distribution)搭建模型。 ↩
-
在股票市场刚成立时,大部分上市公司是国有企业。这些企业大多数有3种类型的股份:国有股、法人股以及普通股。其中只有普通股能在股票市场上交易,于是这3种类型的股份形成了“同股不同权,同股不同利”的局面,也就是所谓的“股权分置”现象。 ↩
-
折现就是利用折现率(可以理解为更广义的通货膨胀率),将现在的货币折算成等价的过去货币。举个简单的例子,假设当前时间距离过去的基准时间点为年,需要折现的金额为,折现率为,则折现后的金额为。 ↩
-
事实上,较早版本的scikit-learn(在0.17之前)是包含隐马尔可夫模型的,但后来因为项目目标的变化,这部分代码被移出了scikit-learn,变成了本节将要使用的hmmlearn。 ↩
-
虽然Gaussian HMM能将数据分类,但与监督式学习有所不同的是,分类结果并没有直接的物理意义。也就是说,模型只能将数据分类,但无法告诉我们每个类别的具体含义。因此需要人为地根据各个类别里的数据特点,给类别赋予含义。 ↩