技术 | 深度学习预测股票系列-2

上篇中,我们简单介绍了用深度学习预测股票,及“数据”类型。在该系列中我们将接着详细说明各“数据”类型/特征。

02│数据

在收集了大量有用的数据特征后,我们进行下面三个操作对数据进行处理:

对“数据质量”进行统计学检验: 如果我们创建的数据是有缺陷的,那么不管我们的算法模型有多成熟,得到的结果也不可能是对的。统计学检验要来确认数据无异方差性、无多重共线性、无序列相关性。

建立“特征重要性”: 一个数据类型/特征(譬如一个技术指标)如果对我们要预测的股票价格没有用处,那么在训练神经网络时我们就不需要考虑该特征。我们用XGBoost (eXtreme Gradient Boosting),一种“梯度提升决策树”算法来进行该步操作。

用PCA (Principal Component Analysis 主成分分析法)建立Eigen组合: 该步骤是前期数据准备的最后一步,用于降低从自编码中创建的数据特征的维度。下面我们来看一组代码示例:

print ('There are {} number of days

in the

dataset. '.format (dataset_ex_df.shap

e[0]))

output >>> There are 2265 number of

days in the dataset.

我们来看组Goldman Sachs 9年的股票价格图,分割线前为用于训练的股票数据,分割线后为用于测试验证的股票数据:

图1. Goldman Sachs (NYSE: GS) 2010年到2019年间9年股票价格图

01. 相关联资产

首先让我们来想想看,还有哪些和GS的股票相挂钩的其他资产,会影响到GS的股价走向? GS的股价某种程度上是其公司业绩好坏的一种反应,要更加全面地了解GS,我们还需要知道:GS的竞争对手、业务线、影响GS业务的因素、上游供应商和下游客户,这些信息对于我们抉择哪些是和GS股价挂钩的资产十分重要:

和GS类似的公司: JP Morgan、Morgan Stanley等;

影响GS业务的因素: 全球经济形势。GS是一家国际化投资银行,它的目的就是为了扶持公司上市,从中赚取佣金。较差或者波动性很大的经济形势意味着不会有M & A或者IPO机会,对于GS的业务将是很大的冲击。这就是为什么我们要考虑“全球经济指标”,同时也要考虑“LIBOR利率 (USP/GBP)”因素,还有其他FI证券类资产等因素。

每日恐慌指数(Daily volatility index –VIX): 全球经济形势会对GS的业务产生极大的影响,因此VIX是要被考虑进去的指标之一;

复合指数: NASDAQ (US), NYSE (US),FTSE100 (UK),Nikkei225 (JP),Hang Seng & BSE Sensex (APAC)指数;

货币: 全球贸易最直接的反应体现在货币的走向上,因此一揽子货币(USDJPY,GBPUSD等)是重要的特征之一;

我们选择了72类相关联资产,其日交易价格作为数据特征,为神经网络模型的输入数据。

2. 技术指标

这里直接附上创建GS股票技术指标的代码:

"""Function to create the

technical indicators"""

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

t['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'].ewa(com=0.5).mean9

)

#Create Momentum

dataset ['momentum'] =

dataset['price'] -1

return dataset

上述代码实现了包含MACD,Bollinger bands等的日均交易技术指标,建立了多达12种技术指标。

图2. Goldman Sachs过去400日的日均技术指标值

图2给出了Goldman Sachs过去400个交易日的技术指标图。

3. 基本面分析

这里我们会对跟GS有关的每日消息做情绪解析, 用BERT模型,将消息分类为对GS股价有“负面影响”、“中立”、“正面影响”。

MXNet/Gluon库已有训练好的BERT模型,我们只需实例化模型,加几层“全连接层”,到softmax,就能得到从0到1的分数值了,分数值越接近0,表面对股价的影响越负面。实现“实例化BERT模型”的代码如下:

import bert

最后,用Sigmoid激活函数对所有的每日消息给出一个介于0到1之间的均值,表明该日关于GS的新闻/消息对GS的股价影响,称之为当日的日均基本面分数,作为一类数据特征。

4. 傅里叶变换

对一个数学函数进行傅里叶变换,将得出一系列幅值和帧不同的正弦波,这组正弦波组合起来可以等同于该数学函数。

在股票预测领域,傅里叶变换被用来提取GS股价在全球和当地的趋势,代码如下:

""" Code to create the Fuorier trasfrom """data_FT = dataset_ex_df[['Date', 'GS']]

close_fft = np.fft.fft(np.asarray(data_FT['GS'].tolist()))

fft_df = pd.DataFrame({'fft':close_fft})

fft_df['absolute'] = fft_df['fft'].apply(lambda x: np.abs(x))

fft_df['angle'] = fft_df['fft'].apply(lambda x: np.angle(x))

plt.figure(figsize=(14, 7), dpi=100)

fft_list = np.asarray(fft_df['fft'].tolist())

for num_ in [3, 6, 9, 100]:

fft_list_m10= np.copy(fft_list); fft_list_m10[num_:-num_]=0

plt.plot(np.fft.ifft(fft_list_m10), label='Fourier transform with {} components'.format(num_))

plt.plot(data_FT['GS'], label='Real')

plt.xlabel('Days')

plt.ylabel('USD')

