R 抛物线 SAR 和前视偏差
R Parabolic SAR and Look-Ahead Bias
我正在 R
中使用 SAR()
函数进行测试 TTR
包由 Joshua Ulrich 实施。我不确定这是否是 Parabolic SAR 的标准行为。如果是,我需要一些帮助来实施 "future blind" 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
Parabolic 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
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.
Ex-post
as noted from the very beginning, the sar()
function was proved to be correctly implemented pSAR technical indicator. The R wrapper was the issue, as it decides on what parameters the underlying, correctly working, function sar()
is being invoked. Upon a case the call-signature is loaded with parameters, that carry a forward looking bias, the function is not to be blamed for a such behaviour, but rather the user. 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
抛物线 SAR 的 R 实现带有前瞻偏差。
initGap 值是所有时间 HL 数据的标准偏差:
initGap <- sd(drop(coredata(HL[, 1] - HL[, 2])), na.rm = TRUE)
参考文献:https://github.com/joshuaulrich/TTR/issues/23
对我的原始示例的巨大影响是由短数据样本和使用的极值造成的。
@user3666197 :
您的测试对两个简短示例给出了相同的结果,因为在这两种情况下都使用了默认值 initGap = 0.
。如上所述,R 包装函数不是这种情况:
# Gap for inital SAR
initGap <- sd(drop(coredata(HL[,1] - HL[,2])), na.rm=TRUE)
我正在 R
中使用 SAR()
函数进行测试 TTR
包由 Joshua Ulrich 实施。我不确定这是否是 Parabolic SAR 的标准行为。如果是,我需要一些帮助来实施 "future blind" 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
Parabolic 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
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.
Ex-post
as noted from the very beginning, the
sar()
function was proved to be correctly implemented pSAR technical indicator. The R wrapper was the issue, as it decides on what parameters the underlying, correctly working, functionsar()
is being invoked. Upon a case the call-signature is loaded with parameters, that carry a forward looking bias, the function is not to be blamed for a such behaviour, but rather the user.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
抛物线 SAR 的 R 实现带有前瞻偏差。
initGap 值是所有时间 HL 数据的标准偏差:
initGap <- sd(drop(coredata(HL[, 1] - HL[, 2])), na.rm = TRUE)
参考文献:https://github.com/joshuaulrich/TTR/issues/23
对我的原始示例的巨大影响是由短数据样本和使用的极值造成的。
@user3666197 :
您的测试对两个简短示例给出了相同的结果,因为在这两种情况下都使用了默认值 initGap = 0.
。如上所述,R 包装函数不是这种情况:
# Gap for inital SAR
initGap <- sd(drop(coredata(HL[,1] - HL[,2])), na.rm=TRUE)