傳統量化金融時序模型(ARMA,ml-XGBoost,dl-LSTM)

在這裏插入圖片描述
時間序列是按照時間排序的一組隨機變量,時間序列數據本質上反映的是隨機比變量隨時間不斷變化的趨勢。
時間序列預測就是想根據已有的歷史數據,挖掘出這樣的規律,如t1,t2,t3,...,tn{t_1,t_2,t_3,...,t_n}按照時間次序排列,然後嘗試預測其tn+1t_{n+1}時刻的狀態。

時間預測數據的特點:

  • 由從前的時刻點,當下時刻點與未來時刻點之間的相互聯繫關係,數據的變化規律往往存在,趨勢性(在某區間內的發展方向)、週期性(週期性波動,長期有效性)、不規則性(突發狀況和偶然,短期波動不穩定)。
  • 平穩性與非平穩性。平穩性表明時間序列的均值和方差不會隨着時間推移會發生變化。所以如果序列滿足平穩性,也就保證了當前特徵不但僅僅存在與現在,還會延伸到未來。
  • 時間延續的規模太長。隨着存儲技術的提升,可獲得的時間序列數據長度也越長,那麼如何處理“大數據”?

傳統處理方法
經典時間序列模型也就是ARMA(auto regressive moving average model,自迴歸滑動平均模型)了,它是最常用的擬合平穩序列的模型,它又可細分爲 AR模型(auto regression model)、MA模型(moving average model)和ARMA模型(auto regression moving average model) 三大類。

  • AR是線性預測,該模型認爲通過時間序列過去時點的線性組合加上偏置項(如公式中的γ\gamma)即可預測當前時點,它是隨機遊走的一個簡單擴展。即已知N個數據,可由模型推出第N點前面或後面的數據,其本質類似於插值。α\alpha爲權重,p是時間窗大小。
    Xt=i=1pαiXti+γiX_t=\sum_{i=1}^{p}\alpha_iX_{t-i}+\gamma_i
    AR模型對偏自相關函數(PACF)截尾,對自相關函數(ACF)拖尾。所謂截尾指的是從某階開始均爲(接近)0的性質,拖尾指的是並不存在某一階突然跳變到0而是逐漸衰減爲0。

  • MA模型和AR大同小異,使用趨勢移動平均法建立直線趨勢的預測模型。但它不是過去點的線性組合而是過去偏置項的線性組合,故與AR最大的不同之處是,AR模型中偏置項的影響是間接影響當前預測值的。β\beta是權重,q是時間窗大小。
    Xt=i=1qβiγti+γiX_t=\sum_{i=1}^{q}\beta_i\gamma_{t-i}+\gamma_i

  • 至於ARMA,在國際上被譽爲時間序列預測方法中較爲複雜且最高級的模型,先看其公式:
    Xt=i=1pαiXti+i=1qβiγti+γiX_t=\sum_{i=1}^{p}\alpha_iX_{t-i}+\sum_{i=1}^{q}\beta_i\gamma_{t-i}+\gamma_i
    如果權重係數β\beta全爲0,則退化爲AR模型,同理也可以退化爲MA模型。所以MA和AR都是ARMA的一個特例,通過p和q進行調整。但以上這幾種模型都是僅適合於描述平穩過程,而實際應用中所遇到的時間序列往往是非平穩的,往往還需要進行多次差分使其變得平穩,即差分次數d值的大小。不過有時遇到的時間序列呈現出一種特殊的非平穩性,即齊次非平穩性,對於這樣的時間序列只要進行一次或兩次差分就可以轉化爲平穩序列。

針對於具體模型的求解,按照Box-Jenkins的方法,

  • 1.對於給定的時間序列,先確定適合的p,d,q (d值通過檢驗差分後序列是否平穩;p通過偏自相關PACF;q通過自相關函數來確定)
  • 2.計算具體參數。根據觀察到的值,使用最大似然法求解。若最大似然難以求解,考慮使用EM算法 。
  • 3.檢驗其適合性。如均方誤差等。
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import pandas as pd
sns.set()

