摘要:我們可以看到,MLP在預測絕對波動率值時的表現優於其他所有方法,而CNN在預測相對波動率時在各個方面都優於同一網絡。我們基本上對開盤前和開盤後的波動率做了線性迴歸分析。

標星★ 置頂 公衆號      愛你們    

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

1

前言

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

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

2

問題

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

3

數據準備

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

可視化:

我們感興趣的數據是價格的波動率,本質上就是價格的標準差。我們構造的波動性指標是:用最高價減去最低價(分鐘bar),同時應用一個大小爲N的移動平均窗口。

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

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

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

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

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

  • 0100:CFD開始進行交易

  • 0700:歐盟股市盤前

  • 0800:英國股市開盤

  • 1200:中午

  • 1430:美國股市開盤

  • 1630:英國股市收盤

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

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

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

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

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:線性迴歸

由於數據有分組,所以線性迴歸的統計數據與使用完整數據集生成的統計數據略有不同。

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

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

統計數據上整體有所改善,但仍然不行,這裏所有的線性迴歸都使用statsmodel庫中的OLS。

import statsmodels.api as sm

def 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 LGBMRegressor
from 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)

訓練集和測試集結果:

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

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

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

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

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)

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

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

5

基於圖像識別的迴歸分析

在基於圖像的迴歸之前,我們的目標參數需要做一點修改,因爲在轉換過程中我們會丟失數值。因爲在轉換成圖像之前,每個時間窗口內的值都被歸一化了。

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

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

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

Raw vol_after / vol_before

Capped@30 vol_after / vol_before

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

6

圖像轉換

藉助Gramian Angular Field和pyts庫的幫助下,我們現在可以根據點之間的極座標關係將任何時間序列轉換成圖像。

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

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

from pyts.image import GramianAngularField
from matplotlib import pyplot as plt

from 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):
return
except:
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)
# )

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

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

不通方法的比較:

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

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

2020年第 71 篇文章

量化投資與機器學習微信公衆號,是業內垂直於 Quant、MFE、 Fintech、AI、ML 等領域的 量化類主流自媒體。 公衆號擁有來自 公募、私募、券商、期貨、銀行、保險資管、海外 等衆多圈內 18W+ 關注者。每日發佈行業前沿研究成果和最新量化資訊。

你點的每個“在看”,都是對我們最大的鼓勵

相關文章