HMM(隱馬爾科夫模型)——本質上就是要預測出股市的隱藏狀態(牛市、熊市、震盪、反彈等)和他們之間的轉移概率


摘自:http://blog.csdn.net/baskbeast/article/details/51218777

可以看 《統計學習方法》里的介紹

舉一個日常生活中的例子,我們希望根據當前天氣的情況來預測未來天氣情況。一種辦法就是假設這個模型的每個狀態都只依賴於前一個的狀態,即馬爾科夫假設,這個假設可以極大簡化這個問題。當然,這個例子也是有些不合實際的。但是,這樣一個簡化的系統可以有利於我們的分析,所以我們通常接受這樣的假設,因為我們知道這樣的系統能讓我們獲得一些有用的信息,盡管不是十分准確的。weather-example-anim.gif上面的圖顯示了天氣進行轉移的模型。

注意一個含有N個狀態的一階過程有N²個狀態轉移。每一個轉移的概率叫做狀態轉移概率,就是從一個狀態轉移到另一個狀態的概率。這所有的N²個概率可以用一個狀態轉移矩陣來表示,上面天氣例子的狀態轉移矩陣如下:yesterday_today.PNG這個矩陣表示,如果昨天是陰天,那么今天有25%的可能是晴天,12.5%的概率是陰天,62.5%的概率會下雨,很明顯,矩陣中每一行的和都是1。
為了初始化這樣一個系統,我們需要一個初始的概率向量:3.gif
這個向量表示第一天是晴天。到這里,我們就為上面的一階馬爾科夫過程定義了以下三個部分:

  1. 狀態:晴天、陰天和下雨。
  2. 初始向量:定義系統在時間為0的時候的狀態的概率。
  3. 狀態轉移矩陣:每種天氣轉換的概率。所有的能被這樣描述的系統都是一個馬爾科夫過程。