data = pd.read_csv('data.csv')
print(data.head())

signal = np.copy(data.Close.values)
#MA
def moving_average(signal, period):
    buffer = []
    for i in range(period, len(signal)):
        buffer.append(signal[i - period : i].mean())
    return buffer

#AR
def auto_regressive(signal, p, d, q, future_count = 10):
    buffer = np.copy(signal).tolist()
    for i in range(future_count):
        ma = moving_average(np.array(buffer[-p:]), q)
        forecast = buffer[-1]
        for n in range(0, len(ma), d):
            forecast -= buffer[-1 - n] - ma[n]
        buffer.append(forecast)
    return buffer

future_count = 15
predicted_15 = auto_regressive(signal,15,1,2,future_count)
predicted_30 = auto_regressive(signal,30,1,2,future_count)
plt.figure(figsize=(15, 7))
plt.plot(signal, label = 'data')
plt.plot(predicted_15, label = 'ARIMA 15 MA')
plt.plot(predicted_30, label = 'ARIMA 30 MA')
plt.legend()
plt.show()

如果使用現成工具包:

#AR
from statsmodels.tsa.ar_model import AR
from random import random
model = AR(data)
model_fit = model.fit()

#plot
plt.plot(data)
plt.plot(model_fit.fittedvalues, color='red')
plt.title('RSS: %.4f'% np.nansum((model_fit.fittedvalues-data)**2))
plt.show()

#MA
from statsmodels.tsa.arima_model import ARMA
from random import random
model = ARMA(ts_log_diff, order=(0, 1))
model_fit = model.fit(disp=False)

# ARMA 
from statsmodels.tsa.arima_model import ARMA
from random import random
model = ARMA(data, order=(2, 1))
model_fit = model.fit(disp=False)

在這裏插入圖片描述
但傳統的時間序列方法在很大程度上由參數模型的選擇。

機器學習方法
線性迴歸SVM貝葉斯XGBoost等(博主博客已整理,不再贅述),轉化爲迴歸問題。如用SVM方法直接對數據做迴歸預測等。

#LR方法
import numpy as np
from sklearn.linear_model import LinearRegression
def get_preds_lin_reg(df, target_col, N, pred_min, offset):
   regr = LinearRegression(fit_intercept=True)
   pred_list = []
   for i in range(offset, len(df['adj_close'])):
       X_train = np.array(range(len(df['adj_close'][i-N:i]))) 
       y_train = np.array(df['adj_close'][i-N:i]) 
       X_train = X_train.reshape(-1, 1)     
       y_train = y_train.reshape(-1, 1)
       regr.fit(X_train, y_train)            # Train the model
       pred = regr.predict(N)
       pred_list.append(pred[0][0])  
   
   #限制pre_min
   pred_list = np.array(pred_list)
   pred_list[pred_list < pred_min] = pred_min
   return pred_list
   
#同樣可以使用其他ML算法,如SVM
from sklearn.svm import SVR
vr_rbf = SVR(kernel='rbf',C=1e3,gamma=250)
y_rbf = svr_rbf.fit(X,y).predict(X)
predicted_vol_rbf = np.exp(y_rbf)

svr_linear = SVR(kernel='linear',C=1e3,gamma=250)
y_linear = svr_linear.fit(X,y).predict(X)
predicted_vol_linear = np.exp(y_linear)

svr_poly = SVR(kernel = 'poly',C=1e3,gamma=250)
y_poly = svr_poly.fit(X,y).predict(X)
predicted_vol_poly = np.exp(y_poly)

#XGBoost
from xgboost import XGBRegressor
model = XGBRegressor(seed=model_seed,
                        n_estimators=n_estimators,
                        max_depth=max_depth,
                        learning_rate=learning_rate,
                        min_child_weight=min_child_weight,
                        subsample=subsample,
                        colsample_bytree=colsample_bytree,
                        colsample_bylevel=colsample_bylevel,
                        gamma=gamma)
   
 model.fit(X_train_scaled, y_train_scaled)
 est_scaled = model.predict(X_test_scaled)

