欢迎光临散文网 会员登陆 & 注册

量化交易软件策略:使用指数平滑法进行时间序列预测(续)

2023-07-31 15:14 作者:bili_45793681098  | 我要投稿

简介

《使用指数平滑法进行时间序列预测》 [1] 一文对指数平滑模型进行了简要总结,举例阐明了一种用于优化模型参数的可能方案,并最终提出了基于呈线性衰减的增长模型开发的预测指标。本文体现了在一定程度上提升该预测指标准确性的一次尝试。

预测货币报价甚至提前三四步进行极为可靠的预测,实施起来都比较复杂。然而,在本系列的前一篇文章中,赫兹量化 会提前 12 步进行预测,并清楚认识到无法在如此长的范围内获得满意结果。因此,置信区间最窄的前几步预测应给予最大关注。

提前 10 到 12 步进行预测主要是为了说明不同模型与预测方法的行为特征。在任何情况下,针对任何范围获得的预测准确度都可以利用置信区间限制进行评估。本文的首要目的就是说明一些有助于升级文章 [1] 中所述指标的方法。

由于前文已经介绍了查找若干变量函数最小值(该值用于生成指标之用)的相应算法,这里就不再赘述。为了简便起见,我们尽量减少理论方面的内容。

1. 初始指标

IndicatorES.mq5 指标(参见文章 [1])会被用作一个起始点。

为了编译指标,赫兹量化需要用到同一目录下的 IndicatorES.mq5、CIndicatorES.mqh 和 PowellsMethod.mqh。这些文件都可以在本文末尾的 files2.zip 档案中找到。

赫兹量化来刷新定义了该指标制定过程中所用指数平滑模型的方程,即呈线性衰减的增长模型。







其中:


- 序列级别的平滑参数,[0,1];


- 趋势的平滑参数,[0,1];


– 衰减参数,[0,1];


– 观测到

后,于时间 t 处计算得出的平滑序列级别;


– 于时间 t 处计算得出的平滑加法趋势;


– 时间 t 处的序列值;


– 所做预测的提前步数;


– 于时间 t 处所做的提前 m 步预测;


– 于时间 t 处所做的提前一步预测误差,

该指标唯一的输入参数就是用于确定区间长度的值,将根据该值来优化模型参数以及选择初始值(研究区间)。确定某给定区间模型参数的最优值及所需的计算后,就会生成预测、置信区间以及与提前一步预测相对应的线条。每个新柱处的参数都会被优化,并会做出相应预测。

由于要更新所述指标,所以我们会利用本文末尾处 Files2.zip 档案中的测试序列来评估变化结果。档案目录 \Dataset2 中的文件包含已保存的 EURUSD、USDCHF、USDJPY 报价及美元指数 DXY。其中每一个都针对 M1、H1 与 D1 三种时间框架予以提供。在文件中保存 "open" 值时,应让最新值位于文件末尾。每个文件都包含 1200 个元素。

预测误差将通过计算“平均绝对百分比误差” (MAPE) 系数进行评估



赫兹量化将 12 个测试序列中的每个序列都划分为 50 个重叠区间,每个区间都包含 80 个元素,并计算其中每个元素的 MAPE 值。通过这种方式获取的评估平均值,将会被用作与对比指标相关的一个预测误差指数。提前两步和三步预测误差的 MAPE 值,也以同样的方式进行计算。此类平均估算值还会进一步表示如下:

  • MAPE1 – 提前一步预测误差的平均估算值;

  • MAPE2 – 提前两步预测误差的平均估算值;

  • MAPE3 – 提前三步预测误差的平均估算值;

  • MAPE1-3 – 平均值 (MAPE1+MAPE2+MAPE3)/3。

计算 MAPE 值时,每一步都会用绝对预测误差值除以序列的当前值。为在此过程中避免被零除或得到负值,要求输入序列仅取非零正值,就像在本例中一样。

初始指标的估算值如表 1 所示。

MAPE1 MAPE2 MAPE3 MAPE1-3 IndicatorES 0.2099 0.2925 0.3564 0.2863

表 1. 初始指标预测误差估算值

表 1 中所示数据是利用 Errors_IndicatorES.mq5 脚本(来自本文末尾的 files2.zip 档案)获取的。要编译并运行此脚本,则 CIndicatorES.mqh 和 PowellsMethod.mqh 必须与 Errors_IndicatorES.mq5 同处一个目录下,且输入序列位于 Files\Dataset2\ 目录下。

获取预测误差的初始估算值后,现在就可以继续升级研究中的指标了。


2. 优化准则

