相关文章推荐
骑白马的毛巾  ·  【PW早报】阿里巴巴公布新“六脉神剑”:客户 ...·  6 月前    · 
喝醉的哑铃  ·  极米遥控器怎么调节音量·  7 月前    · 
俊秀的滑板  ·  关于评选2020年度复旦大学优秀博士后的通知·  7 月前    · 
越狱的煎饼果子  ·  南阳市公共资源交易平台·  1 年前    · 
满身肌肉的充值卡  ·  邓州几所高中排第几?网传一模过后豫西南的高中 ...·  1 年前    · 
Code  ›  神经网络在算法交易上的应用系列——时序预测+回测开发者社区
神经网络算法 时间序列 算法交易
https://cloud.tencent.com/developer/article/1395781
逃跑的键盘
2 年前
作者头像
量化投资与机器学习微信公众号
0 篇文章

神经网络在算法交易上的应用系列——时序预测+回测

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > 量化投资与机器学习 > 正文

神经网络在算法交易上的应用系列——时序预测+回测

发布 于 2019-02-26 16:33:12
1.4K 0
举报

本期作者:Alexandr Honchar

本期翻译:LIN | 公众号翻译部 这是公众号关于神经网络在金融领域特别是算法交易上的一个连载系列:

1、简单时间序列预测 (已发表) 2、正确的时间序列预测+回测 3、多变量时间序列预测 4、波动率预测和自定义损失函数 5、多任务和多模式学习 6、超参数优化 7、用神经网络增强传统策略 8、概率编程和Pyro进行预测

欢迎大家 关注公众号 查看此系列。本期我们从讲第二部分。

前言

在第二部分中,我们想描述更正确处理金融数据的方法。与前一篇文章相比,我们想展示不同的 数据标准化方法 ,并多 讨论些过拟合的问题 (在处理具有随机特性的数据时肯定会出现过拟合问题)。我们不会比较不同的架构(CNN, LSTM),你可以在之前的文章中查看它们。但即使只使用简单的前馈神经网络,我们也能看到一些重要的东西。

数据准备

让我们看看从2005年到今天苹果股价的历史时间序列。你可以很容易地从雅虎财经下载到csv格式的文件。在这个文件中数据的顺序是“颠倒”的——从2017年到2005年,所以我们需要先把它颠倒过来,如图:

data = pd.read_csv('./data/AAPL.csv')[::-1] 
close_price = data.ix[:, 'Adj Close'].tolist() 
plt.plot(close_price) 
plt.show()

正如我们在前一篇文章中所讨论的,我们可以用两种不同的方式来处理金融时间序列预测的问题(暂时忽略波动率预测、异常检测等有趣的话题):

我们将问题看作:

1、回归问题(试图准确预测收盘价或第二天的收益) 2、二元分类问题(价格将上升[1;0]或向下[0;1])

首先,我们准备训练数据。我们想根据N天前的信息来预测t+1的值。例如,有过去30天的收盘价数据,我们想预测明天,也就是第31天的价格是多少。我们将前90%的时间序列作为训练集(将其视为历史数据),后10%作为测试集来评估模型。

金融时间序列的主要问题是它们并不一定平稳,这意味着它们的统计特性(平均值、方差、最大值和最小值)随着时间的变化而变化,我们可以用ADF检验。 正因为这种不平稳性,我们不能使用经典的数据标准化方法,如MinMax或Z-score标准化 。

在我们的例子中,我们将在分类问题上做一点“弊”。 我们不需要预测某个确切的值,所以未来的期望值和方差对我们来说不是很有意义,我们只需要预测价格往上还是往下运动。 这就是为什么我们冒险用30天窗口内数据的均值和方差(z-score标准化)来标准化的原因,不妨假设在一个时间窗口内均值和方差不会改变很多,和未来的信息也没有关系。

X = [(np.array(x) — np.mean(x)) / np.std(x) for x in X]

对于回归问题,我们已经不能像这样作弊了,所以我们用pandas计算收益率(价格与昨天相比变化的百分比),它看起来是这样的:

close_price_diffs = close.price.pct_change()

正如我们所看到的,这个数据已经比较规范了,位于-0.5到0.5之间。

神经网络结构

正如我之前所说,在本文中,我们将只使用MLPs来展示在金融数据上过度拟合神经网络是多么容易(在前一篇文章中实际上存在过拟合),以及如何预防它。在CNNs或RNNs上扩展这些想法相对容易,但是理解这个概念要重要得多。和以前一样, 我们使用Keras作为神经网络原型的主要框架 。

我们的第一个网络是这样的:

model = Sequential() 
model.add(Dense(64, input_dim=30)) 
model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(2)) 
model.add(Activation('softmax'))

建议在每一个仿射或卷积层之后都使用批规范化方法和用 Leaky ReLU作为基本的激活函数,因为它已经成为了“工业标准”——它们有助于更快地训练网络。另一个好处是在训练中降低学习率,Keras用 ReduceLROnPlateau 函数做到了这一点:

reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.9, 
patience=5, min_lr=0.000001, verbose=1) 
model.compile(optimizer=opt,                
loss='categorical_crossentropy', metrics=['accuracy'])

我们是这样开始训练的:

