[Kaggle比赛] 高频股价预测小结
高頻股價預測
文章目錄
- 高頻股價預測
- 問題描述
- 問題分析
- 數據分析
- 數據集
- 數據清洗
- 解決方案
- 數據預處理
- 歸一化
- Prices
- Volume
- 時間信息
- 對于預測值的處理
- 噪聲
- 模型探索
- 基于LSTM的RNN模型
- 遞歸神經網絡(RNN)
- 長短期記憶(LSTM)網絡
- 模型實現
- 參數調整
- 卷積神經網絡
- 卷積神經網絡
- 模型實現
- 全鏈接的神經網絡模型
- 神經網絡模型
- 模型實現
- 利用XGBoost創建的模型
- XGBoost介紹
- 模型實現
- 參數調整
- 隨機回歸森林模型
- 模型實現
- 參數調整
- 結果與討論
- 結果
- 討論:模型
- 討論:模型之外
- 未來的工作
問題描述
Kaggle 比賽: CS410/EI339 Fall18’ Stock Price Prediction
- 通過對交易委托賬本(訂單簿)中數據的學習,給定特定一只股票10個時間點股票的訂單簿信息,預測下20個時間點中間價的均值。
- 評價標準為均方根誤差。
RMSE?(θ^)=MSE?(θ^)=E?((θ^?θ)2)\operatorname{RMSE}(\hat{\theta}) = \sqrt{\operatorname{MSE}(\hat{\theta})} = \sqrt{\operatorname{E}((\hat{\theta}-\theta)^2)}RMSE(θ^)=MSE(θ^)?=E((θ^?θ)2)? - 交易時間為工作日9:30-11:30,13:00-15:00,快照頻率3秒。
- 股價的形成分為集合競價和連續競價
– 集合競價:9:15-9:25,開盤集合競價,確定開盤價
– 連續競價:9:30之后,根據買賣雙方的委托形成的價格 - 競價原則:價格優先,時間優先。
- 交易委托賬本具體信息:
– Date - 日期
– Time - 時間
– MidPrice - 中間價(買入價與賣出價的平均值)
– LastPirce - 最新成交價
– Volume - 當日累計成交數量
– BidPrice1 - 申買最高價
– BidVolume1 - 申買最高價對應的量
– AskPrice1 - 申賣最高價
– AskVolume1 - 申賣最高價對應的量
問題分析
高頻交易,是指從那些人們無法利用的、極為短暫的市場變化中尋求獲利的自動化程序交易,比如某種證券買入價和賣出價差價的微小變化,或者某只股票在不同交易所之間的微小價差。這種交易的速度如此之快,以至于有些交易機構將自己的“服務器群組”安置到了離交易所的服務器很近的地方,以縮短交易指令通過光纜以光速傳送的時間。一般是以電腦買賣盤程式進行非常高速的證券交易,從中賺取證券買賣價格的差價。1
在這個問題中,我們利用10個時間點股票的訂單簿信息,預測特定一只股票下20個時間點中間價的均值,來判斷其在一分鐘內的價格變化特征,以便于高頻交易。高頻交易的意義在于,對于人類來說,很難在一分鐘之內判斷出股價變化情況,并完成交易。因此,只能利用計算機進行自動化交易。
對于無信息無模型預測,即利用訂單簿中最后一個價格“預測”,得到的均方根誤差為0.00155。試圖通過分析數據、建立模型,做出高于此誤差的預測。
數據分析
數據集
訓練集(raw training data,train_data.csv):430039條訂單簿信息
測試集(test data, test_data.csv):1000條(100組)訂單簿信息
為了避免概念的混淆,下文中如果特別說明,“測試集”均指public board所依賴的數據。此外,這里的“訓練集”下文中包含經過數據清理和預處理的訓練集(training data)和驗證集(development data)。
數據清洗
為了將訓練集轉換為測試集的格式,即通過10個間隔3秒的訂單簿記錄,來預測后20個間隔3秒的訂單簿記錄中中間價的均值,必須對數據清洗。
- 將訓練集集中連續的nGiven+nPredictnGiven + nPredictnGiven+nPredict 2 條數據作為一組數據。
- 檢查每一組數據,去掉含有時間差不為3秒的連續兩條數據的組。這樣可以跳過跨天的以及不規整的數據。
解決方案
數據預處理
歸一化
給定的數據特征(日期、時間、價格、成交量等)的量綱不同,并且數據絕對值差的較大。如測試集第一條數據:
MidPrice和Volume差6個數量級。
首先,數據歸一化后,最優解的尋優過程明顯會變得平緩,更容易正確地收斂到最優解。3
其次,在支持向量機(SVM)等不具有伸縮不變性的模型中,大數量級的數據會掩蓋小數量級的數據。這是因為隨機進行初始化后,各個數據擁有同樣的或近似的縮放比例,相加之后小數量級的數據便被大數量級的數據“吃掉了”。
此外,對于具有伸縮不變性的模型,如邏輯回歸,進行歸一化也有助于模型更快地收斂。
綜上所述,對模型進行歸一化是十分有必要的。
Prices
訓練集MidPrice分布:
測試集MidPrice分布:
從上面兩張圖片中可以看出,訓練集和測試集中最重要的特征以及待遇測量——中間價只有約三分之一重合。這意味著如果按照數值直接進行歸一化,可能會有較差的結果。
我采取的第一種方式是預測差值——+即每組數據待預測量——下20條數組中MidPrice的均值與最后一個MidPrice的差值,并將各個價格減去最后一個MidPriced的值,這樣可以使訓練集和驗證集分布更為接近,但是這樣造成的問題是,在量綱存在的情況下,最后一個MidPriced的值仍是有價值的,將它直接消去不合適。
第二種方式是完全消除量綱,將預測任務變為變化率的預測。即將所有與Price相關的變量都減去并除以最后一條數組的中間價。這樣就可以將量綱完全消除。
last_mp = x_cur[nGiven-1,0] for axis in [0,1,3,5]: # MidPrice, LastPrice, BidPrice1, AskPrice1x_cur[:,axis] -= last_mpx_cur[:,axis] /= last_mp ... y.append((sum(mid_price[k+nGiven:k+nGiven+nPredict])/nPredict-mid_price[k+nGiven-1])/mid_price[k+nGiven-1])Volume
Volume是指當日累計成交數量。在每組數據中,Volume的大小差別很大,這主要是因為每組數據開始的時間不同。開始,我試圖保留時間信息和Volume,來更好地利用Volume信息。事實上,雖然一天中的Volume是相關的,但是幾乎不可能通過時間信息來估計Volume,何況高頻交易簿的精度很高。因此,通過加入時間信息避免對Volume的歸一化是不可行的。
第二個嘗試是利用類似于對Prices的處理,將每組數據中的Volume減去該組數據中第一條數據的Volume。但這樣效果并不好,這是因為Volume在一組中是遞增的,將它們進行如上處理后仍是遞增的,利用普通的歸一化手段無法將它們映射在同一尺度上。
第三種嘗試是利用變化量。將每一組Volume數據減去上一條信息的Volume,將這個特征轉化為:3秒內累計成交數量。至此,每組/條數據的Volume便為同一分布了。此外,對于第一條數據,沒有辦法得知它與上一條數據(沒有給出)的差值,只能用均值填充。具體方法是利用迄“今”(這條數據)為止得到的Volume插值的均值。
for i in range(9,0,-1):x_cur[i,2]-=x_cur[i-1,2]volume_sum+=x_cur[i,2]volume_len+=1 x_cur[0,2]=volume_sum/volume_len時間信息
由于時間是遞增的,可以通過將它們映射在每一天(即,刪除日期,保留時間),然后進行預測。但是由于數據只有約120天,將它們映射在每一個時間點會導致這部分數據過于稀疏。因此,在保證每組數據中,每連續兩條數據的時間差值為3秒的情況下,可以直接將時間信息刪除。
此外,我發現在多種模型的實驗中,是否將時間信息加入并不會有太大的改變。
對于預測值的處理
在前文中提到過,將預測數值任務改變為預測變化率的任務。這樣做除了為了消除量綱,更主要的原因是加快收斂。若果不進行這樣的處理,對于CNN/DNN/RNN等基于神經網絡的模型,需要大約20epoch才能收斂到baseline RMSE=0.00155,但是如果采取變化率預測,只需要一個epoch就可以收斂到RMSE=0.00149.4
因此,如果不進行這樣的處理,將會極度增加訓練的時間,對調參和模型分析造成很大困難。
噪聲
模型探索
基于LSTM的RNN模型
這個模型是我所實現最優的模型,因此我將其以Kernel的形式發布在了Kaggle上。
采取這個模型的主要原因是基于LSTM的RNN模型具有很好的處理時間序列的能力。
遞歸神經網絡(RNN)
循環神經網絡(Recurrent Neural
Network,RNN)是一類具有短期記憶能力的神經網絡。在循環神經網絡中,神經元不但可以接受其它神經元的信息,也可以接受自身的信息,形成具有環路的網絡結構。和前饋神經網絡相比,循環神經網絡更加符合生物神經網絡的結構。循環神經網絡已經被廣泛應用在語音識別、語言模型以及自然語言生成等任務上。循環神經網絡的參數學習可以通過隨時間反向傳播算法 [Werbos, 1990] 來學習。隨時間反向傳播算法即按照時間的逆序將錯誤信息一步步地往前傳遞。當輸入序列比較長時,會存在梯度爆炸和消失問題[Bengio et al., 1994, Hochreiter and Schmidhuber, 1997, Hochreiteret al., 2001],也稱為長期依賴問題。為了解決這個問題,人們對循環神經網絡進行了很多的改進,其中最有效的改進方式引入門控機制。5
長短期記憶(LSTM)網絡
長短期記憶(long short-term memory,LSTM)網絡 [Gers et al., 2000, Hochreiter and Schmidhuber, 1997]是循環神經網絡的一個變體,可以有效地解 決簡單循環神經網絡的梯度爆炸或消失問題。 在公式(6.48)的基礎上,LSTM網絡主要改進在以下兩個方面: 新的內部狀態 LSTM網絡引入一個新的內部狀態(internal state)ctc_tct? 專門進行 線性的循環信息傳遞,同時(非線性)輸出信息給隱藏層的外部狀態hth_tht?。
在每個時刻t,LSTM網絡的內部狀態ctc_tct?記錄了到當前時刻為止的歷史信息。
循環神經網絡中的隱狀態h存儲了歷史信息,可以看作是一種記憶(memory)。在簡單循環網絡中,隱狀態每個時刻都會被重寫,因此可以看作是一種短 期記憶(short-term memory)。在神經網絡中,長期記憶(long-term memory)可以看作是網絡參數,隱含了從訓練數據中學到的經驗,并更新周期要遠遠慢于短期記憶。而在LSTM網絡中,記憶單元c可以在某個時刻捕捉到某個關鍵信息,并有能力將此關鍵信息保存一定的時間間隔。記憶單元c中保存信息的生命周期要長于短期記憶h,但又遠遠短于長期記憶,因此稱為長的短期記憶(long short-term memory)。5
模型實現
利用Keras框架,實現基于LSTM的RNN模型。具體結構為兩層LSTM網絡和兩層Dense層網絡。試圖利用LSTM網絡提取時間序列中的特征信息,并利用Dense層將提取出的特征信息進行回歸。
model = Sequential() model.add(LSTM(input_shape=(None, nFeature),activation='softsign',dropout=0.5, units=256, return_sequences=True)) model.add(LSTM(units=256,activation='softsign',dropout=0.5, return_sequences=False)) model.add(Dense(64,kernel_initializer="glorot_normal",activation='relu')) model.add(Dropout(0.5)) model.add(Dense(1,kernel_initializer="uniform",activation='linear')) model.compile(loss='mean_squared_error', optimizer='Adam')在這個較大的模型中,為了防止過擬合訓練集和驗證集,我采取了以下的措施:
- 在全連接(Dense)層和LSTM層中,加入Dropout。在訓練中,dropout掉近似50%的參數,可以將網絡模型減小至一半。在實驗發現,減小至該網絡一半的網絡更不容易出現過擬合的情況(下文中會詳細說明)。
- 提前結束訓練(Early-stopping)。在兩個相同的網絡中,改變MN(即nPredict)的值,得到如下的測試集RMSE~epochs。由此可見,Early-stopping是非常有必要的。
注:MN=20的同樣模型RMSE最好達到0.00148。
參數調整
我沒有進行大規模的網格搜索以確定最好的超參數,我主要調整了網絡的規模。基本想法是先選擇一個較大的網絡,訓練至過擬合,判斷其有足夠擬合數據的能力,然后減小網絡規模或進行正則化,消除過擬合以保留足夠的泛化能力。
大網絡(units = 256):
中網絡(units = 128):
小網絡(units = 64):
在實驗中發現,三個網絡均會產生過擬合的問題。但是很明顯小網絡的擬合能力不足(在更大的RSME開始出現過擬合),而大網絡的擬合能力極其嚴重。于是我選擇了中網絡規模的網絡——大網絡+50%dropout。
卷積神經網絡
采取這個模型的主要原因是卷積神經網絡模型可以通過共享(1,nFeature)(1,nFeature)(1,nFeature)卷積核減少參數,并將一組中每條數據進行同樣地處理。
卷積神經網絡
卷積神經網絡由一個或多個卷積層和頂端的全連通層(對應經典的神經網絡)組成,同時也包括關聯權重和池化層(pooling layer)。這一結構使得卷積神經網絡能夠利用輸入數據的二維結構。與其他深度學習結構相比,卷積神經網絡在圖像和語音識別方面能夠給出更好的結果。這一模型也可以使用反向傳播算法進行訓練。相比較其他深度、前饋神經網絡,卷積神經網絡需要考量的參數更少,使之成為一種頗具吸引力的深度學習結構。6
模型實現
利用Keras框架,實現卷積神經網絡模型。具體結構為兩層卷積網絡和三層Dense層網絡。其中兩層卷積網絡分別為1?71*71?7卷積核和10?110*110?1卷積核。
model = Sequential() model.add(Conv2D(input_shape=(10,7,1),filters = 256, kernel_size = (1,7), strides=(1, 1), padding='valid',activation='relu')) model.add(Dropout(0.5)) model.add(Conv2D(filters = 256, kernel_size = (10,1), strides=(1, 1), padding='valid',activation='relu')) model.add(Dropout(0.5)) model.add(Flatten()) model.add(Dense(512,kernel_initializer="glorot_normal",activation='relu')) model.add(Dropout(0.5)) model.add(Dense(256,kernel_initializer="glorot_normal",activation='relu')) model.add(Dropout(0.5)) model.add(Dense(1,kernel_initializer="uniform",activation='linear')) model.compile(loss='mean_squared_error', optimizer='Adam')全鏈接的神經網絡模型
神經網絡模型的主要優點是具有極強的近似能力:模型可以以任意精度擬合一切連續函數。同時,進行這個模型的嘗試,也可以判斷卷積神經網絡是否比樸素的全鏈接神經網絡模型更好。
神經網絡模型
人工神經網絡(英語:Artificial Neural Network,ANN),簡稱神經網絡(Neural Network,NN)或類神經網絡,在機器學習和認知科學領域,是一種模仿生物神經網絡(動物的中樞神經系統,特別是大腦)的結構和功能的數學模型或計算模型,用于對函數進行估計或近似。神經網絡由大量的人工神經元聯結進行計算。大多數情況下人工神經網絡能在外界信息的基礎上改變內部結構,是一種自適應系統,通俗的講就是具備學習功能。現代神經網絡是一種非線性統計性數據建模工具。7
模型實現
利用Keras框架,實現卷積神經網絡模型。具體結構為兩層卷積網絡和三層Dense層網絡。其中兩層卷積網絡分別為1?71*71?7卷積核和10?110*110?1卷積核。
model = Sequential() model.add(Flatten(input_shape=(10,7,1))) model.add(Dense(1024,kernel_initializer="glorot_normal",activation='relu')) model.add(Dropout(0.5)) model.add(Dense(512,kernel_initializer="glorot_normal",activation='relu')) model.add(Dropout(0.5)) model.add(Dense(256,kernel_initializer="glorot_normal",activation='relu')) model.add(Dropout(0.5)) model.add(Dense(1,kernel_initializer="uniform",activation='linear')) model.compile(loss='mean_squared_error', optimizer='Adam')利用XGBoost創建的模型
XGBoost介紹
XGBoost代表“Extreme Gradient Boosting”,其中術語“Gradient Boosting”源于弗里德曼的貪婪函數逼近:梯度增強機。8
XGBoost實質上是Gradient boosting Decision Tree(GBDT)的高效實現,如果使用最常用gbtree作為學習器,那么它基本相當于CART分類樹。
CART分類回歸樹是一種典型的二叉決策樹,可以做分類或者回歸。如果待預測結果是離散型數據,則CART生成分類決策樹;如果待預測結果是連續型數據,則CART生成回歸決策樹。數據對象的屬性特征為離散型或連續型,并不是區別分類樹與回歸樹的標準,例如表1中,數據對象xixi的屬性A、B為離散型或連續型,并是不區別分類樹與回歸樹的標準。作為分類決策樹時,待預測樣本落至某一葉子節點,則輸出該葉子節點中所有樣本所屬類別最多的那一類(即葉子節點中的樣本可能不是屬于同一個類別,則多數為主);作為回歸決策樹時,待預測樣本落至某一葉子節點,則輸出該葉子節點中所有樣本的均值。 9
模型實現
利用xgboost庫,實現XGB模型。
from xgboost import XGBRegressor from sklearn.model_selection import GridSearchCV cv_params = {'n_estimators': [600,800,1000,1200,1400,1600]} other_params = {'learning_rate': 0.1, 'n_estimators': 100, 'max_depth': 4, 'min_child_weight': 5, 'seed': 0,'subsample': 0.6, 'colsample_bytree': 0.9, 'gamma': 0.4, 'reg_alpha': 0, 'reg_lambda': 1} model = XGBRegressor(**other_params) optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params,scoring='neg_mean_squared_error', cv=3, verbose=3, n_jobs=5) optimized_GBM.fit(X_train_70, y_train)參數調整
利用上述GridSearchCV函數以及類似于Gibbs采樣算法的思想,逐步調整參數。具體方法為:首先設置每個參數的取值區間。然后選取某個參數,將其設置為取值區間中等間距的幾個點,進行訓練模型進行驗證,將最好的點設置為這個參數的值,然后選取其他參數,重復著一步,直到參數穩定。
但實驗中,由于過擬合情況嚴重,n_estimators越大會導致近似情況更好,但同時會導致模型的泛化能力降低。于是我通過提交結果,選定了n_estimator=200n\_estimator=200n_estimator=200。然后調整其他參數。
隨機回歸森林模型
簡單來說,隨機森林就是多個回歸樹的融合。
隨機森林的優勢在于
1.在沒有驗證數據集的時候,可以計算袋外預測誤差(生成樹時沒有用到的樣本點所對應的類別可由生成的樹估計,與其真實類別比較即可得到袋外預測)。
2.隨機森林可以計算變量的重要性。
3.計算不同數據點之間的距離,從而進行非監督分類。10
模型實現
利用sklearn庫提供的RandomForestRegressor。
from sklearn.ensemble import RandomForestRegressor clf = RandomForestRegressor(oob_score = True,max_depth = 20,min_samples_split=20,min_samples_leaf=10,n_estimators=20,random_state=0,verbose=3) clf.fit(X_train.reshape(-1,70),y_train.reshape((-1,)))參數調整
這個模型的參數基本是通過經驗+與XGB類似的調參方式確定的。高度參考了劉建平的這篇博文[scikit-learn隨機森林調參小結]。(https://www.cnblogs.com/pinard/p/6160412.html)
結果與討論
結果
| RNN(LSTM)* | 0.00147 |
| CNN | 0.00149 |
| DNN | 0.00148 |
| XGBoost | 0.00149 |
| Random Forest | 0.00150 |
| None(baseline) | 0.00155 |
*private leader board = 0.00140
討論:模型
- CNN vs DNN。 利用卷積沒有取得更好的結果,這很大原因是數據特征只有7維,沒有必要進行降維,因此CNN模型中的池化層(Pooling Layer)無法使用,降低了卷積模型能力。
- DNN vs RNN。RNN在epoch = 20開始lb = 0.00149,而DNN在較長區間[4,30+] epoches 中一直保持lb = 0.00148,這說明了RNN有更好的擬合時間序列的能力,但同樣有著更差的擬合能力,因此必須進行early-stopping防止過擬合。
- XGB。XGB有著很好的數據擬合能力,但由于調參需要較多的時間(每個模型擬合需要約40分鐘),而我沒有足夠的計算資源,只能放棄更細粒度的調參。
- Random Forest。和XGB類似,它們對于多維數據的處理可能會比神經網絡模型更好,但是在7維的數據中,表現并不如神經網絡模型。
討論:模型之外
在這場比賽中,我發現特征工程的重要性遠遠超過模型的選取以及調參。在最初的嘗試中,我只是簡單的進行了數據歸一化,得到的結果并不理想,很多次訓練的RNN模型有RMSE>0.00155的情況。在認真探索每個數據特征的意義并根據它們的意義進行數據處理后,采取的模型幾乎全部RMSE<0.00150。我想,思考特征的特點并思考如何利用是十分關鍵的。畢竟說白了,這些模型只是泛用函數擬合器。
未來的工作
- 豐富訂單簿信息。可以獲得AskPrice2, AskPrice3,… 以及AskVolumn2,AskVolumn3等豐富信息。
- 采取更多的輸入時間點。畢竟過去的數據是“免費”的,我們可以采用如過去一分鐘的數據進行預測。但可能結果和MN的情況一樣——再多的數據只是噪聲。
- 豐富數據集。用更多股票和更長時間的數據。RNN模型的泛化能力沒有被完全利用,我想通過更多的數據可以達到更好的效果。
- 嘗試XGboost的精細調參。
- 模型融合。如XGBoost+LightGBM+LSTM。
2018/12/31
@karmayh
維基百科:高頻交易 ??
通常情況下nGiven=10,nPredict=20nGiven = 10,nPredict = 20nGiven=10,nPredict=20。但是為了化簡模型以及降低噪聲,可以減少它們的值,即取10條中后nGiven條作為特征,將20條中前nPredict 條的中間價均值作為待預測量。 ??
特征工程中的「歸一化」有什么作用? ??
兩層LSTM+兩層Dense層,不采用Dropout等正則化措施。 ??
邱錫鵬:《神經網絡與深度學習》 ?? ??
Stanford UFLDL Tutorial ??
Wiki 人工神經網絡 ??
https://xgboost.readthedocs.io/ ??
決策樹之CART(分類回歸樹)詳解 ??
云社區 ??
總結
以上是生活随笔為你收集整理的[Kaggle比赛] 高频股价预测小结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 嵌入式系统设计(一)
- 下一篇: 内存攻略:SDRAM应用解析