机器学习和深度学习已经成为量化对冲基金常用的新有效策略,并且能帮助他们最大化其利润。作为一名人工智能和金融爱好者,这是一个不一样的时代,因为这个时代将两个领域完美的结合起来。
本文将介绍如何使用神经网络预测股票市场,特别是股票(或指数)的价格。我们的目标是使用机器学习和神经网络的方法预测所选公司的股票价格。
对于股票预测的更高级的神经网络实现,请看我后面的文章。
金融中神经网络的需求
金融是高度非线性的,有时股票价格数据甚至可能看起来完全随机。传统的时间序列方法(如ARIMA和GARCH模型)仅在序列是静止时才有效,这是一个限制性假设,需要通过记录返回(或其他变换)对序列进行预处理。然而,主要问题出现在实时交易系统中实施这些模型,因为在添加新数据时无法保证稳定性。
我们通过使用不需要使用任何稳定性的神经网络来解决这个问题。此外,神经网络可以从本质上有效地找到数据之间的关系并使用它来预测(或分类)新数据。
典型的完整栈式数据科学项目具有以下工作流程:
数据采集 - 这为我们提供了特征
数据预处理 - 去除一些噪声并使数据具有可用性
设计和实现模型 - 我们选择神经网络
回测模型 - 任何交易策略中非常关键的一步
优化 - 找到合适的参数
我们的神经网络的输入数据是过去十天的股票价格数据,我们用它来预测第二天的股票价格数据。
1、数据采集
幸运的是,该项目所需的股票价格数据在雅虎财经中可以找到。可以使用他们的Python API,pdr.get_yahoo_data(ticker,start_date,end_date或直接从他们的网站获取)数据。
2、数据预处理
在我们的案例中,我们需要将数据分解为十个价格和第二天价格的训练组。我通过定义一个类预处理,将其分解为训练和测试数据并定义一个方法get_train(self,seq_len)来完成此操作,该方法将训练数据(输入和输出)作为numpy数组返回,给定特定长度的周期。完整代码如下:
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的方法。
3、设计并实现模型
神经网络模型
对于这个项目,我使用了两种神经网络模型:多层感知器(MLP)和长短期模型(LSTM)。我将简要介绍这些模型的工作原理。
MLP是最简单的神经网络形式,其中输入被馈送到模型中,并且使用特定权重,值通过隐藏层向前馈送以产生输出。学习来自于通过隐藏层反向传播以改变每个神经元之间权重的值。 MLP的一个问题是缺乏“记忆”。对先前的训练数据中发生的事情以及如何影响新的训练数据没有任何意义。在我们的模型中,一个数据集中的十天数据与另一个数据集之间的差异可能很重要(例如),但MLP无法分析这些关系。
这就是LSTM或一般的递归神经网络(RNN)的用武之地。RNN能够存储有关数据的某些信息供以后使用,这扩展了网络分析股票价格数据之间关系的复杂结构的能力。 RNN的一个问题是梯度消失问题。这是因为当层数增加时,梯度不断减小。 LSTM对此进行了改进,使其更有效。
实现模型
为了实现模型,我选择了keras,因为它使用了向网络添加层而不是一次定义整个网络。这使我们能够快速更改层数和层类型,这在优化网络时非常方便。
使用股票价格数据的一个重要步骤是正则化数据。这通常意味着你减去平均值并除以标准差,但在我们的情况下,我们希望能够在一段时间内在实时交易中使用该系统。因此,采用统计方法可能不是正则化数据的最准确方法。所以我只将整个数据除以200。虽然近似正则化看起来不靠谱,但它仍然有效地确保神经网络中的权重不会变得太大。
让我们从更简单的MLP开始。在keras中,这是通过在顺序模型上添加Dense层来完成的。完整代码如下:
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)还保持每参数学习速率,该每参数学习速率基于权重的最近梯度的平均值(例如,它的变化速度)进行调整。这意味着该算法在在线和非静止问题(例如噪声)上表现良好。
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.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重新构造数据至关重要。
4、回测模型
现在我们已经使用我们的训练数据拟合了我们的模型并使用我们的测试数据对其进行了评估,我们可以通过对新数据的模型进行回溯测试来进一步评估。回溯测试基本上是针对一段时间内的数据运行您的策略(或我的情况,预测算法),以查看算法的损益或准确性。这很简单
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模型,这是非常好的预测。它真实地向我们展示了神经网络和机器学习模型在建模参数之间复杂关系方面的稳健性。
5、优化 - 超参数调整
优化神经网络模型对于在样本外测试中提高模型的性能通常很重要。我没有在我的开源版本的项目中包含调优,因为我希望它对那些阅读它的人来说是一个挑战,并尝试优化模型以使其表现更好。对于那些不了解优化的人来说,它涉及找到最大化模型性能的超参数。您可以通过多种方式搜索这些理想的超参数,从网格搜索到随机方法。我强烈认为,学习优化模型可以将您的机器学习知识提升到新的水平。
结论
机器学习每天都在不断发展,每天都在开发新的方法。至关重要的是,我们不断更新我们的知识,为有趣的项目建立模型,如股票价格预测。虽然上面的LSTM模型不足以用于实时交易,但通过开发这种模型构建的基础可以帮助我们构建更好的模型,这些模型有一天可能会在我们的交易系统中使用。
人工智能与深度学习做量化请关注:AI量化(https://t.zsxq.com/RvfY37y) 星球限时免费,如需加入,请私信我获得免费邀请码!
零基础学习Python与深度学习应用请关注星球:Python与深度学习 https://t.zsxq.com/bUFayZ3
微信公众号:QTechAI
网友评论