【问题标题】:R Parabolic SAR and Look-Ahead BiasR抛物线SAR和前瞻偏差
【发布时间】:2016-10-11 06:08:21
【问题描述】:

我正在 R 中使用由 Joshua Ulrich 实现的出色 TTR 包中的 SAR() 函数进行测试。我不确定这是否是抛物线 SAR 的标准行为。如果是,我需要一些帮助来实施“未来盲人”SAR。

为了简单起见,我将使用短向量和整数值而不是实时序列数据。

L <- c(1:4, 5)
H <- c(2:5, 6)

ParSAR <- SAR(cbind(H, L))
cbind(L, H, ParSAR)

     L H   ParSAR
[1,] 1 2 1.000000
[2,] 2 3 1.000000
[3,] 3 4 1.080000
[4,] 4 5 1.255200
[5,] 5 6 1.554784

我只会在 last 区间更改一个值,此时 Low - High 的范围将是 5 - 7,而不是 5 - 6。

L <- c(1:4, 5)
H <- c(2:5, 7)

我们得到:

     L H    ParSAR
[1,] 1 2 0.5527864
[2,] 2 3 0.5817307
[3,] 3 4 0.6784614
[4,] 4 5 0.8777538
[5,] 5 7 1.2075335

抛物线 SAR 的所有历史都被大幅修改是预期的行为吗?如果第 1 到第 4 行的 SAR 值被第 5 行的不同未来值修改,则会对之前的行引入前瞻偏差。

如果这是抛物线 SAR 的标准行为并且我需要它进行回测,我将不得不为每一行重新计算它,始终屏蔽所有未来数据(行)。

期望的结果是每行都有抛物线 SAR 值,因为我可以在特定的时间见证它,不知道未来。


编辑2016-06-18

user3666197 的简化代码示例:

> SAR(cbind(c(2, 3, 4, 5, 6), c(1, 2, 3, 4, 5)), c(0.02, 0.2))
[1] 1.000000 1.000000 1.080000 1.255200 1.554784

> SAR(cbind(c(2, 3, 4, 5, 7), c(1, 2, 3, 4, 5)), c(0.02, 0.2))
[1] 0.5527864 0.5817307 0.6784614 0.8777538 1.2075335