《使用指数平滑法进行时间序列预测》文中所述的初始指标中的模型参数,均通过提前一步对预测误差平方和进行最小化的方法进行确定。针对提前一步预测进行优化的模型参数可能不会产生提前多步预测的最小误差,这似乎比较符合逻辑。当然,最好能够将提前 10 到 12 步预测的误差降至最低,但要在给定的研究序列范围内获得满意的预测结果,却是不可能完成的任务。

从现实来看,在优化模型参数时,赫兹量化会使用提前一、二、三步预测误差的平方和,将其用于指标的第一次升级。误差的平均数量可能有望在预测前三步的范围内实现某种程度上的降低。

显而易见,初始指标的此类升级并不涉及其主体结构原理,而只是更改参数优化准则而已。因此,赫兹量化不能指望预测精确度能提高数倍,尽管提前两步和三步预测误差的数量应当下降一点。

为了对比预测结果,赫兹量化创建了 CMod1 类,其类似于前文提到的带有修改目标函数 func 的 CIndicatorES 类。

初始 CIndicatorES 类的 func 函数:

double CIndicatorES::func(const double &p[])  {  int i;  double s,t,alp,gam,phi,k1,k2,k3,e,sse,ae,pt;    s=p[0]; t=p[1]; alp=p[2]; gam=p[3]; phi=p[4]; k1=1; k2=1; k3=1;  if     (alp>0.95){k1+=(alp-0.95)*200; alp=0.95;}       // Alpha  > 0.95  else if(alp<0.05){k1+=(0.05-alp)*200; alp=0.05;}       // Alpha  < 0.05  if     (gam>0.95){k2+=(gam-0.95)*200; gam=0.95;}      // Gamma  > 0.95  else if(gam<0.05){k2+=(0.05-gam)*200; gam=0.05;}       // Gamma  < 0.05  if     (phi>1.0 ){k3+=(phi-1.0 )*200; phi=1.0; }      // Phi    > 1.0  else if(phi<0.05){k3+=(0.05-phi)*200; phi=0.05;}       // Phi    < 0.05  sse=0;  for(i=0;i<Dlen;i++)    {    e=Dat[i]-(s+phi*t); sse+=e*e;    ae=alp*e; pt=phi*t; s=s+pt+ae; t=pt+gam*ae;    }  return(Dlen*MathLog(k1*k2*k3*sse));  }

经过一些修改之后,func 函数的现状如下:

double CMod1::func(const double &p[])  {  int i;  double s,t,alp,gam,phi,k1,k2,k3,e,err,ae,pt,phi2,phi3,a;    s=p[0]; t=p[1]; alp=p[2]; gam=p[3]; phi=p[4]; k1=1; k2=1; k3=1;  if     (alp>0.95){k1+=(alp-0.95)*200; alp=0.95;        // Alpha   > 0.95  else if(alp<0.05){k1+=(0.05-alp)*200; alp=0.05;}       // Alpha   < 0.05  if     (gam>0.95){k2+=(gam-0.95)*200; gam=0.95;}      // Gamma   > 0.95  else if(gam<0.05){k2+=(0.05-gam)*200; gam=0.05;}       // Gamma   < 0.05  if     (phi>1.0 ){k3+=(phi-1.0 )*200; phi=1.0; }      // Phi     > 1.0  else if(phi<0.05){k3+=(0.05-phi)*200; phi=0.05;}       // Phi     < 0.05  phi2=phi+phi*phi; phi3=phi2+phi*phi*phi;  err=0;  for(i=0;i<Dlen-2;i++)    {    e=Dat[i]-(s+phi*t); err+=e*e;    a=Dat[i+1]-(s+phi2*t); err+=a*a;    a=Dat[i+2]-(s+phi3*t); err+=a*a;    ae=alp*e; pt=phi*t; s=s+pt+ae; t=pt+gam*ae;    }  e=Dat[Dlen-2]-(s+phi*t); err+=e*e;  a=Dat[Dlen-1]-(s+phi2*t); err+=a*a;  ae=alp*e; pt=phi*t; s=s+pt+ae; t=pt+gam*ae;  a=Dat[Dlen-1]-(s+phi*t); err+=a*a;  return(k1*k2*k3*err);  }

现在,计算该对象函数时就会用到提前一、二、三步预测误差的平方和。

而且,基于此类开发的 Errors_Mod1.mq5 脚本允许估算预测误差,这类似于曾经提到过的 Errors_IndicatorES.mq5 脚本功能。CMod1.mqh 与 Errors_Mod1.mq5 均位于本文末尾的 files2.zip 档案中。

表 2 显示了初始及升级版的预测误差估算值。

MAPE1 MAPE2 MAPE3 MAPE1-3 IndicatorES 0.2099 0.2925 0.3564 0.2863 Mod1 0.2144 0.2898 0.3486 0.2842

表 2. 预测误差估算值的对比

可以看出,误差系数 MAPE2 和 MAPE3 以及平均值 MAPE1-3 确实要比研究中的序列略低一些。所以,我们保存了这一版本,并继续进一步修改我们的指标。


3. 平滑过程中的参数调整

根据输入序列的当前值更改平滑参数,这一想法并不新颖,也并非原创,其目的是希望能调整平滑系数,以便其在给定的输入序列性质发生变化时仍保持最佳状态。调整平滑系数的一些方式会在参考文献 [2]、[3] 中进行说明。

为了进一步升级该指标,赫兹量化会使用平滑系数呈动态变化的模型,希望使用自适应指数平滑模型来实现指标预测精确度的提升。

遗憾的是,如果在预测算法中使用该模型,则大多数自适应方法都无法始终获得理想结果。选取适当的自适应方法可能过于繁琐且耗时,因此在本例中我们会利用参考文献 [4] 中提供的研究结果,并采用文章 [5] 中讲到的“平滑转换的指数平滑” (STES)。

由于指定文章中已明确说明该方法的实质内容,所以我们暂时无需理会,而只需直接转到模型的方程(请参阅指定文章的开头),同时考虑到自适应平滑系数的使用即可。








现在可以看出,平滑系数 alpha 的值会在算法中的每一步计算得出,具体取决于平方预测误差。b 与 g 系数的值会确定预测误差对 alpha 值所造成的影响。而在所有其他方面,所用模型的方程仍保留未变。与 STES 法使用相关的更多详情请参见文章 [6]。

在之前的版本中,赫兹量化必须确定整个给定序列 alpha 系数的最优值,而现在则有 b 和 g 两个自适应系数可待优化,且 alpha 值会在平滑输入序列的过程中被动态确定。

该升级以 CMod2 类的形式进行。重大变化(像上次一样)主要与 func 函数相关,其现状如下所示。

double CMod2::func(const double &p[])  {  int i;  double s,t,alp,gam,phi,sb,sg,k1,k2,e,err,ae,pt,phi2,phi3,a;    s=p[0]; t=p[1]; gam=p[2]; phi=p[3]; sb=p[4]; sg=p[5]; k1=1; k2=1;  if     (gam>0.95){k1+=(gam-0.95)*200; gam=0.95;}        // Gamma   > 0.95  else if(gam<0.05){k1+=(0.05-gam)*200; gam=0.05;}        // Gamma   < 0.05  if     (phi>1.0 ){k2+=(phi-1.0 )*200; phi=1.0; }       // Phi     > 1.0  else if(phi<0.05){k2+=(0.05-phi)*200; phi=0.05;}        // Phi     < 0.05  phi2=phi+phi*phi; phi3=phi2+phi*phi*phi;  err=0;  for(i=0;i<Dlen-2;i++)    {    e=Dat[i]-(s+phi*t); err+=e*e;    a=Dat[i+1]-(s+phi2*t); err+=a*a;    a=Dat[i+2]-(s+phi3*t); err+=a*a;    alp=0.05+0.9/(1+MathExp(sb+sg*e*e));                  // 0.05 < Alpha < 0.95    ae=alp*e; pt=phi*t; s=s+pt+ae; t=pt+gam*ae;    }  e=Dat[Dlen-2]-(s+phi*t); err+=e*e;  a=Dat[Dlen-1]-(s+phi2*t); err+=a*a;  alp=0.05+0.9/(1+MathExp(sb+sg*e*e));                    // 0.05 < Alpha < 0.95  ae=alp*e; pt=phi*t; s=s+pt+ae; t=pt+gam*ae;  a=Dat[Dlen-1]-(s+phi*t); err+=a*a;  return(k1*k2*err);  }

开发此函数时,定义 alpha 系数值的方程也会稍做修改。这样做是为了分别在 0.05 与 0.95 处对最大与最小允许值进行限制。

为了像之前一样评估预测错误,要基于 CMod2 类来编写 Errors_Mod2.mq5 脚本。CMod2.mqh 与 Errors_Mod2.mq5 均位于本文末尾的 files2.zip 档案中。

脚本结果如表 3 所示。

MAPE1 MAPE2 MAPE3 MAPE1-3 IndicatorES 0.2099 0.2925 0.3564 0.2863 Mod1 0.2144 0.2898 0.3486 0.2842 Mod2 0.2145 0.2832 0.3413 0.2797

表 3. 预测误差估算值的对比

如表 3 所示,使用自适应平滑系数后一般都允许进一步略微减少测试序列的预测误差。因此,在两次升级之后,我们便设法将误差系数 MAPE1-3 降低了约两个百分点。

尽管升级结果不太明显,但我们仍坚持将其作为最终版本,并将进一步的升级留到本文之外再行讨论。在下一步中尝试使用博克斯-卡克斯转换会很不错。该转换方法主要用于让初始序列分布接近正态分布。

在本例中可以使用该转换方法来转换初始序列、计算预测并反向转换预测。这种方法用到了转换系数,其选择应以结果预测误差最小为原则。在预测序列中使用博克斯-卡克斯转换的示例请参见文章 [7]。


4. 预测置信区间

初始 IndicatorES.mq5 指标(前文提到过)中的预测置信区间,是根据选定指数平滑模型 [8] 的解析式计算得出的。本例所做的变更已导致研究中模型发生了变化。由于存在变量平滑系数,便不适合再使用上述分析表达式来估算置信区间了。

之前使用的分析表达式均基于预测误差为对称正态分布这一假设推算得出,而这是更改置信区间评估法的又一原因。由于我们的序列类未能满足这些要求,所以预测误差分布可能并非正态或对称的。

估算初始指标中的置信区间时,提前一步预测误差方差应从输入序列的开头开始计算,接下来再利用解析式并根据获得的提前一步预测误差方差值来计算提前两步、三步及更多步预测的方差。

为避免使用解析式,还可采用一种简单方法,即直接通过输入序列和提前一步预测方差来计算提前两步、三步及更多步预测的方差。但该方法存在一个明显缺陷:在短输入序列中,置信区间估算值会相当分散,而且在计算方差和均方误差时还不允许解除对于预期误差正态性的限制。

在使用非参数自助法(重新采样) [9] 的过程中可以发现针对这种情况的解决方案。这一想法的核心内容非常简单:如果以随机方式(均匀分布)替换通过初始序列进行采样的做法,则如此生成的伪序列的分布情况会与初始序列的分布情况相同。

假设我们有一个 N 成员的输入序列;通过在 [0,N-1] 的范围内生成一个均匀分布的伪随机序列,并在由初始数组采样时将这些值作为索引,就可以生成一个明显长于初始序列的伪序列。也就是说,生成序列的分布情况会与初始序列的分布情况相同(几乎相同)。

估算置信区间的自助法流程如下所示:

  1. 通过指数平滑模型中的输入序列来确定该模型的参数、系数和自适应系数的最优初始值,而该模型是在修改后得出的。最优参数还是像以前一样,通过采用使用鲍威尔搜索法的算法进行确定;

  2. 利用确定的最优模型参数从头到尾过一遍初始序列,并创建一个由提前一步预测误差组成的数组。数组元素的数量将等于输入序列长度 N;

  3. 从误差数组的每个元素中减去其中的平均值以调整误差;

  4. 利用伪随机序列生成器生成 [0,N-1] 范围内的索引,并用它们构建一个 9999 个元素长度(重新采样后)的伪误差序列;

  5. 将来自人工生成误差数组的值插入到定义当前使用模型的方程中,从而创建一个包含 9999 个伪输入序列值的数组。换言之,之前我们必须将输入序列值插入到模型方程中,并据此计算预测误差,但现在却在进行逆运算。对于数组中的每个元素而言,都要插入其误差值才能计算出输入值。结果我们得到一个 9999 个元素的数组,其包含序列的分布情况与输入序列的分布情况相同,而通过其长度足以直接估算预测置信区间。

接下来再利用所生成的足够长度的序列来估算置信区间。为此,我们会利用以下情况:如果生成的预测误差数组按升序排列,则索引为 249 与 9749 的单元格中的值就会对应 95% 置信区间 [10] 的限制值,这些单元格位于包含 9999 个值的数组中。

要对预测区间进行更为精确的估算,则数组长度应为奇数。在本例中,预测置信区间的限制值通过以下方式进行估算:

  1. 利用前文确定的最优模型参数从头到尾过一遍所生成的序列,并创建一个由 9999 个提前一步预测误差组成的数组。

  2. 对所创建的数组进行排序;

  3. 从排序的误差数组中选择索引为 249 和 9749 (代表 95% 置信区间的限制值)的值;

  4. 针对提前两步、三步及更多步预测误差重复步骤 1、步骤 2 和步骤 3。

使用这种方法来估算置信区间有利也有弊。


量化交易软件策略:使用指数平滑法进行时间序列预测(续)的评论 (共 条)

分享到微博请遵守国家法律