量化投资的利器:隐马尔可夫模型(四)

版权声明:本文为作者唐亘的原创文章,欢迎转载,但请注明出处。 https://blog.csdn.net/weixin_39844018/article/details/82559349

之前的《量化投资的利器:隐马尔可夫模型(三)》讨论了如何在监督式学习的场景下使用隐马尔可夫模型。在监督式学习(针对序列数据)里,搭建模型的训练数据为 ( X i , y i ) {(X_i, y_i)} ,其中 y i y_i 表示事物的状态,它是能被观察的(训练数据里有这个变量)。但在现实生活中的很多情况下,变量 y i y_i 是隐藏的、观测不到的,得到的训练数据里只有 X i X_i ,如图1所示。

图1

比如《量化投资的利器:隐马尔可夫模型(一)》中的例子:只能观察到小安每天的活动,并不知道每天的天气情况;又比如在股票市场,我们只能看到股票价格、成交量等信息,但无从知道当前股市的状态(分为牛市、熊市和震荡3种状态),这些场景都是所谓的非监督式学习,下面讲讨论如何在这些场景下使用HMM模型。

:在Github上可以下载本文中所用到的训练数据和模型代码。

一、股票市场:非监督式学习

对于这种类型的数据,我们希望也能像之前一样,搭建模型预测变量 y i y_i (根据变量 X i X_i )。这是一个很困难的任务,因为这要求模型能像变魔术一样,“无中生有”地变成相应的 y i y_i 来。比较经典的逻辑回归、支持向量学习机等判别式模型完全没办法处理这类型数据,但作为生成式模型的隐马尔可夫模型却能很好地完成这个建模任务。事实上,解决这种非监督式学习问题才是隐马尔可夫模型的设计初衷,也是这个模型最常用的使用方法。从文字上来讲,隐马尔可夫这个名字中的隐字就对应着变量 y i y_i 不可观测这个事实。

隐马尔可夫模型是如何做到这一点的呢?要回答这个问题,我们先来看看在已知 y i y_i 的情况下,隐马尔可夫模型是如何估计模型参数的。正如前面文章讨论的那样,隐马尔可夫模型估计模型参数的原则是最大似然估计法,就是最大化序列数据的联合概率P(X, y),如公式(1)所示,其中 θ \theta 表示模型参数, ( X , y ) = ( X i , y i ) (X, y) = {(X_i, y_i)} 表示训练数据。

(1) P ( X , y θ ) = P ( y 0 θ ) i P ( y i y i 1 , θ ) j P ( X j y j , θ ) θ ^ = a r g m a x θ P ( X , y θ ) P(X, y | \theta) = P(y_0 | \theta) \prod_i P(y_i | y_{i - 1}, \theta) \prod_j P(X_j | y_j, \theta) \\ \hat{\theta} = argmax_\theta P(X, y | \theta) \tag{1}

在非监督学习中,变量是未知的,但依然可以类似地定义模型的似然函数,如公式(2)所示:

(2) P ( X y , θ ) = P ( y 0 θ ) i P ( y i y i 1 , θ ) j P ( X j y j , θ ) θ ^ , y ^ = a r g m a x θ , y P ( X y , θ ) P(X | y, \theta) = P(y_0 | \theta) \prod_i P(y_i | y_{i - 1}, \theta) \prod_j P(X_j | y_j, \theta) \\ \hat{\theta}, \hat{y} = argmax_{\theta, y} P(X| y, \theta) \tag{2}

与监督式学习相比(公式(1)),变量从已知的训练数据变成了一类特殊的“模型参数”,但整个似然函数的“架子”(数学公式)还是不变的。针对这类似然函数,依然可以使用最大似然估计法的原则来估计模型参数以及被预测量。但与监督式学习相比,由于新加入了未知量,需要估计的“参数”个数更多了,所以需要用到特殊的估计算法:最大期望算法(Expectation-Maximization Algorithm,EM)。下面就以multinomial HMM为例介绍,如何在非监督式学习场景里使用EM算法估计模型参数。

数学上可以证明,如果将上面的两步重复交叉使用,就可以最终得到公式(2)的解。这就是EM算法,其中第一步被称为M step,而第二步被称为E step,具体如图2所示。

图2

在讨论完有点艰深晦涩的模型理论后,我们重新回到股票市场,讨论如何使用隐马尔可夫模型对其建模。正如本节开头讨论的,将股票市场分为如下两层。

  • 第一层是观察得到的股票市场特征包括5日的收益率、20日收益率、5日成交额增长率以及20日成交额增长率,用变量 X i X_i 表示。
  • 第二层是观察不到的市场状态,一共包含3种状态,分布是牛市、熊市和震荡(当然也可细分为更多的市场状态,这里仅以3种状态举例),用变量 y i y_i 表示。

