前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用神经网络预测股票市场

用神经网络预测股票市场

作者头像
Python数据科学
发布2018-12-17 14:29:51
4.6K0
发布2018-12-17 14:29:51
举报
文章被收录于专栏:Python数据科学Python数据科学

作者:Vivek Palaniappan

编译:NumberOne

机器学习和深度学习已经成为定量对冲基金常用的新的有效策略,以最大化其利润。作为一名人工智能和金融爱好者,这是令人激动的消息,因为它结合了我自己感兴趣的两个领域。本文将介绍如何使用神经网络预测股票市场,特别是股票的价格。这篇文章的源码在我的GitHub中的python项目,如下:

源码: https://github.com/VivekPa/NeuralNetworkStocks

▍金融中的神经网络

金融是高度非线性的,有时股票价格数据甚至看起来完全随机,没有任何规律。传统的时间序列方法(如ARIMA和GARCH模型)仅在静止时才有效,这是一个限制性假设,需要通过记录返回,或其他变换,来对序列进行预处理。然而,主要的问题出现在实时交易系统中这些模型的实现,因为在添加新数据时无法保证平稳性。

这不需要使用任何平稳性的神经网络来进行对抗。此外,神经网络本质上在寻找数据之间的关系和使用它预测(或分类)新数据方面是有效的。

典型的完整数据科学项目可以参考以下工作流程:

  • 数据采集 - 提供了特征
  • 数据预处理 - 非常复杂,但是必要,为了使数据可用
  • 开发和模型实现 - 选择神经网络和参数的类型
  • 回测模型 - 任何交易策略中非常关键的一步
  • 优化 - 找到合适的参数

神经网络的输入数据是过去十天的股价数据,我们用它来预测第二天的股价数据。

▍数据采集

非常幸运,该项目所需的股票价格数据在雅虎财经中都是随时可用的。可以使用他们的Python API,或直接从他们的网站获取数据。

▍数据预处理

在我们的案例中,我们需要将数据分解为十个价格和第二天价格的训练集。通过定义一个类Preprocessing,将其分解为训练和测试数据并定义一个方法get_train(self,seq_len)来完成此操作,该方法将训练数据(输入和输出)作为numpy数组返回,给定特定长度的窗口(十在我们的情况下)。完整代码如下:

def gen_train(self, seq_len):
    """
    生成训练数据
    :param seq_len: 窗口长度
    :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)。下面将简要地介绍这些模型的工作原理,但是要了解MLP的工作原理,而对于LSTM,请查看Jakob Aungiers撰写的这篇优秀文章。相关链接如下:

MLP: https://medium.com/engineer-quant/multilayer-perceptron-4453615c4337

LSTM: https://www.altumintelligence.com/articles/a/Time-Series-Prediction-Using-LSTM-Deep-Neural-Networks

MLP是最简单的神经网络形式,其中输入将被喂到模型中,并且会使用特定权重,值通过隐藏层向前送入以产生输出。学习来自于通过隐藏层反向传播以改变每个神经元之间权重的值。 MLP的一个问题是缺乏“记忆”。对以前的训练数据中发生的事情没有任何意义,以及这可能会如何影响新的训练数据。在我们的模型的上下文中,一个数据集中的十天数据与另一个数据集之间的差异可能很重要(例如)但是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的优雅所在。只需要仅仅5行代码,我们就创建了一个带有两个隐藏层的MLP模型,每个层都有100个神经元。下面是关于优化器的一些个人看法。目前,Adam优化器在机器学习社区中越来越受欢迎,因为它与传统的随机梯度下降相比,它更为有效。我们可以观察随机梯度下降的另外两个扩展优点,这样可以最好地理解这些优点:

  • 自适应梯度算法(AdaGrad),保持参数学习速率,改善稀疏梯度问题的性能(例如自然语言和计算机视觉的问题)。
  • 均方根传播(RMSProp)也可以保持参数学习速率,该参数学习速率基于权重的最近梯度的平均值(例如,其变化的速度)进行调整。这意味着该算法在在线和非静止问题(例如噪声)上表现良好。

可以说,Adam是结合上述扩展的好处,这也就是为什么我选择使用Adam作为优化器的原因所在。

现在我们需要用数据去拟合出一个模型(训练一个模型)。同样,keras使它变得简单,只需1行代码:

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()}")

但是,这种回溯测试只是一个简化版本,并非一个完整的回测系统。对于完整的回测系统,你还需要考虑生存偏差,预测偏差,市场体制变化和交易成本等因素。本篇只是一个简单的教学项目,上面的回测就足够了。

下图展示了LSTM模型在2月份Apple股票价格的预测表现。

可以看到,对于还没有优化的简单LSTM模型,这是非常好的预测。这真实说明了神经网络和机器学习模型在建模参数之间复杂关系方面是非常稳健的。

▍超参数调整

对于优化神经网络模型,在样本外测试提高模型的性能通常很重要。我没有在开源版本的项目中使用调优,因为我希望能够给更多的人机会来调节参数,并尝试优化模型以使其表现更好。对于那些不了解优化的人来说,就需要找到最大化模型性能的超参数。有几种方法可以帮助搜索这些最优的超参数,比如网格搜索,随机方法。我认为,优化模型的学习可以将你的机器学习水平,因此,我提出了一个优于上图中性能的优化模型。

▍结论

机器学习真的是每天都在不断变化发展,每天都会有新的方法。但重要的是,我们不断更新知识,最好的方法是找到有趣的项目,去建模,如股票价格预测。虽然上面完成的LSTM模型还不足以用于实时交易,但通过练习实践这样的模型可以帮助我们构建更好的模型,这些模型很有可能在未来某一天为我们使用。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python数据科学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ▍金融中的神经网络
  • ▍数据采集
  • ▍数据预处理
  • ▍神经网络模型
  • ▍实现模型
  • ▍回测模型
  • ▍超参数调整
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档