然而,當馬爾科夫過程不夠強大的時候,我們又該怎么辦呢?在某些情況下,馬爾科夫過程不足以描述我們希望發現的模式。
比如我們的股市,如果只是觀測市場,我們只能知道當天的價格、成交量等信息,但是並不知道當前股市處於什么樣的狀態(牛市、熊市、震盪、反彈等等),在這種情況下我們有兩個狀態集合,一個可以觀察到的狀態集合(股市價格成交量狀態等)和一個隱藏的狀態集合(股市狀況)。我們希望能找到一個算法可以根據股市價格成交量狀況和馬爾科夫假設來預測股市的狀況。
在上面的這些情況下,可以觀察到的狀態序列和隱藏的狀態序列是概率相關的。於是我們可以將這種類型的過程建模為有一個隱藏的馬爾科夫過程和一個與這個隱藏馬爾科夫過程概率相關的並且可以觀察到的狀態集合,就是隱馬爾可夫模型。
隱馬爾可夫模型(Hidden Markov Model) 是一種統計模型,用來描述一個含有隱含未知參數的馬爾可夫過程。其難點是從可觀察的參數中確定該過程的隱含參數,然后利用這些參數來作進一步的分析。下圖是一個三個狀態的隱馬爾可夫模型狀態轉移圖,其中x表示隱含狀態,y表示可觀察的輸出,a表示狀態轉換概率,b表示輸出概率。state_trans.jpg用一個擲篩子的例子闡述一下:假設我手里有三個不同的骰子。第一個骰子是我們平常見的骰子(稱這個骰子為D6),6個面,每個面(1,2,3,4,5,6)出現的概率是1/6。第二個骰子是個四面體(稱這個骰子為D4),每個面(1,2,3,4)出現的概率是1/4。第三個骰子有八個面(稱這個骰子為D8),每個面(1,2,3,4,5,6,7,8)出現的概率是1/8。11.png
假設我們開始擲骰子,我們先從三個骰子里挑一個,挑到每一個骰子的概率都是1/3。然后我們擲骰子,得到一個數字,1,2,3,4,5,6,7,8中的一個。不停的重復上述過程,我們會得到一串數字,每個數字都是1,2,3,4,5,6,7,8中的一個。例如我們可能得到這么一串數字(擲骰子10次):1 6 3 5 2 7 3 5 2 4
這串數字叫做可見狀態鏈。但是在隱馬爾可夫模型中,我們不僅僅有這么一串可見狀態鏈,還有一串隱含狀態鏈。在這個例子里,這串隱含狀態鏈就是你用的骰子的序列。比如,隱含狀態鏈有可能是:D4 D6 D8 D6 D4 D8 D6 D6 D6 D4。
一般來說,HMM中說到的馬爾可夫鏈其實是指隱含狀態鏈,因為隱含狀態(骰子)之間存在轉換概率。在我們這個例子里,D6的下一個狀態是D4,D6,D8的概率都是1/3。D4,D8的下一個狀態是D4,D6,D8的轉換概率也都一樣是1/3。這樣設定是為了最開始容易說清楚,但是我們其實是可以隨意設定轉換概率的。比如,我們可以這樣定義,D6后面不能接D4,D6后面是D6的概率是0.9,是D8的概率是0.1。這樣就是一個新的HMM。
同樣的,盡管可見狀態之間沒有轉換概率,但是隱含狀態和可見狀態之間有一個概率叫做輸出概率。就我們的例子來說,六面骰子(D6)產生1的輸出概率是1/6。產生2,3,4,5,6的概率也都是1/6。我們同樣可以對輸出概率進行其他定義。比如,我有一個被賭場動過手腳的六面骰子,擲出來是1的概率更大,是1/2,擲出來是2,3,4,5,6的概率是1/10。12.png13.png
其實對於HMM來說,如果提前知道所有隱含狀態之間的轉換概率和所有隱含狀態到所有可見狀態之間的輸出概率,做模擬是相當容易的。但是應用HMM模型時候呢,往往是缺失了一部分信息的,有時候你知道骰子有幾種,每種骰子是什么,但是不知道擲出來的骰子序列;有時候你只是看到了很多次擲骰子的結果,剩下的什么都不知道。如果應用算法去估計這些缺失的信息,就成了一個很重要的問題。
和HMM模型相關的算法主要分為三類,分別解決三種問題:

  1. 知道骰子有幾種(隱含狀態數量),每種骰子是什么(轉換概率),根據擲骰子擲出的結果(可見狀態鏈),我想知道每次擲出來的都是哪種骰子(隱含狀態鏈)。
  2. 還是知道骰子有幾種(隱含狀態數量),每種骰子是什么(轉換概率),根據擲骰子擲出的結果(可見狀態鏈),我想知道擲出這個結果的概率。
  3. 知道骰子有幾種(隱含狀態數量),不知道每種骰子是什么(轉換概率),觀測到很多次擲骰子的結果(可見狀態鏈),我想反推出每種骰子是什么(轉換概率)。
    如果要解決上面股市中的問題,我們就需要解決問題1和問題3,下面我們就看看如何實現。


HMM在股票市場中的應用

 

我們假設隱藏狀態數量是6,即假設股市的狀態有6種,雖然我們並不知道每種狀態到底是什么,但是通過后面的圖我們可以看出那種狀態下市場是上漲的,哪種是震盪的,哪種是下跌的。可觀測的特征狀態我們選擇了3個指標進行標示,進行預測的時候假設假設所有的特征向量的狀態服從高斯分布,這樣就可以使用 hmmlearn 這個包中的 GaussianHMM 進行預測了。下面我會逐步解釋。

 

首先導入必要的包:

In [1]:
from hmmlearn.hmm import GaussianHMM import numpy as np from matplotlib import cm, pyplot as plt import matplotlib.dates as dates import pandas as pd import datetime 
 

測試時間從2005年1月1日到2015年12月31日,拿到每日滬深300的各種交易數據。

In [2]:
#6個隱藏狀態
data = get_price('CSI300.INDX',start_date=beginDate, end_date=endDate,frequency='1d') data[0:9] 
Out[2]:
  ClosingPx HighPx LowPx NextTradingDate OpeningPx TotalTurnover TotalVolumeTraded
MDEntryDate              
2005-01-04 982.79 994.77 980.66 20050105 994.77 4431976960 7412869
2005-01-05 992.56 997.32 979.88 20050106 981.58 4529207808 7119109
2005-01-06 983.17 993.79 980.33 20050107 993.33 3921015040 6288028
2005-01-07 983.96 995.71 979.81 20050110 983.05 4737468928 7298694
2005-01-10 993.88 993.96 979.79 20050111 983.76 3762931968 5791697
2005-01-11 997.14 999.55 991.09 20050112 994.19 3704076032 5849079
2005-01-12 996.75 996.98 989.26 20050113 996.65 3093298944 5014525
2005-01-13 996.88 999.47 992.70 20050114 996.08 3842172928 6044065
2005-01-14 988.31 1006.46 987.23 20050117 996.62 4162920960 7297842
 