plt.title('Figure 3: Goldman Sachs (close) stock prices & Fourier transforms')

plt.legend()

plt.show()

图3.Goldman Sachs股价的傅里叶变换(蓝色:3个成分;橙色:6个成分;绿色:9个成分;红色:100个成分;紫色:真实曲线)

为了预测股价的长短期趋势,我们用含3个,6个和9个组分的傅里叶变换。

5. ARIMA

ARIMA是预测时间序列数据的绝佳工具。我们用ARIMA来对股票数据进行降噪处理,并期望从中间找到可解释的股价模式。

图5红线给出了用ARIMA预测的股价走向,蓝线为真实的股票趋势,预测股价几乎与真实股价重合,证明了ARIMA用于股票预测的高可行性。我们用ARIMA预测后得出的数据特征作为LSTM模型的输入,因其能给出足够多且质量足够好的数据特征和模式。

图5. 用ARIMA模型预测GS股票

6. 统计学检验

检验数据质量对于使用我们的模型准确预测股价的重要性不言而喻,主要体现在 “异方差性”、“多重共线性”、“序列相关性”三个方面:

异方差性(Heteroskedasticity): 条件性异方差的发生是当“误差项”(“回归法得出的预测值”与“真实值”之间的差项)取决于“数据”值时,如当数据点随着x轴变大时,误差项随之变大。

多重共线性(Multicollinearity): 指不同误差项之间相互影响。

序列相关性(Serial correlation): 指不同数据(特征)之间相互关联的现象。

7. 特征工程

加上所有的相关联资产、技术指标、基本面分析、傅里叶和ARIMA等数据类型(特征),我们共有2265天的数据,112种数据类型作为模型输入数据。

print('Total dataset has {} samples, and {} features.'.format(dataset_total_df.shape[0], dataset_total_df.shape[1]))

output >>> Total dataset has 2265 samples, and 112 features.

在获得了如此多的数据特征之后,我们要仔细考虑哪些数据特征对于预测股票趋势是有影响的,及影响的重要性,即“特征重要性”。如前面提到的,LIBOR/USD是我们要考虑的因素之一,因为LIBOR的变化意味着全球经济形势的变化,会影响到GS的表现和股价。但这仅仅是我们的猜测,LIBOR/USD对预测GS股价趋势到底有无影响,有多大的影响,还得通过验证才能得知。如何来验证“特征重要性”这件事情呢?在众多模型和方法中,我们选择XGBoost,因为它能给出归类和回归两类问题的最优解。

下面我们给出一个用XGBoost检验GS技术指标重要性的代码示例:

regressor = xgb.XGBRegressor(gamma=0.0,n_estimators=150,base_score=0.7,colsample_bytree=1,learning_rate=0.05)xgbModel = regressor.fit(X_train_FI,y_train_FI, eval_set = [(X_train_FI, y_train_FI), (X_test_FI, y_test_FI)], verbose=False)fig = plt.figure(figsize=(8,8))

plt.xticks(rotation='vertical')

plt.bar([i for i in range(len(xgbModel.feature_importances_))], xgbModel.feature_importances_.tolist(), tick_label=X_test_FI.columns)

plt.title('Figure 6: Feature importance of the technical indicators.')

plt.show()

图6. 用XGBoost给出GS股票技术指标的特征重要性

图6给出了用XGBoost得出的对预测GS股票趋势最有用的几个技术指标:MA7,MACD,及BB,这几个技术指标也是广大股民们在用技术面分析预测GS股价时最常用的,证明了用XGBoost验证“特征重要性”的可行性。对于其他的数据特征,我们也用XGBoost给出相应的“重要性”。

8. SAE提取更高阶的特征

我们用另一种更高性能的神经网络激活函数:GELU (Gaussian Error Linear Units) –高斯误差线性单元作为SAE的自编码器。

在SAE中,编码层的层数和解码层的层数数量是一样的。在模型训练时,我们用到所有编码层和解码层。但为了获得用SAE提取的更高阶的特征,而不仅仅是获得和输入的数据特征等同的输出数据特征,我们要跳过最后一层解码层(图9灰颜色的解码层),而选取倒数第二层解码层(图9紧靠着灰色层的黄色解码层),因其含有更高阶的特征值。

图9.用SAE提取更高阶的特征,灰色层为最后一层解码层,紧挨着灰色层的黄色层为包含高阶特征的解码层

用SAE又获得了112个更高阶的特征,如何将这些特征的维度(数据列的数量)降下来,而同时又保证其具有和原特征组一样的描述功能?这时候就要用PCA基于原数据特征组建立Eigen portfolio,达到上述目的。

本系列关于“数据”的科普全部完成,在下一个系列中我们继续讲“GANs”在预测GS股票上的应用!小伙伴们,来听下回分解吧。

 

 

近期热招:(点击标题,即可了解详情)
 

1. 金融科技招聘 | 技术专场

2. 招聘 | 机器学习(数据分析) -50万+奖金-对冲基金-上海

3. 招聘 | Java/C++架构师-60-90万/年-上海

4. 招聘 | 数据科学家 (NLP)-对冲基金-上海&北京

5. 招聘 | 数据开发工程师-40-48万+奖金-北京-对冲基金