在预测领域,经常使用目标变量的历史值来预测其未来的值。如果目标变量依赖于多个属性,并且每个属性都形成一个时间序列预测,如何利用这些属性来预测未来的值呢?例如,相对强弱指数(RSI)是判断股票价格趋势方向的一个好指标。在另一篇文章中,尝试使用RSI作为机器学习(ML)特征来预测股票价格回报。如果有多个指标会怎样呢?在本文中,将使用多个股市指标来展示如何使用多个ML特征进行时间序列预测。同时,也会解释超参数调整。最后,将从交易策略的角度评估结果。完整的代码可以在笔记本中找到。
将选择以下三个指标作为ML特征:(1) RSI,(2) MACD,和 (3) 布林带。
相对强度(RS)和相对强弱指数(RSI)可以从历史正价格差异(%)的移动平均(MA)除以负价格差异(%)的移动平均来计算。
RS = (MA of positive difference) / (MA of negative difference)
RSI = 100 - 100/(1+RS)
RSI振荡器 = 当前RSI值 - RSI的MA
将使用RSI的振荡器作为ML特征之一。
OsRSI(i,j) = (i-day RSI) - (j-day-MA of i-day-RSI)
移动平均收敛发散(MACD)可以通过减去12天和26天的指数移动平均(EMA)来计算。
MACD = (12-day EMA) - (26-day EMA)
为了简化,使用简单移动平均(MA)代替EMA,这样就不需要调整EMA的平滑因子。
SimpMACD(i,j) = (i-day-MA) - (j-day-MA)
布林带由基于过去i天的正态分布的两条线组成。 上带 = MA + 2 * (标准差) 下带 = MA - 2 * (标准差) 当前MA将与上述两条带进行比较,以指示是上升趋势还是下降趋势。 上带指标:UpBB(i,j) = (i-day-MA) - (j-day-上带) 下带指标:LowBB(i,j) = (i-day-MA) - (j-day-下带)
所有上述指标在计算移动平均(MA)时都有时间范围。与手动分析不同,不需要固定时间范围的值,因为可以在合理的值范围内循环时间范围。对于每个指标,通过循环指标形成矩阵,以“i”和“j”作为行数和列数,其中索引(“i”)的范围从day0到day1天,j = I + delta。
类似于另一篇文章,上述特征矩阵可以输入到卷积神经网络(CNN)进行模式识别。每个特征矩阵将作为CNN层的通道输入。因为有4个特征,CNN的通道输入是4。还使用当前天和之前(SEQLEN-1)天的矩阵形成序列矩阵作为CNN层的第四维输入。卷积的输出将被展平,然后输入到GRU层,最后输入到线性层以预测下一天的回报率。
以下是用Julia编写的模型代码,使用的是ML包Flux。
# 代码示例省略,因为实际代码较长,这里仅提供结构示意
在编码多个神经网络层时,匹配每层的输入形状和输出形状至关重要。卷积层(Conv)输入需要一个4维张量。前两个维度是输入图像的大小。因为使用特征矩阵作为输入,矩阵的形状成为第一和第二个维度的输入,即day1 - day0。CNN输入的第三个维度是通道数,每个指标特征是1个通道,所以CNN的通道数将是4。CNN输入的第四个维度是特征矩阵的时间步历史值,因此将是SEQLEN。
为了使ML训练收敛,使用收盘价回报率的5天移动平均作为目标变量。这是因为移动平均可以平滑价格变化的波动。选择正确的学习率值也很重要,否则训练将不会收敛。其他参数,如指标的时间范围、序列长度和隐藏状态的数量,也会影响收敛。如果训练不能收敛,预测将只是一条直线,如下图所示。通过使用超参数调整可以找到这些参数的合适值。
在Julia中,可以使用“Hyperopt”包轻松进行超参数调整,只需几行代码即可。首先,定义每个参数的调整范围:学习率(LR)和RMSProp的动量(MM)。CNN和GRU的隐藏状态数(Nh)。时间步的序列长度(SEQLEN)。指标矩阵的时间范围(day0和day0+delta)day1 = day0 + delta - 1。Hyperopt将随机循环上述参数的范围,然后找出目标成本的最小值,这是由目标函数(“MyObjective”)返回的值。目标函数使用指定的参数进行模型训练,并返回验证损失作为目标成本。从交易的角度来看,正确预测上升/下降趋势更为重要,因此在超参数优化中通过预测准确性调整了目标成本。