【2万字干货】利用深度学习最新前沿预测股价走势

∥☆過路亽.° 提交于 2020-08-13 06:45:07

https://zhuanlan.zhihu.com/p/56509499

正文

在本篇文章中,我们将创建一个完整的程序来预测股票价格的变动。为此,我们将使用生成对抗性网络(GAN),其中LSTM是一种递归神经网络,它是生成器,而卷积神经网络CNN是鉴别器。我们使用LSTM的原因很明显,我们试图预测时间序列数据。为什么我们使用GAN,特别是CNN作为鉴别器?这是一个好问题,后面会有专门的部分介绍。

当然,我们将对每个步骤会进行详细的介绍,但最难的部分是GAN:成功训练GAN非常棘手的部分是获得正确的超参数集。因此,我们将使用贝叶斯优化(以及高斯过程)和深度强化学习(DRL)来决定何时以及如何改变GAN的超参数(探索与开发的两难境地)。在创建强化学习时,我们将使用该领域的最新进展,如Rainbow和PPO。

我们将使用许多不同类型的输入数据。随着股票的历史交易数据和技术指标,我们将使用NLP最新的进展(使用Bidirectional Embedding Representations from Transformers,BERT,一种传输学习NLP)创建情绪分析(作为基本分析的来源),傅里叶变换提取总体趋势方向,stacked autoencoders识别其他高级特征,寻找相关资产的特征组合,ARIMA用于股票函数的近似度等等,以便尽可能多地获取关于股票的信息、模式、相关性等。我们都知道,数据越多越好。预测股价走势是一项极其复杂的任务,所以我们对股票(从不同的角度)了解得越多,我们的变化就越大。

为了创建所有的神经网络,我们将使用MXNet及其高级API - Gluon,并在多个GPU上对它们进行训练。

注:尽管我们试图深入探讨数学和几乎所有算法和技术背后的机制,但本文并没有明确地解释机器/深度学习或股票市场是如何运作的。其目的是展示我们如何使用不同的技术和算法来准确预测股票价格的变动,并给出每一步使用每种技术的原因和有用性背后的理论基础。

简介

准确预测股票市场是一项复杂的任务,因为有数百万的事件和特定股票在特定方向上移动的前提条件。 因此,我们需要能够尽可能多地捕获这些前置条件。 我们还需要做出几个重要的假设:

1、市场不是100%随机,

2、历史可以重演

3、市场遵循人们的理性行为

4、市场是“完美的”

我们将尝试预测高盛的价格走势。 为此,我们将使用2010年1月1日至2018年12月31日的每日收盘价(训练集7年,测试集2年)。 我们将互换使用“Goldman Sachs”和“GS”这两个术语。后面可以换成A股的某个股票,大家可以尝试。

数据

我们需要了解是什么影响了GS的股价是上涨还是下跌。这是人们的整体想法。因此,我们需要整合尽可能多的信息(从不同的方面和角度来描述股票)。我们将使用每天的数据—1585天来训练各种算法(70%的数据),并预测接下来的680天(测试数据)。然后我们将把预测结果与测试数据进行比较。每种类型的数据(我们将其称为特征)将在后面的章节中进行更详细的解释,但是,作为一个高层次的概述,我们将使用的特性是:

1、相关资产

这些是其他资产(任何类型,不一定是股票,如大宗商品、外汇、指数,甚至是固定收益证券)。高盛这样的大公司显然不是“生活”在一个孤立的世界里——它依赖并与许多外部因素相互作用,包括竞争对手、客户、全球经济、地缘政治形势、财政和货币政策、资本获取渠道等。

2、技术指标

很多投资者遵循技术指标。我们将包括最受欢迎的指标作为独立的功能。其中7和21天移动平均线,指数移动平均线,动量,波林格带,MACD。

3、基本面分析

一个非常重要的特征,表明股票是否可能上涨或下跌。基本面分析有两个特点:

