神經網路預測股票市場

機器學習和深度學習已經成為定量對衝基金為了實現最大化利潤而通常使用的新的有效策略。作為一個人工智慧和金融愛好者,這是一個令人興奮的訊息,因為神經網路結合了我感興趣的兩個領域。本文將介紹如何使用神經網路預測股票市場,特別是股票(或指數)的價格。這篇文章基於我GitHub上的 ofollow,noindex" target="_blank">python專案 ,在專案中可以找到完整的python程式碼以及如何執行這個程式。另外,要了解更多類似的內容,請檢視我自己的頁面: Engineer Quant 。
金融是高度非線性的而且有時股票價格資料甚至看起來完全隨機的。如ARIMA和GARCH模型這些傳統的時間序列方法,只有在序列是靜止的情況下才有效,這是一種需要對序列進行日誌返回(或其他轉換)預處理的限制假設。然而,在實時交易系統中實現這些模型時出現的主要問題是,隨著新資料的新增,無法保證序列的靜止。
這是通過使用不需要任何平穩性的神經網路來解決的。此外,神經網路天生就能有效地發現數據之間的關係,並利用它來預測(或分類)新資料。
一個典型的全堆疊資料科學專案有以下工作流程:
1、資料採集——這為我們提供了特徵;
2、資料預處理——這是使資料可用的一個常見且必要的步驟;
3、開發和實現模型-選擇神經網路的型別和引數;
4、回溯模型——在任何交易策略中都是非常關鍵的一步;
5、優化——找到合適的引數;
神經網路的輸入資料是過去十天的股價資料,我們用它來預測第二天的股價資料。
資料採集
幸運的是,這個專案所需的股價資料很容易通過使用它們的Python API,即get_yahoo_data(ticker, start_date, end_date)在Yahoo Finance中得到,或直接從它們的網站獲取。
資料預處理
在我們的例子中,我們需要將資料分解成過去10天股價和第二天價格的訓練集。我通過定義一個preprocessing類,將其分解為訓練和測試資料,並定義一個方法get_train(self, seq_len),該方法返回訓練資料(輸入和輸出)為numpy陣列,給定一個特定的視窗長度(在例子中是10)。完整程式碼如下:
def gen_train(self, seq_len): """ Generates training data :param seq_len: length of window :return: X_train and Y_train """ for i in range((len(self.stock_train)//seq_len)*seq_len - seq_len - 1): x = np.array(self.stock_train.iloc[i: i + seq_len, 1]) y = np.array([self.stock_train.iloc[i + seq_len + 1, 1]], np.float64) self.input_train.append(x) self.output_train.append(y) self.X_train = np.array(self.input_train) self.Y_train = np.array(self.output_train)
類似的,對於測試資料,我定義了一個方法返回X_test和Y_test。
神經網路模型
對於這個專案,我使用了兩種神經網路模型:多層感知器(MLP)和長短期記憶網路模型(LSTM)。我將簡要介紹這些模型的工作原理,但如果需要了解MLPs的工作原理,請查閱 本文 。
MLPs是最簡單的神經網路形式,從模型中輸入,並使用特定的權重,這些值通過隱藏層被向前輸入以產生輸出。通過隱藏層的反向傳播來改變每個神經元之間的權值並由此進行學習。MLPs的一個問題是缺乏“記憶”,不清楚在以前的訓練資料中發生了什麼,以及這將如何影響新的訓練資料。在我們的模型上下文中,一個數據集中十天股價的資料與另一個數據集中十天股價的資料之間的差異可能很重要(例如),但是MLPs沒有能力分析這些關係。
這就是LSTMs或遞迴神經網路(RNNs)出現的地方。RNNs能夠儲存關於資料的特定資訊以供以後使用,這擴充套件了網路分析股票價格資料之間複雜結構的能力RNNs的一個問題是梯度消失問題。這是由於當層數增加時,學習率被乘以若干次,這導致梯度繼續下降。LSTMs對此進行了優化,使其更加有效。
模型實現
為了實現這些模型,我選擇了keras,因為它向網路新增層而不是一次性定義整個網路。這使我們能夠快速改變層的數量和層的型別,這在優化網路時非常方便。
使用股票價格資料的一個重要步驟是對資料進行規一化。這通常意味著減去平均值除以標準差,但在例子中,我們想要在一段時間內的實時交易中使用這個系統,因此,利用統計矩可能不是使資料歸一化的最精確方法。因此,我只是將整個資料除以200(一個任意的數字,使一切都變得很小)。雖然歸一化似乎是憑空捏造出來的,但它仍然有效地確保神經網路中的權重不會變大。
讓我們從簡單的MLP開始。在keras中,這是通過建立序列模型並在上面新增全連線層來實現的。完整程式碼如下:
model = tf.keras.models.Sequential() model.add(tf.keras.layers.Dense(100, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(100, activation=tf.nn.relu)) model.add(tf.keras.layers.Dense(1, activation=tf.nn.relu)) model.compile(optimizer="adam", loss="mean_squared_error")
這就是keras的優雅之處。僅用這五行程式碼,我們就建立了一個帶有兩個隱藏層的MLP,每個層都有100個神經元。與傳統的隨機梯度下降法相比,Adam優化器是一種更有效的優化演算法,因此在機器學習領域越來越受歡迎。通過觀察隨機梯度下降法的另外兩個擴充套件的優點,我們可以更好地理解這些優點:
自適應梯度演算法(AdaGrad),保持每個引數的學習速率,提高了稀疏梯度問題(例如自然語言和計算機視覺問題)的效能。
均方根傳播(RMSProp)也保持每個引數的學習速率,這些學習速率是根據最近權重梯度的平均值(例如變化的速度)來調整的。這意味著該演算法可以很好地處理線上和非平穩問題(如噪聲)。
可以認為Adam結合了上述擴充套件的優點,這就是為什麼我選擇使用Adam作為我的優化器。
現在我們需要將模型與我們的訓練資料相匹配。同樣,keras使它變得簡單,只需要以下程式碼:
model.fit(X_train, Y_train, epochs=100)
一旦擬合了我們的模型,我們需要根據測試資料來評估它的效能,這是由下列程式碼完成
model.evaluate(X_test, Y_test)
你可以使用評估中的資訊來評估模型預測股票價格的能力。
對於LSTM模型,過程是類似的,因此我將貼出下面的程式碼以供你理解:
model = tf.keras.Sequential()
model.add(tf.keras.layers.LSTM(20, input_shape=(10, 1), return_sequences=True))
model.add(tf.keras.layers.LSTM(20))
model.compile(optimizer="adam", loss="mean_squared_error")
model.add(tf.keras.layers.Dense(1, activation=tf.nn.relu))
model.evaluate(X_test, Y_test)
model.fit(X_train, Y_train, epochs=50)
很重要的一點是keras要求輸入資料具有特定的由模型決定的維度,使用numpy重塑資料非常重要。
回測模型
現在,我們已經使用訓練資料對模型進行了擬合,並使用測試資料對其進行了評估,我們可以通過在新資料上對模型進行回測來進一步進行評估。由下列程式碼實現:
def back_test(strategy, seq_len, ticker, start_date, end_date, dim): """ A simple back test for a given date period :param strategy: the chosen strategy. Note to have already formed the model, and fitted with training data. :param seq_len: length of the days used for prediction :param ticker: company ticker :param start_date: starting date :type start_date: "YYYY-mm-dd" :param end_date: ending date :type end_date: "YYYY-mm-dd" :param dim: dimension required for strategy: 3dim for LSTM and 2dim for MLP :type dim: tuple :return: Percentage errors array that gives the errors for every test in the given date range """ data = pdr.get_data_yahoo(ticker, start_date, end_date) stock_data = data["Adj Close"] errors = [] for i in range((len(stock_data)//10)*10 - seq_len - 1): x = np.array(stock_data.iloc[i: i + seq_len, 1]).reshape(dim) / 200 y = np.array(stock_data.iloc[i + seq_len + 1, 1]) / 200 predict = strategy.predict(x) while predict == 0: predict = strategy.predict(x) error = (predict - y) / 100 errors.append(error) total_error = np.array(errors) print(f"Average error = {total_error.mean()}")
然而,這個回測是一個簡化版本,而不是一個完整的回測系統。對於完整的回測系統,還需要考慮倖存者偏差、前視偏誤、市場機制變化和交易成本等因素。因為這只是一個教育專案,一個簡單的測試就足夠了。但是,如果你對建立完整的回測系統有任何疑問,請隨時與我聯絡。
以下是我的LSTM模型在預測2月份蘋果股票價格時的表現:

對於一個沒有優化的簡單LSTM模型,這已經是一個很好的預測。它向我們展示了神經網路的魯棒性和機器學習模型在引數間複雜關係建模中的作用。
超引數除錯
在樣本外測試中,優化神經網路模型對提高模型的效能具有重要意義。我還沒有在專案的開放原始碼版本中包含調優,因為我希望它對那些閱讀它的人來說是一個挑戰,以便繼續進行並嘗試優化模型以使其效能更好。對於那些不知道優化的人來說,它涉及到找到最大化模型效能的超引數。有幾種方法可以搜尋這些理想超引數,從網格搜尋到隨機方法。我強烈地感覺到,學習優化模型可以把你的機器學習知識提升到一個新的水平,因此,希望你提出一個優化模型,超過我的表現,如上圖所示。
結論
機器學習是不斷更新的,每天都有新的方法被開發出來。我們必須不斷更新知識,最好的方法就是為一些有趣的專案建立模型,比如股票價格預測。雖然上面的LSTM模型還不足以用於實時交易,但是通過開發這樣一個模型所建立的基礎可以幫助我們建立更好的模型,有一天我們的交易系統可能會用到這些模型。
本文由 阿里云云棲社群 組織翻譯。
文章原標題《neural-networks-to-predict-the-market》
作者: Vivek Palaniappan 譯者:烏拉烏拉,審校:。
文章為簡譯,更為詳細的內容,請檢視 原文 。