神經網絡預測股票市場

摘要: 股票跌跌不休?用神經網絡預測一波啊!

機器學習和深度學習已經成爲定量對衝基金爲了實現最大化利潤而一般使用的新的有效策略。做爲一我的工智能和金融愛好者,這是一個使人興奮的消息,由於神經網絡結合了我感興趣的兩個領域。本文將介紹如何使用神經網絡預測股票市場,特別是股票(或指數)的價格。這篇文章基於我GitHub上的python項目,在項目中能夠找到完整的python代碼以及如何運行這個程序。另外,要了解更多相似的內容,請查看我本身的頁面:Engineer Quantpython

金融是高度非線性的並且有時股票價格數據甚至看起來徹底隨機的。如ARIMA和GARCH模型這些傳統的時間序列方法,只有在序列是靜止的狀況下才有效,這是一種須要對序列進行日誌返回(或其餘轉換)預處理的限制假設。然而,在實時交易系統中實現這些模型時出現的主要問題是,隨着新數據的添加,沒法保證序列的靜止。git

這是經過使用不須要任何平穩性的神經網絡來解決的。此外,神經網絡天生就能有效地發現數據之間的關係,並利用它來預測(或分類)新數據。github

一個典型的全堆棧數據科學項目有如下工做流程:算法

一、數據採集——這爲咱們提供了特徵;數組

二、數據預處理——這是使數據可用的一個常見且必要的步驟;網絡

三、開發和實現模型-選擇神經網絡的類型和參數;app

四、回溯模型——在任何交易策略中都是很是關鍵的一步;機器學習

五、優化——找到合適的參數;性能

神經網絡的輸入數據是過去十天的股價數據,咱們用它來預測次日的股價數據。學習

數據採集

幸運的是,這個項目所需的股價數據很容易經過使用它們的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模型還不足以用於實時交易,可是經過開發這樣一個模型所創建的基礎能夠幫助咱們創建更好的模型,有一天咱們的交易系統可能會用到這些模型。

本文做者:【方向】

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索