a. 使用10-K和10-Q报告分析公司业绩,分析ROE和P/E,等等。

b. 我们将为高盛和阅读每日新闻提取总情绪是否对高盛在那一天是正的,中性的,还是消极的(如得分从0到1)。像许多投资者密切阅读新闻和做出投资决策基于新闻,如果机会高盛今天是非常积极的消息明天股票飙升。关键的一点是,我们将在以后对每个特性执行特性重要性(这意味着它对GS的移动有多么具有指示性),并决定是否使用它。稍后将对此进行详细介绍。

为了建立准确的情绪预测,我们将使用NLP。我们将使用BERT -谷歌最近宣布的NLP方法来转移学习情绪分类股票新闻情绪提取。

4、傅立叶变换

随着每日收盘价,我们将创建傅立叶变换,以概括几个长期和短期趋势。使用这些变换,我们将消除许多噪音(随机漫步),并创建真实股票运动的近似。采用趋势逼近可以帮助LSTM网络更准确地选取预测趋势。

5、ARIMA

这是(在前神经网络时代)预测时间序列数据未来值最流行的技术之一。让我们看看它是否是一个重要的预测方法。

6、栈式自动编码器(Stacked autoencoders)

上面提到的大部分特性(基础分析、技术分析等)都是人们经过几十年的研究发现的。但也许我们错过了什么。也许有一些隐藏的相关性,人们无法理解,因为有大量的数据点、事件、资产、图表等。通过栈式自动编码器,我们可以利用计算机的力量,可能会发现影响股票走势的新类型的特征。即使我们无法理解人类语言中的这些特性,我们也将在GAN中使用它们。

7、深度无监督学习

期权定价中异常检测的深度无监督学习。我们还将使用一个新功能——每增加一个高盛股票90天看涨期权的价格。期权定价本身结合了大量数据。期权合约的价格取决于股票的未来价值(分析师也试图预测价格,以便得出最准确的看涨期权价格)。利用深度无监督学习,我们将试图发现每天定价中的异常。异常(例如价格的剧烈变化)可能表明一个事件可能对LSTM了解整个股票模式有用。

有这么多特性,接下来,我们需要执行几个重要步骤:

1、对数据的“质量”进行统计检查。如果我们创建的数据有缺陷,那么无论我们的算法多么复杂,结果都不会是正面的。检查包括确保数据不受异方差、多重共线性或序列相关性的影响。

2、创建特征的重要性。如果一个特征(如另一只股票或一个技术指标)对我们想预测的股票没有解释力,那么我们就没有必要在神经网络的训练中使用它。我们将使用XGBoost(eXtreme Gradient boost),一种增强树回归算法。

作为数据准备的最后一步,我们还将使用主成分分析(PCA)创建特征投资组合,以减少自编码器创建的特征的维数。

from utils import *

import time import numpy as np from mxnet import nd, autograd, gluon from mxnet.gluon import nn, rnn import mxnet as mx import datetime import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline from sklearn.decomposition import PCA import math from sklearn.preprocessing import MinMaxScaler from sklearn.metrics import mean_squared_error from sklearn.preprocessing import StandardScaler import xgboost as xgb from sklearn.metrics import accuracy_score import warnings warnings.filterwarnings("ignore") context = mx.cpu(); model_ctx=mx.cpu() mx.random.seed(1719) def parser(x): return datetime.datetime.strptime(x,'%Y-%m-%d') dataset_ex_df = pd.read_csv('data/panel_data_close.csv', header=0, parse_dates=[0], date_parser=parser) plt.figure(figsize=(14, 5), dpi=100) plt.plot(dataset_ex_df['Date'], dataset_ex_df['GS'], label='Goldman Sachs stock') plt.vlines(datetime.date(2016,4, 20), 0, 270, linestyles='--', colors='gray', label='Train/Test data cut-off') plt.xlabel('Date') plt.ylabel('USD') plt.title('Figure 2: Goldman Sachs stock price') plt.legend() plt.show()