history = model.fit(X_train, Y_train, nb_epoch = 50,  
batch_size = 128, verbose=1, validation_data=(X_test, Y_test),           
shuffle=True, callbacks=[reduce_lr])

这是我们将结果可视化的方法(让我们来判断loss和accuracy图)

plt.figure() 
plt.plot(history.history['loss']) plt.plot(history.history['val_loss']) 
plt.title('model loss') 
plt.ylabel('loss') 
plt.xlabel('epoch') 
plt.legend(['train', 'test'], loc='best')

重要时刻 :

在上一篇文章中,我们在训练网络时只迭代了10次——这是完全错误的。即使我们能看到55%的准确率,这并不意味着我们能比随机猜测更好地预测未来。最有可能的是,在我们的训练数据集中有55%的窗口数据具有一种行为(向上),45%的窗口数据具有另一种行为(向下)。我们的网络只是学习到了训练数据的这种分布而已。所以,最好可以让网络迭代学习20-50-100次,如果迭代次数太多的话无法使用提前停止策略(early stopping)。

分类

First network loss

First network accuracy

结果一点都不好,我们的测试loss根本没有改变,我们可以看到明显的过拟合,让我们建立一个更深的网络并尝试一下:

model = Sequential() 
model.add(Dense(64, input_dim=30)) 
model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(16)) 
model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(2)) model.add(Activation('softmax'))

以下是结果:

Second network loss

Second network accuracy

在这里,我们看到结果或多或少是相同的,甚至更糟…… 是时候 向模型添加一些正则化方法 了,首先在权重求和上添加L2范数(译者注:一种深度学习中常用的减少泛化误差技术):

model = Sequential() 
model.add(Dense(64, input_dim=30,                 
activity_regularizer=regularizers.l2(0.01))) model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(16,                 
activity_regularizer=regularizers.l2(0.01))) model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(2)) 
model.add(Activation('softmax'))

它表现得更好,但仍然不够好(即使损失在减少,但准确性很差)。这种情况在处理金融数据时经常发生——在这里有更好的解释:

https://www.quora.com/Loss-cross-entropy-is-decreasing-but-accuracy-remains-the-same-while-training-convolutional-neural-networks-How-can-it-happen

Regularized network loss

Regularized network accuracy

接下来我要做的事情看起来很奇怪,就是我们要对已经正则化的网络进行正则化,以0.5的概率加入dropout(在反向传播时随机忽略一些权重,以避免神经元之间的共适应关系造成的过拟合):

model = Sequential()  
model.add(Dense(64, input_dim=30,                 
activity_regularizer=regularizers.l2(0.01))) model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dropout(0.5)) 
model.add(Dense(16,                 
activity_regularizer=regularizers.l2(0.01))) model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(2)) 
model.add(Activation('softmax'))

Hardcore regularized network loss

Hardcore regularized network accuracy

正如我们所看到的,图表上看起来有点凑合了,我们可以报告大约58%的准确率,这比随机猜测好一点。

回归

对于回归,我们将使用收益率数据和前面搭建好的神经网络(但没有dropout),并检查回归的效果如何:

model = Sequential()
model.add(Dense(64, input_dim=30,                 
activity_regularizer=regularizers.l2(0.01))) model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(16,                 
activity_regularizer=regularizers.l2(0.01))) model.add(BatchNormalization()) 
model.add(LeakyReLU()) 
model.add(Dense(1)) 
model.add(Activation('linear'))

这是将预测结果可视化的代码:

pred = model.predict(np.array(X_test)) 
original = Y_test 
predicted = pred  
plt.plot(original, color='black', label = 'Original data') plt.plot(predicted, color='blue', label = 'Predicted data') plt.legend(loc='best') 
plt.title('Actual and predicted') 
plt.show()

它的效果很差,甚至不值得评论。在结论部分,我们将给出一些有助于解决回归问题的小提示。

回测

请想起通常我们为什么处理这些时间序列?我们想要建立一个交易系统,这意味着它必须做一些交易——买卖股票,希望能使投资组合增值。

有很多现成的解决方案可以测试你的策略(比如Quantopian),但我们决定学习它们是如何从内部构建的,这本详细介绍实现的方法:( 文末下载 )

文末下载

附随书代码下载

我们测试的策略非常简单:如果我们的网络说股价会上涨,我们就买入股票,然后在网络说股价会下跌时卖出,并等待下一个买入信号。逻辑是这样的:

if np.argmax(pred) == 0 and not self.long_market:
     self.long_market = True
     signal = SignalEvent(1, sym, dt, 'LONG', 1.0)
     self.events.put(signal)
     print pred, 'LONG'
if np.argmax(pred) == 1 and self.long_market:
 
推荐文章
骑白马的毛巾  ·  【PW早报】阿里巴巴公布新“六脉神剑”:客户第一、员工第二、股东第三-品玩
6 月前
喝醉的哑铃  ·  极米遥控器怎么调节音量
7 月前
俊秀的滑板  ·  关于评选2020年度复旦大学优秀博士后的通知
7 月前
越狱的煎饼果子  ·  南阳市公共资源交易平台
1 年前
满身肌肉的充值卡  ·  邓州几所高中排第几?网传一模过后豫西南的高中排行榜…_南阳
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号