深度學習技術
主流多使用LSTM 代碼如下,算法思想博主博客中已有,同樣不做贅述。除了RNN系列外,同樣可以用keras搭建一個CNN用於預測,比如將圖片的R、B、G三維分別換成開盤、最高、最低、收盤和成交量這類似的5維通道,然後在一定的時間窗口內進行卷積。

只是機器學習相關算法運用在時間序列問題上往往是處理爲預測問題。包括用其他的網絡,如玻爾茲曼機RBMCNNGAN等,都是簡單的直接應用,所以也存在一些DeepLearning+傳統處理方法,不但能理解數據的統計構成,還能利用其深度學習的抽象能力,如SOCNN,LSTNet等等。

from keras.layers.core import Dense, Activation, Dropout
from keras.layers.recurrent import LSTM
from keras.models import Sequential

#載入自己數據,並進行基本的數據切分和歸一化預處理
X_train, y_train, X_test, y_test = load_data('text.csv')

model = Sequential()
model.add(LSTM(input_shape=(None, 1), return_sequences=True, units=50))
model.add(Dropout(0.2))
model.add(LSTM(100,return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(units=1))
model.add(Activation("linear"))

reduce_lr=ReduceLROnPlateau(monitor='val_acc',factor=0.9,patience=30,min_lr=0.00001,verbose=1) #在訓練中降低學習率
checkpointer=ModelCheckpoint(filenpath="model.hdf5",verbose=1,save_best_only=True)
model.compile(loss="mse", optimizer="rmsprop")
print ("Compilation Time : ", time.time() - start)

model.fit(X_train,y_train,batch_size=50,epochs=20,verbose=1,validation_split=0.05,callbacks=[reduce_lr,checkpointer],shuffle=Ture)

#重載數據用以畫圖
f=open('text.csv')
df=pd.read_csv(f)
data=np.array(df[kdata])
data=data[::-1]

#預測數據並畫圖
predicted = model.predict(X_test)
print(predicted)
predicted = np.reshape(predicted, (predicted.size,))
plt.plot(data,'y')
plt.plot(list(range(len(data),len(data)+len(X_test))),predicted,'b')
plt.show()

#重載模型,檢查其過擬合,繪製混淆矩陣
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
model.load_weights("model.hdf5")
pred=model.predict(np.array(X_test))
C=confusion_matrix([np.argmax(y) for y in Y_test],[np.argmax(y) for y in pred])
print(C/C.astype(np.float).sum(axis=1))

以以上代碼爲基礎,可以利用LSTM做向後連續多天預測和趨勢判斷的探究,如下圖是博主自己訓練的模型在A股市場上做測試的簡單結果。黃線爲原數據線,綠線爲LSTM的預測線,黑線爲向後多天的訓練結果,紅點與藍點爲上漲或下降的趨勢判斷。(果然還是應該舉起多因子分析大旗…)
在這裏插入圖片描述
爲什麼ML算法在金融數據“預測”會效果不佳?
金融時間序列本身存在:

  • 多重共線性,模型難以設計;
  • 信噪比低,極度嘈雜;
  • ML方法需要序列平穩的條件,而不平穩是常態;
  • 二級市場,想要獲利的所有參與者都會根據結果再做變動;
  • 測不準法則。一邊實驗,一邊改變環境變量,想要找到確定的影響機制成爲不可能;

故單純的使用ML,而不重視經濟學理論,ML原理的本質範式就會不存在,挖掘挖掘的能力也只會變成一種虛假的模擬,如上圖用LSTM的測試結果,在很大程度上產生了“過擬合”,即只是過去時間態勢的回放。

未來?
經濟理論爲綱,使用ML去發掘變量之間的複雜相互作用。
經濟理論爲綱,結合其他信息如新聞,心理分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章