繁簡切換您正在訪問的是FX168財經網,本網站所提供的內容及信息均遵守中華人民共和國香港特別行政區當地法律法規。

FX168財經網>人物頻道>帖子

HMM擇時進一步研究

作者/外匯老法師 2019-05-09 18:52 0 來源: FX168財經網人物頻道


一、研究過程:方法參考陳大神的帖子

1、研究對象。考慮到之後以滬深300期貨作為回測對象,因此以滬深300指數為研究對象,采用python中的hmmlearn.hmm模塊中的GaussianHMM模型進行擬合,擬合樣本範圍為2005-2014,測試樣本為2015-2017。

2、觀測變量選取。選取日對數收益率、5日對數收益率、日極差對數收益率(最高減最低後取對數)作為觀測變量。三個觀測變量經偏度、峰度及正態性檢驗,符合高斯分布。

3、擬合。隱含狀態數取13,進行GaussianHMM模型擬合.。

4、分析。畫出滬深300指數2005-2014年每日股價所處的狀態;畫出每個狀態在10年間的累計收益圖。由圖分析出狀態4、9、10為上漲狀態、狀態0、2、8為下跌狀態。

5、簡單回測。在擬合樣本及測試樣本中,分別將每個上漲狀態的下一天的累計收益率,減去下跌狀態下一天的累計收益率,得到擬合範圍及測試範圍的隱馬爾科夫擇時模型的累計收益率圖。

6、初步結論:2005-2014年,該策略多空累計收益約55倍,且少有回撤。2015-2017的測試樣本,該策略累計收益約1.7倍,收益率曲線前半段上升較為平穩,16年7月之後收益有所回撤。

二、回測

1、回測思路:

(1)選取滬深300股指期貨10年至17年作為回測對象,調倉周期為每天,時間為開盤,為盡可能模擬滬深300指數收益,設傭金為0,保證金比率為100%。每天開盤,將截止昨日收盤前90天的日對數收益率、5日對數收益率、日極差對數收益率輸入第一步中擬合出的HMM模型對昨日進行隱含狀態預測。昨日預測為上漲狀態即做多、下跌狀態即做空。其結果與原先大相近庭,收益為負數。

(2)不在每天進行模型預測,而將“一、研究過程”中產生的信號直接輸入進行回測,15-17年收益為38.75%,最大回撤為12.87%,表現大幅度提高。

2、反思:經過反複試驗,發現隱馬爾科夫模型具有前視性,原先使用完整收益序列預測每一天的狀態時會使用到未來數據,其預測結果為最大後驗概率的狀態。而真實回測時預測最後一天的狀態,狀態預測會根據未來數據變化而變化、不穩定。

三、穩定HMM信號模型

為提高HMM的穩定性,構造穩定HMM信號模型。利用觀測變量正態分布的特征,計算前750天觀測變量的均值與標準差,對當日及之後共5天的觀測值進行模擬。將這未來5天的模擬數據與過去750天的觀測變量連同一起產生1000個樣本,輸入HMM模型進行預測,產生1000個當天狀態的預測值。若某狀態預測頻率高於80%,則認為其為穩定信號。根據穩定信號進行回測,11-14年收益率為32.49%,最大回撤16.32%;15-17年收益率為12.49%,最大回撤為16.13%。可見穩定HMM信號模型稍稍改善了模型預測能力,但收益和原HMM模型不可同日而語。

四、HMM狀態動量反轉策略
1、思路:改變一下使用HMM模型的思路。根據前面的研究,HMM模型雖然在預測上不穩定,但其對曆史數據具有極強形態識別能力。考慮根據HMM識別出的牛熊特征,進行擇時。

