距離上一篇文章,正好兩個星期。 這篇文章9月15日 16:30 開始寫。 可能幾個小時后就寫完了。
用一句粗俗的話說, “當你懷孕的時候,別人都知道你懷孕了, 但不知道你被日了多少回 ” ,紀念
這兩周的熬夜,熬夜。 因為某些原因,文章發布的有點倉促,本來應該再整理實驗和代碼比較合適。
文章都是兩個主要作用: 對自己的工作總結, 方便自己回顧和分享給有興趣的朋友。
不說廢話了, 進入正題。 本次的課題很簡單, 深度神經網絡(AI)來預測5日和22日后的走勢。 (22日
尚未整理, 不表)。
先上個工作流程圖, 也基本上是本文章的脈絡:
先說金融需求, 我很希望能預測股票5日后的情況或者22日后的情況。如果知道5日后能漲個10%,概率達到70%以上。
我想肯定會很受用。 因此我把5日后的收盤價格,作為我預測(分類)的目標。
在整個工作過程中, 搭建數據環境和數據整理清洗,耗費了我50%以上的時間。 而且還在我有有基本數據的基礎上。
搭建數據環境,就是根據我的目標,提出所需的訓練數據的需求。 然后整理基礎數據,形成相關數據及數據調用的接口。方便我
很快的獲得訓練數據。 我所需要的數據包括:股票代碼,日線數據,分紅數據,等其它。 整理后的數據包括各項均線。 細節不表。
數據整理清洗,說一下我的處理:
1. 所有參加訓練的數據均不包括分紅相關,感覺前復權后復權太復雜,且與實際不符,直接過濾。
2. 數據我只包含2017年1月到7月數據。 有人會說數據太少,且對股市來說周期不全,會直接影響最后的使用。這個等下稍微
再做補充說明。
3. 所有數據訓練前做歸一化處理, 包括價格,成交量,成交金額,漲幅,均線等。
4. 所有數據訓練前,做打亂處理。
5. 數據等量分布
(還有其它處理,想起來再做補充)
只有2017年的數據,我是這么想的, 上半年的基本面基本相同, 1~7月份的情況,應該可以適合 9,10月份。
股票是有周期性的, 快速上漲(瘋狂), 和快速下跌,與平時狀態是不一樣。 所以有意識的分階段預測有必要性。
自身原因: 機器性能有限,過量的數據訓練,時間消耗太大。
當然,全數據(全金融周期)的訓練,肯定會進行的。
說一下目標分類:
目標為 5日后的收盤價格, 預測數據是前21日的 o c h l, v ,amout, zf , 均線 等。
數據分為 5類 , 類0, 類1 , 類2, 類3, 類4
標准: ~-10 % , -10 %~-1 %, -1~2 %, 2 %~10 %, 10 %~
應該很好理解吧, 就是5日后收盤價 比今日收盤價低 10%以上為 0類, 如果是10%以上為 4類
接下去就是上主要代碼了,發布主要代碼。
建立LSTM神經網絡:
def buildlstm(): # expected input data shape: (batch_size, timesteps, data_dim)
model = Sequential() model.add(LSTM(nUnits, return_sequences=True, input_shape=(timesteps, data_dim))) model.add(Dropout(0.2)) model.add(LSTM(nUnits, return_sequences=True)) model.add(Dropout(0.2)) model.add(LSTM(nUnits)) # model.add(Dense(128, activation='relu'))
# model.add(Dropout(0.2))
# model.add(Dense(64, activation='relu'))
# model.add(Dropout(0.2))
model.add(Dense(32, activation='relu')) model.add(Dropout(0.2)) model.add(Dense(5, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy']) print model.summary() return model pass
主流程:
def run(): if (os.path.exists(destfile) == True): X = pd.read_hdf(destfile, 'data') y = pd.read_hdf(destfile, 'label') codedtlist = pd.read_hdf(destfile, 'codedt') X = np.array(X) y = np.array(y) codedtlist = np.array(codedtlist) else: X, y, codedtlist = makedata() df = pd.DataFrame(X) df.to_hdf(destfile, 'data') df = pd.DataFrame(y) df.to_hdf(destfile, 'label') df = pd.DataFrame(codedtlist) df.to_hdf(destfile, 'codedt') print 'read file:'
print codedtlist[:10] print y[:10] X, y, codedtlist = dataDoByYsite(X, y, codedtlist) X, y, codedtlist = dataDaluan(X, y, codedtlist) print 'ByYsite and Daluan :'
print codedtlist[:10] print y[:10] print len(X) maxLen = len(X) splen = maxLen * 90 / 100 X_train, X_test = X[:splen], X[splen:] y_train, y_test = y[:splen], y[splen:] codedt_train, codedt_test = codedtlist[:splen], codedtlist[splen:] model = buildlstm() TrainMode(X_train, y_train, model) TestMode(X_test, y_test, model, codedt=codedt_test) model.save_weights('Result/lstm_class5_2017_debug' + '_V1.2' + '.h5') pass
訓練預測前, 我們數據 類4, 是 5657 : 233000, 也就是說,你隨機選,大概選 50 個股票會中一個5天內漲 10%的。
很多人想着急看到結果, 想看結果的到文章最后看吧。
下面開始說分析調優, 我認為這是量化交易最重要的工作之一, 另外一個之一就是構建更復雜的神經網絡提高 准確率。
第一輪結果,我用全數據訓練,達到大概 0.5xxx 的ACC 。 然后我把測試數據和預測數據做了對比,結果概率高達多 80%.
然后我去看數據, 一看,發現有問題了。 因為數據基本集中在 類2, 所以在訓練的時候, AI( AI並不AI ), 就很聰明的
往類2 靠, 這樣能很快提高准確率。 其實對我們有意義的是類4的預測。
第二輪訓練測試, 我把所有分類,整成等量的,再做預測。 結果同樣達到 達到大概 0.5xxx 的ACC, 同樣能把測試數據和
預測數據做了對比,相似度最高的前20條, 高達90%。 嚇了我一跳, 還好我也是見過世面的人, 馬上穩定下來查問題。
因為我覺得這么高的成功率,我成神仙了, 或者說AI成神仙了。 所以說這數據是不符合現實的。
第三輪訓練測試, 等量分類訓練數據, 全量預測數據。
直接說重點 : 我把中獎率從 2% 提高到了 25%。 也就是 4個股票,其中有1個可以在未來5天內達到 10%。
實際與預測截圖:
相似度大於 0.50 分(滿分為1分) 准確率統計:
再做精細統計:
通俗的表達就是, 選相似度大於 95% 的 類4 預測, 就能達到 4個股票 有 1 個股票5天內能達到 10%。
有沒價值, 金融領域的朋友可能比較清楚。
為了防范風險, 再做一個風險統計:
說明: 統計這個的目的是, 萬一 我不是 4選1 ( 類4), 而是4選3了, 那我就成了另外的4類了。 踩地雷
的概率是多少呢? 這個表就是說明這個情況。
預測僅僅是量化的開始, 后面還有倉控,資金控制等。 一個好的入場會為后續管理提供更大的操作空間。
That is all ! 文章就此結束。
順便說一下接下想做點什么事情:
1. 預測實盤, 我搭建的環境是一個研究環境, 所以做實盤環境,還得熬夜。(實盤很重要, 是狗是貓,總得拿出來遛遛 )
2. 再研究, 在此數據基礎上, 再提升(方法一:提升網絡模型, 方法二:根據預測數據 二次刪選)
3. 我向往的強化學習
有對 金融程序化 和 深度學習結合有興趣的可以加群 , 個人群: 杭州程序化交易群 375129936