天天看點

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

作者:Chuan Bai   編譯:1+1=6

1

前言

金融市場主要處理時間序列方面的問題,圍繞時間序列預測有大量的算法和工具。 今天,我們使用CNN來基于回歸進行預測,并與其他一些傳統算法進行比較,看看效果如何。

我們這裡關注的是市場波動率,具體來說,就是股市開盤前後的波動率。

2

問題

我們覺得,開盤前的波動率(vol)可能是一個很好的名額。如果我們能夠準确地預測波動率,我們就可以利用它做些事情。

3

資料準備

2016年1月至2020年3月富時100指數合約資料。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

可視化:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

我們感興趣的資料是價格的波動率,本質上就是價格的标準差。我們構造的波動性名額是:用最高價減去最低價(分鐘bar),同時應用一個大小為N的移動平均視窗。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

原則上,當價格大幅波動時,波動率應該變大,為了測試這一點,我們随機選擇一個交易日,然後根據當天的vol和價格來确認這一點。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

為了比較所有交易日的波動率,我們繪制了基于時序的波動率。波動率是根據5分鐘的時間視窗計算的。每個點代表最後5分鐘的體積,在1070天内每分鐘計算一次。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

可以看到,這些峰值似乎在一小時内重複出現,例如在0000和0100、0700和0800處出現峰值。讓我們來畫出熱力圖來檢查這些值。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

我們可以看到時間是Daylight Saving Time(夏令時),是以需要将夏令時調整為GMT(格林尼治标準時間),如下所示:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

在某些時期,波動率很大。貫穿熱力圖的實線表明,在某些時間,波動性持續較高,這些都是合理的。

  • 0100:CFD開始進行交易
  • 0700:歐盟股市盤前
  • 0800:英國股市開盤
  • 1200:中午
  • 1430:美國股市開盤
  • 1630:英國股市收盤

我們還可以看到,在2020年3月的幾天裡,波動率很高。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

如果我們想要利用波動率,它應該越高越好,那麼最高的時間應該是股市開盤的時候,即0800。如果我們可以用開盤前一小時的波動率來預測開盤後5分鐘的波動率(通常這一時間段是一天中波動率最大的時候),那麼我們可以圍繞這個時間段去進行交易。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

上圖顯示了2016年至2020年期間所有交易日的總波動率。我們可以看到,波動率往往在0800點市場開盤後立即回升,幾分鐘後回落。

我們假設開盤前和開盤後的波動率之間存在相關性。是以,如果我們在開盤前1小時和開盤後5分鐘分别畫出波動率的平均值,它們應該總體上會有一個上升趨勢,确實如此:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

x軸是開盤前1小時的平均波動率,y軸是開盤後5分鐘的平均波動率。兩者雖有相關性,但它們之間存在很多變量,是以不是一個可靠的預測因子。例如,根據這個圖表,如果開盤前的平均波動率為7.5,我們有理由假設市場開盤後的波動率在5到25之間,這沒啥幫助。

4

進一步讨論

我們基本上對開盤前和開盤後的波動率做了線性回歸分析。接下來我們加入一些稍微複雜的算法。将1070個樣本分為三組:訓練、驗證和測試。

  • 訓練:0-699(截止2018-10-09)
  • 驗證:700-899(截止2019-07-25)
  • 測試:900-1070(截止2020-03-25)

▌方法1:線性回歸

由于資料有分組,是以線性回歸的統計資料與使用完整資料集生成的統計資料略有不同。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

從上面的圖我們可以看出,相關性仍然很強,但可決系數很低,我們不能用這個方法來解釋開盤後的波動率變化。

改進預測的方法之一是增加特征的數量,這就導緻了多變量(元)回歸。在這種情況下,我們可以利用開盤前一小時的分鐘(1min)來預測開盤後的波動率:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

統計資料上整體有所改善,但仍然不行,這裡所有的線性回歸都使用statsmodel庫中的OLS。