2、回測實現:仍以滬深300指數期貨為標的,傭金為0、保證金比率為100%。每個交易日,利用HMM模型獲取過去60天的牛熊狀態,分類為牛、熊與震蕩,狀態值分別為1,-1和0。選取過去10天為短周期、60天為長周期,將短周期和長周期每日狀態值進行累加,得到牛熊指標。當短期牛熊指標大於6(短期動量)或者長期牛熊指標小於-25且短期牛熊指標大於0(長期反轉),則做多;做空策略相對稱。該策略在10年6月至16年12月,累計收益率為81.77%,最大回撤為20.18%。

3、結論:該策略有一定的收益潛力,能夠識別大趨勢,在大漲大跌中獲取趨勢收益,但在震蕩市中表現尚一般。另外,該模型收益受參數影響大,有過擬合的風險。

才疏學淺,對hmm研究不深,最後沒研究出啥牛逼成果。在這里拋磚迎玉,歡迎大家批評指正,提供新思路哈。

pickle文件:https://pan.baidu.com/s/1dFIMjTZ

from hmmlearn.hmm import GMMHMM,GaussianHMMimport datetimeimport numpy as npimport pandas as pdimport seaborn as snsfrom matplotlib import cmfrom matplotlib import pyplot as pltimport scipy.stats as scs freq='1d'stock='000300.XSHG'startdate = '2005-04-08'enddate = '2014-12-31'df = get_price([stock], start_date=startdate, end_date=enddate, frequency=freq, fields=['close','volume','high','low'])close = df['close'][stock]high = df['high'][stock][5:]low = df['low'][stock][5:]volume = df['volume'][stock][5:]money = df['volume'][stock][5:]datelist = pd.to_datetime(close.index[5:])logreturn = (np.log(np.array(close[1:]))-np.log(np.array(close[:-1])))[4:]logreturn5 = np.log(np.array(close[5:]))-np.log(np.array(close[:-5]))diffreturn = (np.log(np.array(high))-np.log(np.array(low)))closeidx = close[5:]X = np.column_stack([logreturn,diffreturn,logreturn5])len(X)def normality_test(arr):  print "Skew of dataset %14.3f" % scs.skew(arr)  print "Skew test p-value %14.3f" % scs.skewtest(arr)[1]  print "Kurt of dataset %14.3f" % scs.kurtosis(arr)  print "Kurt test p-value %14.3f" % scs.kurtosistest(arr)[1]  print "Norm test p-value %14.3f" % scs.normaltest(arr)[1] normality_test(logreturn)
Skew of dataset         -0.360
Skew test p-value          0.000
Kurt of dataset          2.995
Kurt test p-value          0.000
Norm test p-value          0.000
hmm = GaussianHMM(n_components = 13, covariance_type='diag',n_iter = 5000).fit(X)latent_states_sequence = hmm.predict(X)len(latent_states_sequence)sns.set_style('white')plt.figure(figsize = (15, 8))for i in range(hmm.n_components):state = (latent_states_sequence == i)plt.plot(datelist[state],closeidx[state],'.',label = 'latent state %d'%i,lw = 1)plt.legend()plt.grid(1)
data = pd.DataFrame({'datelist':datelist,'logreturn':logreturn,'state':latent_states_sequence}).set_index('datelist')plt.figure(figsize=(20,15))for i in range(hmm.n_components):state = (latent_states_sequence == i)idx = np.append(0,state[:-1])data['state %d_return'%i] = data.logreturn.multiply(idx,axis = 0) plt.plot(np.exp(data['state %d_return' %i].cumsum()),label = 'latent_state %d'%i)plt.legend(loc='upper left')plt.grid(1)plt.annotate(i, xy=(2400, np.exp(data['state %d_return' %i].cumsum())[2300]), xytext=(2400, np.exp(data['state %d_return' %i].cumsum())[2300]))
buy = (latent_states_sequence == 9) + (latent_states_sequence == 4)+ (latent_states_sequence == 10)buy = np.append(0,buy[:-1])sell = (latent_states_sequence == 0) + (latent_states_sequence == 2)+ (latent_states_sequence == 8)sell = np.append(0,sell[:-1])data['backtest_return'] = data.logreturn.multiply(buy,axis = 0)- data.logreturn.multiply(sell,axis = 0)plt.figure(figsize = (15,8))plt.plot_date(datelist,np.exp(data['backtest_return'].cumsum()),'-',label='backtest result')plt.legend()plt.grid(1)
startdate2 = '2015-01-01'enddate2 = '2017-04-19'df2 = get_price([stock], start_date=startdate2, end_date=enddate2, frequency=freq, fields=['close','volume','high','low'])close2 = df2['close'][stock]high2 = df2['high'][stock][5:]low2 = df2['low'][stock][5:]volume2 = df2['volume'][stock][5:]money2 = df2['volume'][stock][5:]datelist2 = pd.to_datetime(close2.index[5:])logreturn2 = (np.log(np.array(close2[1:]))-np.log(np.array(close2[:-1])))[4:]logreturn52 = np.log(np.array(close2[5:]))-np.log(np.array(close2[:-5]))diffreturn2 = (np.log(np.array(high2))-np.log(np.array(low2)))closeidx2 = close2[5:]X2 = np.column_stack([logreturn2,diffreturn2,logreturn52])latent_states_sequence = hmm.predict(X2)data2 = pd.DataFrame({'datelist':datelist2,'logreturn':logreturn2,'state':latent_states_sequence}).set_index('datelist')buy = (latent_states_sequence == 9) + (latent_states_sequence == 4)+ (latent_states_sequence == 10)buy = np.append(0,buy[:-1])sell = (latent_states_sequence == 0) + (latent_states_sequence == 2)+ (latent_states_sequence == 8)sell = np.append(0,sell[:-1])data2['backtest_return'] = data2.logreturn.multiply(buy,axis = 0) - data2.logreturn.multiply(sell,axis = 0)plt.figure(figsize = (15,8))plt.plot_date(datelist2,np.exp(data2['backtest_return'].cumsum()),'-',label='backtest result')plt.legend()plt.grid(1)
/opt/conda/envs/python2/lib/python2.7/site-packages/sklearn/utils/deprecation.py:70: DeprecationWarning: Function log_multivariate_normal_density is deprecated; The function log_multivariate_normal_density is deprecated in 0.18 and will be removed in 0.20.
  warnings.warn(msg, category=DeprecationWarning)
import pickleoutput = open('hmm300day.pkl', 'wb')pickle.dump(hmm,output)output.close()
分享到:
舉報財經168客戶端下載

全部回複

0/140

投稿 您想發表你的觀點和看法?

更多人氣分析師

  • 張亦巧

    人氣2208文章4145粉絲45

    暫無個人簡介信息

  • 張迎妤

    人氣1912文章3305粉絲34

    個人專注於行情技術分析,消息面解讀剖析,給予您第一時間方向...

  • 指導老師

    人氣1864文章4423粉絲52

    暫無個人簡介信息

  • 李冉晴

    人氣2320文章3821粉絲34

    李冉晴,專業現貸實盤分析師。

  • 梁孟梵

    人氣2184文章3177粉絲39

    qq:2294906466 了解群指導添加微信mfmacd

  • 王啟蒙現貨黃金

    人氣328文章3545粉絲8

    本人做分析師以來,並專注於貴金屬投資市場,尤其是在現貨黃金...

  • 金泰鉻J

    人氣2328文章3925粉絲51

    投資問答解咨詢金泰鉻V/信tgtg67即可獲取每日的實時資訊、行情...

  • 金算盤

    人氣2696文章7761粉絲125

    高級分析師,混過名校,廝殺於股市和期貨、證券市場多年,專注...

  • 金帝財神

    人氣4760文章8329粉絲119

    本文由資深分析師金帝財神微信:934295330,指導黃金,白銀,...

FX168財經

FX168財經學院

FX168財經

FX168北美