拿到每日成交量和收盤價的數據。

In [3]:
 

計算每日最高最低價格的對數差值,作為特征狀態的一個指標。

In [4]:
Out[4]:
 

計算每5日的指數對數收益差,作為特征狀態的一個指標。

In [5]:
#這個作為后面計算收益使用
logRet_5 = np.log(np.array(close[5:])) - np.log(np.array(close[:-5])) logRet_5 
Out[5]:
 

計算每5日的指數成交量的對數差,作為特征狀態的一個指標。

In [6]:
Out[6]:
 

由於計算中出現了以5天為單位的計算,所以要調整特征指標的長度。

In [7]:
 

把我們的特征狀態合並在一起。

In [8]:
Out[8]:
 

下面運用 hmmlearn 這個包中的 GaussianHMM 進行預測。

In [9]:
Out[9]:
 

關於 covariance_type 的參數有下面四種:

 

spherical:是指在每個馬爾可夫隱含狀態下,可觀察態向量的所有特性分量使用相同的方差值。對應協方差矩陣的非對角為0,對角值相等,即球面特性。這是最簡單的高斯分布PDF。imagediag:是指在每個馬爾可夫隱含狀態下,可觀察態向量使用對角協方差矩陣。對應協方差矩陣非對角為0,對角值不相等。diag是hmmlearn里面的默認類型。imagefull:是指在每個馬爾可夫隱含狀態下,可觀察態向量使用完全協方差矩陣。對應的協方差矩陣里面的元素都是不為零。imagetied:是指所有的馬爾可夫隱含狀態使用相同的完全協方差矩陣。

這四種PDF類型里面,spherical, diag和full代表三種不同的高斯分布概率密度函數,而tied則可以看作是GaussianHMM和GMMHMM的特有實現。其中,full是最強大的,但是需要足夠多的數據來做合理的參數估計;spherical是最簡單的,通常用在數據不足或者硬件平台性能有限的情況之下;而diag則是這兩者一個折中。在使用的時候,需要根據可觀察態向量不同特性的相關性來選擇合適的類型。

轉自知乎用戶Aubrey Li

 

我們把每個預測的狀態用不同顏色標注在指數曲線上看一下結果。

In [10]:
for i in range(model.n_components): pos = (hidden_states==i) plt.plot_date(Date[pos],close[pos],'o',label='hidden state %d'%i,lw=2) plt.legend(loc="left") 
 
 

從圖中可以比較明顯的看出綠色的隱藏狀態代表指數大幅上漲,淺藍色和黃色的隱藏狀態代表指數下跌。

 

為了更直觀的表現不同的隱藏狀態分別對應了什么,我們采取獲得隱藏狀態結果后第二天進行買入的操作,這樣可以看出每種隱藏狀態代表了什么。

In [11]:
for i in range(model.n_components): pos = (hidden_states==i) pos = np.append(0,pos[:-1])#第二天進行買入操作 df = res.logRet_1 res['state_ret%s'%i] = df.multiply(pos) plt.plot_date(Date,np.exp(res['state_ret%s'%i].cumsum()),'-',label='hidden state %d'%i) plt.legend(loc="left") 
 
 

可以看到,隱藏狀態1是一個明顯的大牛市階段,隱藏狀態0是一個緩慢上漲的階段(可能對應反彈),隱藏狀態3和5可以分別對應震盪下跌的大幅下跌。其他的兩個隱藏狀態並不是很明確。由於股指期貨可以做空,我們可以進行如下操作:當處於狀態0和1時第二天做多,當處於狀態3和5第二天做空,其余狀態則不持有。

In [12]:
#做多
short = (hidden_states==3) + (hidden_states == 5) #做空 long = np.append(0,long[:-1]) #第二天才能操作 short = np.append(0,short[:-1]) #第二天才能操作 
 

收益曲線圖如下:

In [13]:
Out[13]:
[<matplotlib.lines.Line2D at 0x7fb1b67bec50>]
 
 

可以看到效果還是很不錯的。但事實上該結果是有些問題的。真實操作時,我們並沒有未來的信息來訓練模型。不過可以考慮用歷史數據進行訓練,再對之后的數據進行預測。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM