8.5 金融特征 RNN 的应用不仅限于原始价格或收益率数据,还可以包括附加特征以改进它的预测性能。 以下 Python 代码向数据集中添加了典型的金融特征。 In [77]: data = generate_data() In [78]: data['r'] = np.log(data / data.shift(1)) In [79]: window = 20 data['mom'] = data['r'].rolling(window).mean() ➊ data['vol'] = data['r'].rolling(window).std() ➋ In [80]: data.dropna(inplace=True) ➊ 增加时间序列动量特征。 ➋ 增加滚动波动率特征。 8.5.1 估计 在估计任务中,样本外准确率可能会显著下降,这有些出人意料。换句话说,在这种特殊 情况下添加金融特征并没有观察到任何改进。 In [81]: split = int(len(data) * 0.8) In [82]: train = data.iloc[:split].copy() In [83]: mu, std = train.mean(), train.std() ➊ In [84]: train = (train - mu) / std ➋ In [85]: test = data.iloc[split:].copy() In [86]: test = (test - mu) / std ➌ In [87]: g = TimeseriesGenerator(train.values, train['r'].values, length=lags, batch_size=5) ➍ In [88]: set_seeds() model = create_rnn_model(hu=100, features=len(data.columns), layer='SimpleRNN')200 | 第 8 章 In [89]: %%time model.fit_generator(g, epochs=100, steps_per_epoch=10, verbose=False) ➍ CPU times: user 5.24 s, sys: 1.08 s, total: 6.32 s Wall time: 2.73 s Out[89]: In [90]: g_ = TimeseriesGenerator(test.values, test['r'].values, length=lags, batch_size=5) ➎ In [91]: y = model.predict(g_).flatten() ➎ In [92]: accuracy_score(np.sign(test['r'].iloc[lags:]), np.sign(y)) ➎ Out[92]: 0.37299771167048057 ➊ 计算训练数据的一阶矩和二阶矩。 ➋ 对训练数据应用高斯归一化。 ➌ 对测试数据应用高斯归一化(基于来自训练数据的统计数据)。 ➍ 在训练数据上拟合模型。 ➎ 在测试数据上测试模型。 8.5.2 分类 迄今为止的分析都在使用 Keras 中的 RNN 模型进行估计,以预测金融工具价格的未来方 向。我们所关心的问题可能会更好地直接转换为分类问题。以下 Python 代码会处理二进制 标签数据并直接预测价格变动的方向。这次我们使用 LSTM 层,即使对于相对少量的隐藏单 元和有限的几个训练轮数,样本外的准确率也相当高。该方法通过适当调整类权重来解决 类别不平衡的问题。在这种情况下,预测准确率非常高,约为 65%。 In [93]: set_seeds() model = create_rnn_model(hu=50, features=len(data.columns), layer='LSTM', algorithm='classification') ➊ In [94]: train_y = np.where(train['r'] > 0, 1, 0) ➋ In [95]: np.bincount(train_y) ➌ Out[95]: array([2374, 1142]) In [96]: def cw(a): c0, c1 = np.bincount(a) w0 = (1 / c0) * (len(a)) / 2 w1 = (1 / c1) * (len(a)) / 2 return {0: w0, 1: w1} In [97]: g = TimeseriesGenerator(train.values, train_y, length=lags, batch_size=5)循环神经网络 | 201 In [98]: %%time model.fit_generator(g, epochs=5, steps_per_epoch=10, verbose=False, class_weight=cw(train_y)) CPU times: user 1.25 s, sys: 159 ms, total: 1.41 s Wall time: 947 ms Out[98]: In [99]: test_y = np.where(test['r'] > 0, 1, 0) ➍ In [100]: g_ = TimeseriesGenerator(test.values, test_y, length=lags, batch_size=5) In [101]: y = np.where(model.predict(g_, batch_size=None) > 0.5, 1, 0).flatten() In [102]: np.bincount(y) Out[102]: array([492, 382]) In [103]: accuracy_score(test_y[lags:], y) Out[103]: 0.6498855835240275 ➊ 用于分类的 RNN 模型。 ➋ 二元训练标签。 ➌ 训练标签的组频率。 ➍ 二进制测试标签。 8.5.3 深度RNN 最后,本章将演示深度 RNN,它是具有多个隐藏层的 RNN。如同创造深度 DNN 一样简 单,唯一的要求是对于非最终隐藏层,参数 return_sequences 需要被设置为 True。以下用 于创建深度 RNN 的 Python 函数还添加了 Dropout 层以避免潜在的过拟合,预测准确率与 上一节中的预测准确率相当。 In [104]: from keras.layers import Dropout In [105]: def create_deep_rnn_model(hl=2, hu=100, layer='SimpleRNN', optimizer='rmsprop', features=1, dropout=False, rate=0.3, seed=100): if hl ➊ if layer == 'SimpleRNN': layer = SimpleRNN else: layer = LSTM model = Sequential() model.add(layer(hu, input_shape=(lags, features), return_sequences=True, )) ➋ if dropout: model.add(Dropout(rate, seed=seed)) ➌ for _ in range(2, hl): model.add(layer(hu, return_sequences=True)) if dropout: model.add(Dropout(rate, seed=seed)) ➌202 | 第 8 章 model.add(layer(hu)) ➍ model.add(Dense(1, activation='sigmoid')) ➎ model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy']) return model In [106]: set_seeds() model = create_deep_rnn_model( hl=2, hu=50, layer='SimpleRNN', features=len(data.columns), dropout=True, rate=0.3) ➊ In [107]: %%time model.fit_generator(g, epochs=200, steps_per_epoch=10, verbose=False, class_weight=cw(train_y)) CPU times: user 14.2 s, sys: 2.85 s, total: 17.1 s Wall time: 7.09 s Out[107]: In [108]: y = np.where(model.predict(g_, batch_size=None) > 0.5, 1, 0).flatten() In [109]: np.bincount(y) Out[109]: array([550, 324]) In [110]: accuracy_score(test_y[lags:], y) Out[110]: 0.6430205949656751 ➊ 保证最少有两个隐藏层。 ➋ 第一个隐藏层。 ➌ Dropout 层。 ➍ 最终隐藏层。 ➎ 建立分类模型。 8.6 结论 本章基于 Keras 库介绍了 RNN 模型,并说明了这种神经网络在金融时间序列数据中的应 用。从 Python 语言的角度看,使用 RNN 与使用 DNN 并无太大区别。一个主要区别是训 练数据和测试数据必须以序列形式呈现给各自的方法,但是通过应用 TimeseriesGenerator 函数可以轻松实现这一点,该函数使用的生成器对象会将序列数据转换为 Keras 中的 RNN 能处理的数据。 本章中的示例适用于金融价格序列和金融收益率序列。此外,我们还可以轻松添加金融特 征,比如时间序列动量。为模型创建提供的函数可以使用 SimpleRNN 层或 LSTM 层以及不同 的优化器等,还可以在浅层神经网络和深层神经网络的背景下对估计和分类问题进行建模。 在预测市场方向时,分类示例得到的样本外预测准确率相对较高,但对估计示例而言并没 有那么高,甚至可能很低。
Python进行金融特征的估计和分类,及如何构建深度RNN
最新推荐文章于 2024-07-24 10:53:21 发布