【问题讨论】:

    标签: r trading algorithmic-trading sar back-testing


    【解决方案1】:

    @user3666197:

    您的测试对两个简短示例给出了相同的结果,因为在这两种情况下都使用了默认值 initGap = 0.。如上所述,R 包装函数并非如此:

      # Gap for inital SAR
      initGap <- sd(drop(coredata(HL[,1] - HL[,2])), na.rm=TRUE)
    

    【讨论】:

    • 这从一开始就很清楚。请考虑 O/P 问题 (cit.:) Q:“如果这是抛物线 SAR 的标准行为”的观点。 A:不,不是。 进一步的推理和证据在上面的详细答案中得到了发展。除了initGap = 0. 之外的任何分配都是特定的包装器注入断言,不是普遍接受的pSAR() 功能/引入前瞻偏差的副作用。 所以保持原始帖子的观点,因此,答案是“不,不是”。 以及实现前瞻盲包装校正的解决方案。
    • 你总是错的。最初的问题是关于 R、R 实现、R 解决方案等。你从一开始就完全脱离了它,然后没有带来任何启发性的东西。后来你滥用你的权力来否决唯一真正的答案。您基本上破坏了我的问题以及我的整个 Stack Overflow 体验。 @user.51U15:你的方法是对的。感谢您的光临。
    • @Dave Are you sure? 如果很好地阅读了架构,R 不会计算 p-SAR 值,是吗?调用正确实现的 sar() 并接收该值。返回值错误不是由于 sar() 前瞻偏差或其他魔法,而是由于不适当的初始化,它来自 R 端包装器并导致您所询问的副作用。 抱歉再重复一遍——不,抛物线 SAR ( sar() ) 没有前瞻偏差,但由于初始化值选择不当,R 端包装器注入了一个这样的偏差。 Q.E.D.
    • 您不必说对不起,也不必重复。这些是我的发现,不是你的。让我引用你的话:“在 Joshua ULRICH 的观察到的 pSAR 算法的实现中,前瞻窥视为零。Q.E.D.”错误的。有。唯一正确和完整的答案是下面很短的答案。你只是为了回答不存在的问题而大声喧哗。阅读标题的第一个字符,阅读第一个标志,阅读第一篇文章的第一句话。我在问“R”的实现。
    【解决方案2】:

    抛物线 SAR 的 R 实现带有前瞻偏差。

    initGap 值是所有时间 HL 数据的标准偏差:

    initGap <- sd(drop(coredata(HL[, 1] - HL[, 2])), na.rm = TRUE)
    

    参考:https://github.com/joshuaulrich/TTR/issues/23

    对我的原始示例的巨大影响是由于数据样本太短和使用的极值造成的。

    【讨论】:

      【解决方案3】:

      pSAR 没有实现任何前瞻窥视

      只要稍微code-review of Joshua ULRICH's pSAR implementation,就可以确认源代码中的零前瞻窥视。

      问题可能来自函数调用签名的第一眼,但the R-wrapper 解决了这些问题。

      #'@export
      "SAR" <-
      function(HL, accel=c(.02,.2)) {
      
        # Parabolic Stop-and-Reverse (SAR)
        # ----------------------------------------------
        #       HL = HL vector, matrix, or dataframe
        # accel[1] = acceleration factor
        # accel[2] = maximum acceleration factor
        ...
      
        # Gap for inital SAR
        initGap <- sd(drop(coredata(HL[,1] - HL[,2])), na.rm=TRUE)
      
        # Call C routine
        sar <- .Call("sar", HL[,1], HL[,2], accel, initGap, PACKAGE = "TTR")
      
        reclass( sar, HL )
      }
      

      SAR()实现使用sar()发布的调用接口:

      SEXP sar ( SEXP hi, /* HIGH[]-s */ SEXP lo, /* LOW[]-s */ SEXP xl, /* [initial AF value, max AF value] */ SEXP ig /* initial GAP */ )

      在任何for(){...} 扫描仪中都没有对未来的窥视(零前瞻)(所有这些都是纯粹的回顾)。


      更新

      两个给定数据集的测试输出:

      |>>> sar( ( 2, 3, 4, 5, 6 ), ( 1, 2, 3, 4, 5 ), ( 0.02, 0.2 ) )
      [1.0, 1, 1.08, 1.2552, 1.5547840000000002]
      |
      |>>> sar( ( 2, 3, 4, 5, 7 ), ( 1, 2, 3, 4, 5 ), ( 0.02, 0.2 ) )
      [1.0, 1, 1.08, 1.2552, 1.5547840000000002]
      

      在 Joshua ULRICH 的 pSAR 算法实现中观察到零前瞻窥视

      Q.E.D.



      事后

      从一开始就指出,sar() 函数被证明是正确实现的 pSAR 技术指标。 R 包装器是问题所在,因为它决定了正在调用底层、正确工作的函数sar() 的参数。 在调用签名加载带有前瞻性偏见的参数的情况下,此类行为不应归咎于函数,而应归咎于用户。 Q.E.D.

      #----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
              # CRAN - R-Project TTR lib: indicators::                        # Joshua ULRICH: >>> https://github.com/joshuaulrich/TTR/tree/master/src + https://cran.r-project.org/web/packages/TTR/TTR.pdf
              def sar( Hi, Lo, acceleration_factor = ( 0.02, 0.2 ), initGap = 0. ):
                  """                                                         __doc__
                  USAGE:      calculate parabolic SAR on given inputs
                              sar( Hi,
                                   Lo,
                                   acceleration_factor = ( 0.02, 0.2 ),
                                   initGap = 0.
                                   )
                  PARAMS:     Hi:                     High[]s in []-alike representation
                              Lo:                     Low[]-s in []-alike representation
                              acceleration_factor:    [ afSTEP, afMAX ], ref. pSAR rules
                              initGap:                initial gap under first valid Low[]
                  RETURNS:    pSAR[]
                  THROWS:     n/a
                  EXAMPLE:    |>>> QuantFX.sar( (2,3,4,5,6), (1,2,3,4,5) )
                              [1.0, 1, 1.08, 1.2552, 1.5547840000000002]
                              |
                              |>>> QuantFX.sar( (2,3,4,5,7), (1,2,3,4,5) )
                              [1.0, 1, 1.08, 1.2552, 1.5547840000000002]
                  """
                  """
                  #___________________________________________________________/* Initalize loop and PROTECT counters */
                  int i, P=0;
                  #___________________________________________________________/* Ensure all arguments are double */
                  if(TYPEOF(hi) != REALSXP) {
                    PROTECT(hi   = coerceVector(hi, REALSXP)); P++;
                  }
                  if(TYPEOF(lo) != REALSXP) {
                    PROTECT(lo   = coerceVector(lo, REALSXP)); P++;
                  }
                  if(TYPEOF(xl) != REALSXP) {
                    PROTECT(xl   = coerceVector(xl, REALSXP)); P++;
                  }
                  double initGap = asReal( ig );                              ### ------------------------ extern ( ig )
                  #___________________________________________________________/* Pointers to function arguments */
                  double *d_hi   = REAL(hi);
                  double *d_lo   = REAL(lo);
                  double *d_xl   = REAL(xl);
                  """
                  #___________________________________________________________/* Input object length */
                  #int nr        = nrows(hi);
                  nRows          = len(  Hi )
                  #___________________________________________________________/* Initalize result R object */
                  #SEXP sar; PROTECT(sar = allocVector(REALSXP,nr)); P++;
                  #double *d_sar = REAL(sar);
                  sar            = [None] * nRows
                  #___________________________________________________________/* Find first non-NA value */
                  #int beg       = 1;
                  begFrom        = 1
                  #for(i=0; i < nr; i++) {
                  for i in xrange( nRows ):
                    if (  np.isnan( Hi[i] )
                       or np.isnan( Lo[i] )
                       ):
                       sar[i]    = None                                       # NA_REAL; /* skip-it */
                       begFrom  += 1
                    else:
                       break                                                  #          /* break   */
                    pass
                  pass
                  #___________________________________________________________/* Initialize values needed by the routine */
                  #int sig0 = 1, sig1 = 0;
                  sig0           = 1
                  sig1           = 0
      
                  xpt0           = Hi[begFrom-1]
                  xpt1           = 0
      
                  afStp          = acceleration_factor[0]
                  afMAX          = acceleration_factor[1]
                  af0            = afStp
                  af1            = 0
      
                  sar[begFrom-1] = Lo[begFrom-1] - initGap                    # /* SUB initGap from 1st Lo[] to begin from */
      
                  for i in xrange( begFrom, nRows ):
                    #_________________________________________________________/* Increment signal, extreme point, and acceleration factor */
                    sig1         = sig0
                    xpt1         = xpt0
                    af1          = af0
                    #_________________________________________________________/* Local extrema */
                    lmin         = min( Lo[i-1], Lo[i] )                                      #?? pSAR_RULE_Exc 2 ?? 2 last bars checked
                    lmax         = max( Hi[i-1], Hi[i] )
                    #_________________________________________________________/* Create signal and extreme price vectors */
                    if ( sig1   == 1 ):                                                         #/* Previous buy signal */
                         #ig0    = ( Lo[i] > d_sar[i-1]) ?  1 : -1                              #/* New signal */
                         sig0    =                          1 if ( Lo[i] > sar[i-1] ) else -1   #/* New signal */
                         xpt0    = max( lmax, xpt1 )                                            #/* New extreme price */
                    else:                                                                       #/* Previous sell signal */
                         #ig0    = ( Hi[i] < d_sar[i-1]) ? -1 : 1                               #/* New signal */
                         sig0    =                         -1 if ( Hi[i] < sar[i-1] ) else 1    #/* New signal */
                         xpt0    = min( lmin, xpt1 )                                            #/* New extreme price */
                    pass
                    """
                    /*
                     * Calculate acceleration factor (af)
                     * and stop-and-reverse (sar) vector
                     */
                    """
                    #_________________________________________________________/* No signal change */
                    if ( sig0   == sig1 ):
                      #_______________________________________________________/* Initial calculations */
                      sar[i]     =     sar[i-1] + ( xpt1 - sar[i-1] ) * af1
                      #f0        = ( af1 == afMAX ) ? afMAX : ( afStp + af1 )
                      af0        =                    afMAX if ( af1 == afMAX ) else ( afStp + af1 )
                      #_______________________________________________________/* Current buy signal */
                      if ( sig0 == 1 ):
                           #f0   = (xpt0 > xpt1) ? af0 : af1                                  #/* Update acceleration factor */
                           af0   =                 af0 if (xpt0 > xpt1) else af1              #/* Update acceleration factor */
                           sar[i]= min( sar[i], lmin )                                        #/* Determine sar value */
                      #_______________________________________________________/* Current sell signal */
                      else:
                           #f0   = (xpt0 < xpt1) ? af0 : af1                                  #/* Update acceleration factor */
                           af0   =                 af0 if (xpt0 < xpt1) else af1              #/* Update acceleration factor */
                           sar[i]= max( sar[i], lmax )                                        #/* Determine sar value */
                    #_________________________________________________________/* New signal */
                    else:
                      af0        = afStp                                                      #/* reset acceleration factor */
                      sar[i]     = xpt0                                                       #/* set sar value */
                    pass
                  pass
                  #___________________________________________________________/* UNPROTECT R objects and return result */
                  #UNPROTECT(P);
                  #return(sar);
                  return  sar
      

      【讨论】:

      • 对不起,我没明白。我仍然不明白第 5 行的值更改如何影响之前的所有值。如果我有长度为 n 的数据,我不能相信为第 1:n-1 行计算的值。就拿我的第二个例子来说,只使用 1:4 行。计算 SAR。添加最后一行并重新计算。所有的价值观都发生了巨大的变化。这是一个问题,因为 SAR 通常一次应用于整个数据长度。
      • 在交叉验证了源代码以提供正确的结果后,我几乎无法重现解释差异结果,显示在您的帖子中。我想到的是,就像其他类似问题的假设一样,错误设计了计算策略的并行化,其中代码的自然 SEQ 部分被错误地制作为矢量化 ( PAR 处理的弱形式)代码和错误结果显然是由于违反SEQ 流程中的依赖链而产生的。
      • 我不知道您编辑中的示例来自哪里,因为它不是有效的 R 代码。我已更正它并在 R 控制台中运行。您可以在我的原始帖子的编辑中看到结果。如您所见,我的结果完全不同,并且清楚地显示了前瞻性偏差,即未来数据会影响/改变过去的数据。我想知道@JoshuaUlrich 是否会知道为什么会这样。也许这是相关的?:link
      • 验证是在 @JoshuaUlrich re-wrapper 为 R.InitGap 使用的底层 c 代码上执行的,链接中报告的内容在 pSAR 使用环境中对我来说并不常见。通常,最初的 Flip/Flop 决定留给 TimeSERIEs 历史的足够深的头部,之后指标在历史数据的近端表现良好。因此,仅在几个数据点上使用代码是该原理的相反极端。无论如何,python被用来测试假设的算法部分,这证明自己是正确的。其余的在编译器/包装器/R
      • 所以,您没有阅读和理解标题和原始问题 - 从一开始一切都与“R”有关。然后,你没有发现问题,反而释放了你的自我,最终否决了唯一真正的答案。好吧,为自己感到骄傲,享受你的小操场。 :)
      猜你喜欢
      • 2021-09-04
      • 1970-01-01
      • 2019-07-21
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      相关资源
      最近更新 更多