我们希望能搭建这样一个模型,它能根据一段时间的市场表现(变量 X i X_i ),预测当前的市场状态以及未来一段时间的市场状态(变量 y i y_i )。在金融界,针对股票市场有一个很重要的假说,那就是有效市场假说1。这个假说的意思是当前的股票价格已经反映了所有历史信息的价值。换句话说,当前的市场状态已经完全包含了历史市场状态,因此在已知当前市场的条件下,未来和过去是相互独立的,即 y i y_i 可以认为是一个马尔可夫链,这是使用隐马尔可夫模型的基础。除此之外,进一步假设在市场状态已知的情况下,股票的日收益率和成交量服从正态分布2。根据这些假设,搭建隐马尔可夫模型如下。

  • 先验分布 P ( X i y i ) P(X_i | y_i) :正如上面的假设,这个分布是一个正态分布,而且显然在不同的市场环境下,日收益率和交易量对应的协方差矩阵显然是不一样的。因此,假设$X_i | (y_i = l) \sim N(\mu_l, \Sigma_l) $
  • 初始分布 P ( y 0 ) P(y_0) :由于变量是离散的,因此假设 P ( y 0 = l ) = a l P(y_0 = l) = a_l (这和《量化投资的利器:隐马尔可夫模型(三)》中的multinomial HMM是一致的)。
  • 转移矩阵 P ( y i y i 1 ) P(y_i | y_{i - 1}) ,它表示3种状态间相互转移的可能性,于是假设矩阵的元素为 P ( y i = l y i 1 = t ) = b l , t P(y_i = l | y_{i - 1} = t) = b_{l, t} (这和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)所示。

  1. 第三方库hmmlearn实现了3种用于非监督式学习的HMM模型,分别是Gaussian mixture HMM、multinomial HMM以及Gaussian HMM。本节将使用Gaussian HMM,它的具体实现为GaussianHMM,如第1行所示。

  2. 从原始数据中提取4个特征搭建模型,它们分别是5日的收益率(“r_5”)、20日收益率(“r_20”)、5日成交额增长率(“a_5”)以及20日成交额增长率(“a_20”),如第7行代码所示。

  3. GaussianHMM里的参数“n_components”表示内在状态的个数,本例中这个值等于3,如第8行代码所示。
    参数“covariance_type”表示先验分布里协方差矩阵的类型(在状态已知的情况下,特征服从正态分布)。这个值等于“full”表示在不同市场状态下协方差矩阵是不同的,而且可以是任意半正定对称矩阵(也就是说并不要求协方差矩阵是对角矩阵)。其他可能的取值为“spherical”(协方差矩阵为单位矩阵)、“diag”(协方差矩阵为对角矩阵)以及“tied”(不同状态下的协方差矩阵是一样的)。
    参数“n_iter”则表示EM算法的最大循环次数。

  4. 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

图3

基于上面的模型结果,很容易就能得到较为有效的量化交易策略,比如执行这样的策略就能获得不错的收益:若当天的隐藏状态是牛市(根据模型结果),则买入或继续持有股票,否则卖出股票或保持空仓。

如果实际生产中真的使用这个模型来做交易,你会沮丧地发现实际效果远不如历史数据的测算结果。这是因为隐马尔可夫模型的预测公式如下所示(程序清单1中第10行代码中的predict方法就是这么计算的):

(3) Y ^ = a r g m a x Y P ( y 0 , . . . , y T X 1 , . . . , X T ) \hat{Y} = argmax_Y P(y_0, ..., y_T | X_1, ..., X_T) \tag{3}

也就是说,在测算历史数据时,预测变量 y 1 y_1 时,就已经知道了后来的实际交易数据 X 2 , . . . , X T X_2, ..., X_T 。这一点在实际生活中是不可能实现的,因为没有办法预知未来。因此,为了使模型的测算结果更加符合现实,需要循环地调用公式(3)来预测,而不是一次性地得到全部数据的预测结果。

三、广告时间

这篇文章的大部分内容参考自我的新书《精通数据科学:从线性回归到深度学习》

李国杰院士和韩家炜教授在读过此书后,亲自为其作序,欢迎大家购买。

另外,与之相关的免费视频课程请关注这个链接


  1. 有效市场假说(efficient-market hypothesis)是金融学里最重要的理论之一。这个理论认为,投资者无法通过建模等技术手段从市场上获取超过平均水平的收益,也就是说对股票市场进行建模是无意义的。 ↩︎

  2. 金融学里常常假设市场是一个服从正态分布的随机游走,而且实际数据也大致符合这个假设。另外数学上对正态分布的处理也最为成熟,基于该分布进行建模可行性是最高的,因此传统的量化金融模型大多会使用这一假设。但在实际生活中,市场并不总是服从正态分布的,这会导致传统量化模型在特定条件下表现很差。由于金融市场离钱最近,即使很小的模型偏差也会导致巨大而直接的金钱损失,这就是所谓的“黑天鹅”事件。所以现代量化金融的研究重点是利用非正态的概率分布(non Gaussian distribution)搭建模型。 ↩︎

  3. 在股票市场刚成立时,大部分上市公司是国有企业。这些企业大多数有3种类型的股份:国有股、法人股以及普通股。其中只有普通股能在股票市场上交易,于是这3种类型的股份形成了“同股不同权,同股不同利”的局面,也就是所谓的“股权分置”现象。 ↩︎

  4. 折现就是利用折现率(可以理解为更广义的通货膨胀率),将现在的货币折算成等价的过去货币。举个简单的例子,假设当前时间距离过去的基准时间点为 t t 年,需要折现的金额为 a a ,折现率为 β \beta ,则折现后的金额为 a β t a\beta^{t} ↩︎

  5. 事实上,较早版本的scikit-learn(在0.17之前)是包含隐马尔可夫模型的,但后来因为项目目标的变化,这部分代码被移出了scikit-learn,变成了本节将要使用的hmmlearn。 ↩︎

  6. 虽然Gaussian HMM能将数据分类,但与监督式学习有所不同的是,分类结果并没有直接的物理意义。也就是说,模型只能将数据分类,但无法告诉我们每个类别的具体含义。因此需要人为地根据各个类别里的数据特点,给类别赋予含义。 ↩︎

猜你喜欢

转载自blog.csdn.net/weixin_39844018/article/details/82559349