import statsmodels.api as smdef lingres(X, y, title=''):
    X_test = X[900:]
    y_test = y[900:]
    X = X[:700]
    y = y[:700]
    model = sm.OLS(y, X).fit()
    predictions = model.predict(X)
    plot_out(y, predictions, title + ' Train')
    predictions = model.predict(X_test)
    plot_out(y_test, predictions, title + ' Test')return model
           

▌方法2:梯度提升法

在進行預測特别是分類時,梯度增強是标準的方法,它将為我們提供一個非常好的基準,以便後面做進一步改進。

這裡我們使用LightGBM,輸入到模型中的特征本質上與多元回歸相同。

from lightgbm import LGBMRegressorfrom sklearn.model_selection import cross_validate
regr = LGBMRegressor()
scores = cross_validate(regr, X, y, cv=5, scoring=['neg_mean_squared_error', 'r2'])
scores#{'fit_time': array([0.242456, 0.243822, 0.285033, 0.266963, 0.213427]),# 'score_time': array([0.003387, 0.003706, 0.004177, 0.003168, 0.003078]),# 'test_neg_mean_squared_error': array([ -3.989691, -1.751312, -1.646064, -2.936831, -11.072056]),# 'test_r2': array([0.473771, 0.327672, 0.443433, 0.042896, 0.609157])}
           

通過5種不同的交叉驗證評估,該模型在我們資料樣本的不同切面上表現不是很穩定,這表明在我們的資料在不同部分存在某種不平衡的離群樣本。盡管當我們更深入地研究預測過程時,這可能是一個問題,但就本文而言,隻要我們有相同的訓練、驗證和測試集,我們就不需要過多擔心,因為這是我們的第一次嘗試。

如前所述,我們需要在不同的方法中保持樣本的一緻性,是以我們隻訓練前700個樣本,并預測樣本900+個樣本 。

train_index = [x for x in range(700)]
test_index = [x for x in range(900, 1070)]
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
regr.fit(X_train, y_train)
y_hat = regr.predict(X_test)
y_train_hat = regr.predict(X_train)
           

訓練集和測試集結果:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

訓練結果比方法1好,R方為0.94,但測試集的預測失敗了。雖然它在測試集中表現不是很好,但仍然比我們使用純線性回歸所做的預測要好。

▌方法3:MLP(神經網絡)

當我們在預測中有如此大的方差時,神經網絡可能能夠描述輸入特征之間的複雜關系,并發現它們之間的隐藏關系。

我們使用FastAI作為深度學習庫來建構底層網絡,目前FastAI是建立在PyTorch之上的。大家可以描述自定義的PyTorch模型并将其傳遞到FastAI以獲得FastAI提供的訓練工具。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

https://www.fast.ai/

我們使用與LightGBM相同的輸入和輸出集,并将資料輸入到2個隐層的MLP網絡中,每個隐層有300個神經元。

from fastai.tabular import *
dep_var = 'target'
y.name = dep_var
mlp_df = pd.concat([X, y], axis=1)
procs = [Normalize]
data = TabularDataBunch.from_df('.', mlp_df.iloc[:900], dep_var, valid_idx=range(700, 900), procs=procs)
learn = tabular_learner(data, layers=[300,300], loss_func=mse, metrics=[r2_score, explained_variance])
learn.lr_find(start_lr=1e-6, num_it=50, end_lr=1e-1)
learn.recorder.plot()
learn.fit_one_cycle(3, slice(3e-4), wd=0.2) 
           

經過幾次疊代訓練,我們可以得到類似這樣的預測結果。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...
matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...
matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

我們可以看到,由于最近市場的波動,測試集中的波動率最高,是以驗證資料集對我們的測試資料不具有代表性。然而,與之前的方法相比,在統計資料方面表現較好。

5

基于圖像識别的回歸分析

在基于圖像的回歸之前,我們的目标參數需要做一點修改,因為在轉換過程中我們會丢失數值。因為在轉換成圖像之前,每個時間視窗内的值都被歸一化了。

為了彌補這一缺陷, 我們用開盤前後的平均價格比作為我們的目标。通過這種方式,我們向神經網絡提出了一個問題:與盤前波動率相比,開盤後的波動率會有多大?例如,如果開盤前的平均波動率是10,而開盤後的波動率是50,我們的目标是預測5而不是原始的50。

為了防避免這種問題的發生,我們訓練了一個MLP網絡,其與前面的方法具有相同的結構、相同的資料。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...
matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...
matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

注:由于在除法計算後出現了巨大的峰值,是以波動率上限為30,如下所示:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

Raw vol_after / vol_before

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

[email protected] vol_after / vol_before

與原始值的預測相比,MLP的間接預測結果略差,但差别不大。現在我們有了CNN網絡可以比較的基準。

6

圖像轉換

借助Gramian Angular Field和pyts庫的幫助下,我們現在可以根據點之間的極坐标關系将任何時間序列轉換成圖像。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

https://arxiv.org/pdf/1506.00327.pdf

在下面的代碼中,其每天建立一個圖像,每個圖像描述開盤前60分鐘的波動率。

from pyts.image import GramianAngularFieldfrom matplotlib import pyplot as pltfrom multiprocessing import Pool, cpu_count
gadf = GramianAngularField(image_size=60, method='difference')
X_gadf = gadf.fit_transform(X)def convert_img(idx):
    fig = plt.figure()
    ax = plt.subplot(111)try:
        fname = f'imgs/{idx}.png'if os.path.exists(fname):returnexcept:return
    ax.imshow(X_gadf[idx], cmap='rainbow', origin='lower')
    ax.set_title('')
    ax.set_xticks([])
    ax.set_yticks([])
    fig.savefig(fname, bbox_inches='tight')
p = Pool(cpu_count())
_ = p.map(convert_img, (i for i in range(1070)))
           

對于CNN網絡來說,它本質上是使用ResNET34作為底層,然後在頂部加上一個[1024,512]稠密層,并使用一個簡單的線性激活節點執行最終的回歸。

data = (ImageList.from_csv('imgs', 'labels.csv')
                 .split_by_idxs(list(range(700)), list(range(700, 900)))
                 .label_from_df()
                 .databunch())
learner = cnn_learner(data, models.resnet34, loss_func=mae, metrics=[r2_score])
learner.model[1]# Sequential(# (0): AdaptiveConcatPool2d(# (ap): AdaptiveAvgPool2d(output_size=1)# (mp): AdaptiveMaxPool2d(output_size=1)# )# (1): Flatten()# (2): BatchNorm1d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)# (3): Dropout(p=0.25, inplace=False)# (4): Linear(in_features=1024, out_features=512, bias=True)# (5): ReLU(inplace=True)# (6): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)# (7): Dropout(p=0.5, inplace=False)# (8): Linear(in_features=512, out_features=1, bias=True)# )
           

經過反複的訓練,我們得到了這樣的結果:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...
matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

我們可以看到,即使預測相同的目标,基于圖像的回歸也比MLP對應的回歸表現得好得多。

不通方法的比較:

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

我們可以看到,MLP在預測絕對波動率值時的表現優于其他所有方法,而CNN在預測相對波動率時在各個方面都優于同一網絡。

是以,在進行時間序列預測時,CNN是一個很好的選擇,盡管它确實需要大量的計算能力來進行圖像轉換和訓練。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

關于Python金融量化

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...

專注于分享Python在金融量化領域的應用。加入知識星球,可以免費擷取量化投資視訊資料、量化金融相關PDF資料、公衆号文章Python完整源碼、量化投資前沿分析架構,與部落客直接交流、結識圈内朋友等。

matlab卷積神經網絡代碼_如何用卷積神經網絡預測股票波動率?(附Python代碼)...