虚线表示训练和测试数据之间的分离:

num_training_days = int(dataset_ex_df.shape[0]*.7) print('Number of training days: {}. Number of test days: {}.'.format(num_training_days, \ dataset_ex_df.shape[0]-num_training_days)) Number of training days: 1585. Number of test days: 680.

2.1 相关资产

如前所述,我们将使用其他资产作为特性,而不仅仅是GS。

那么,还有哪些资产会影响高盛的股价走势呢?对公司、业务线、竞争环境、依赖关系、供应商和客户类型等的良好理解对于选择正确的相关资产集非常重要:

1、首先是类似于GS的公司。我们将把摩根大通和摩根士丹利等公司加入数据集。

2、作为一家投资银行,高盛依赖于全球经济。糟糕或不稳定的经济意味着没有并购或IPO,可能限制自营交易收入。这就是我们将纳入全球经济指数的原因。此外,我们还将包括LIBOR(以美元和英镑计价)利率,因为分析师设定这些利率可能会考虑到经济中的冲击。

3、每日波动率指数(VIX)。

4、综合指数。例如纳斯达克和纽约证券交易所、FTSE100指数、Nikkei225指数、恒生指数和BSE Sensex指数。

5、货币。全球贸易经常反映在货币的走势上,因此我们将使用一篮子货币(如美元兑日元、英镑兑美元等)作为特征。

2.2 技术指标

我们已经讨论了什么是技术指标以及为什么使用它们,现在让我们直接跳到代码。我们将只为GS创建技术指标。

def get_technical_indicators(dataset): # Create 7 and 21 days Moving Average dataset['ma7'] = dataset['price'].rolling(window=7).mean() dataset['ma21'] = dataset['price'].rolling(window=21).mean() # Create MACD dataset['26ema'] = pd.ewma(dataset['price'], span=26) dataset['12ema'] = pd.ewma(dataset['price'], span=12) dataset['MACD'] = (dataset['12ema']-dataset['26ema']) # Create Bollinger Bands dataset['20sd'] = pd.stats.moments.rolling_std(dataset['price'],20) dataset['upper_band'] = dataset['ma21'] + (dataset['20sd']*2) dataset['lower_band'] = dataset['ma21'] - (dataset['20sd']*2) # Create Exponential moving average dataset['ema'] = dataset['price'].ewm(com=0.5).mean() # Create Momentum dataset['momentum'] = dataset['price']-1 return dataset

所以我们有每个交易日的技术指标(包括MACD、布林带等)。我们总共有12个技术指标。

部分指标

让我们来看看这些指标的最后400天的走势:

def plot_technical_indicators(dataset, last_days): plt.figure(figsize=(16, 10), dpi=100) shape_0 = dataset.shape[0] xmacd_ = shape_0-last_days dataset = dataset.iloc[-last_days:, :] x_ = range(3, dataset.shape[0]) x_ =list(dataset.index) # Plot first subplot plt.subplot(2, 1, 1) plt.plot(dataset['ma7'],label='MA 7', color='g',linestyle='--') plt.plot(dataset['price'],label='Closing Price', color='b') plt.plot(dataset['ma21'],label='MA 21', color='r',linestyle='--') plt.plot(dataset['upper_band'],label='Upper Band', color='c') plt.plot(dataset['lower_band'],label='Lower Band', color='c') plt.fill_between(x_, dataset['lower_band'], dataset['upper_band'], alpha=0.35) plt.title('Technical indicators for Goldman Sachs - last {} days.'.format(last_days)) plt.ylabel('USD') plt.legend() # Plot second subplot plt.subplot(2, 1, 2) plt.title('MACD') plt.plot(dataset['MACD'],label='MACD', linestyle='-.') plt.hlines(15, xmacd_, shape_0, colors='g', linestyles
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!