机器学习:预测股市中的股价

专门针对Netologia的翻译Polina Kabirova改编剑桥大学工程师Vivek Palaniappan 的文章 ,内容涉及如何使用神经网络创建模型,该模型可以预测证券交易所的股价。

机器和深度学习已成为许多投资基金用来增加收入的新有效策略。 在本文中,我将解释神经网络如何帮助预测股市情况,例如股票价格(或指数)。 文本基于我用Python编写的项目 。 完整的代码和程序指南可在GitHub上找到。 阅读Medium Blog上的其他相关文章。

经济学中的神经网络


金融领域的变化不是线性的,有时似乎股价是完全随机形成的。 当时间序列固定时,传统的时间序列方法(例如ARIMA和GARCH模型)是有效的-其基本属性不会随时间变化。 这就要求该系列已经使用log returns进行了预处理,或者以不同的方式达到平稳状态。 但是,由于在添加新数据时不能保证平稳性,因此在实际交易系统中实施这些模型时会出现主要问题。

这个问题的解决方案可以是不需要平稳性的神经网络。 神经网络最初在查找数据之间的关系方面非常有效,并且能够基于它们预测(或分类)新数据。

通常,数据科学项目由以下操作组成:

  1. 数据收集-提供一组必要的属性。
  2. 在使用数据之前,数据预处理通常是一个令人恐惧但必不可少的步骤。
  3. 模型的开发和实现-神经网络的类型及其参数的选择。
  4. 回测模型(对历史数据进行测试)是任何交易策略中的关键步骤。
  5. 优化-搜索合适的参数。

我们神经网络的输入-最近10天的股价数据。 在他们的帮助下,我们将在第二天预测价格。

资料收集


幸运的是,该项目所需的数据可以在Yahoo Finance上找到。 可以使用其Python API pdr.get_yahoo_data(ticker, start_date, end_date)或直接从站点收集数据。

数据预处理


在我们的案例中,数据需要划分为包含10个过去的价格和第二天的价格的训练集。 为此,我定义了Preprocessing类,它将与训练和测试数据一起使用。 在类内部,我定义了get_train(self, seq_len) ,该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_testY_test

神经网络模型


在该项目中,我使用了两个神经网络模型:多层感知器(MLP)和长期短期模型(LSTM)。 我将简要讨论这些模型的工作原理。 在另一篇文章中了解有关MLP的更多信息,并在Jacob Aungiers中了解LSTM的工作。

MLP是神经网络的最简单形式。 输入数据属于模型,并使用一定的权重,这些值通过隐藏层传输以获得输出数据。 学习算法来自隐藏层的反向传播,以改变每个神经元的权重值。 该模型的问题是缺少“内存”。 不可能确定以前的数据是什么,以及它将如何影响新数据。 在我们的模型中,两个数据集的数据之间的10天差异可能很重要,但是MLP无法分析这种关系。

为此,请使用LSTM或递归神经网络(RNN)。 RNN存储某些数据信息以备后用,这有助于神经网络分析股价数据之间关系的复杂结构。 但是,使用RNN时,会出现渐变衰落的问题。 由于层数增加并且训练水平(小于1的值)倍增,因此梯度减小。 通过提高效率来解决LSTM问题。

模型实施


为了实现该模型,我使用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,每层包含一百个神经元。 现在介绍一下优化器。 Adam(自适应矩估计)方法正变得越来越流行-与随机梯度下降相比,这是一种更有效的优化算法。 随机梯度下降还有另外两个扩展-在它们的背景下,亚当的优势显而易见:

AdaGrad-保持设定的学习速度,当梯度不同时(例如,自然语言和计算机视觉问题),可以提高结果。

RMSProp-维持设定的训练速度,该速度可以根据最近的重量梯度的平均值(例如,其变化速度)而变化。 这意味着该算法很好地解决了非平稳问题(例如,噪声)。

亚当结合了这些扩展的优点,所以我选择了它。

现在,我们将模型拟合到我们的训练数据中。 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.add(tf.keras.layers.Dense(1, activation=tf.nn.relu)) model.compile(optimizer="adam", loss="mean_squared_error") model.fit(X_train, Y_train, epochs=50) model.evaluate(X_test, Y_test) 

请注意,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()}") 

但是,这是测试的简化版本。 对于完整的回测系统,应考虑诸如“生存偏差”,偏差(前瞻性偏差),变化的市场条件和交易成本等因素。 由于这只是一个教育项目,因此简单的回测就足够了。


我对2月份苹果股价的LSTM模型的预测

对于没有优化的简单LSTM模型,这是非常好的结果。 它表明神经网络和机器学习模型能够在参数之间建立复杂,稳定的联系。

超参数优化


测试后通常需要优化以改善模型结果。 我没有将其包含在开源版本中,因此读者可以尝试自己优化模型。 那些不知道如何优化的人将不得不找到可以改善模型性能的超参数。 查找超参数的方法有几种:从选择网格上的参数到随机方法。

我相信,随着模型的优化,机器学习领域的知识将达到一个新的水平。 尝试优化模型,使其比我的模型更好。 将结果与上图比较。

结论


机器学习在不断发展-每天都有新方法出现,因此不断学习非常重要。 最好的方法是创建有趣的项目,例如,建立预测股票价格的模型。 尽管我的LSTM模型还不足以用于实际交易,但这种模型的开发奠定了基础,将来可能会有所帮助。

来自编辑


有关该主题的网络学课程:

Source: https://habr.com/ru/post/zh-CN428227/


All Articles