由于事先预测波动率比简单标准差更好,我试图用q
语言编写指数加权移动标准差函数incremental definition
我从ema
中q/k
函数的增量实现中获得了启发。
q) ema
k){(*y)(1f-x)\x*y}
上面有趣的部分是{x y\z}
是{{z+y*x}\[x;y;z]}
的缩写。
这是我的尝试,但它会两次扫描(\
)输入向量y
:
q) .q.emdev:{sqrt 0f (1f-x)\0f^(1f-x)*x*d*d:y-prev ema[x;y]}
q) (1%3) emdev 1,10#0
0 0.4714045 0.496904 0.4566233 0.3981362 0.3381504 0.2829914 0.2347385 0.1936388 0.1591718 0.1305404
核心递归公式(根据上面引用的论文)使用:
假设这是正确的,有人提出更有效的实施吗?
答案 0 :(得分:1)
我尝试实现它,以便它只使用增量公式扫描输入向量,并仅使用每个循环中的前一个值返回每个循环中的下一个EMA和EMVAR,并获得与您相同的结果。
myemdev:{sqrt (flip {((1f-x)*y[0]+x*d*d;y[1]+x*d:z-y[1])}[x]\[(0;first y);y]) 0}
q)myemdev[(1%3);1,10#0]
0 0.4714045 0.496904 0.4566233 0.3981362 0.3381504 0.2829914 0.2347385 0.1936388 0.1591718 0.1305404
但是尽管它只在输入上循环一次,但这种方法比你的方法花费的时间要长得多。
q)\t {sqrt 0f (1f-x)\0f^(1f-x)*x*d*d:y-prev ema[x;y]}[1%3;1,100000#0]
4
q)\t {sqrt (flip {((1f-x)*y[0]+x*d*d;y[1]+x*d:z-y[1])}[x]\[(0;first y);y]) 0}[1%3;1,100000#0]
189
q)\t ema[1%3;100000#0]
1
q)\t {{z+(1f-x)*y}[x]\[first y;y*x]}[1%3;1,100000#0]
57
看看这两个给出相同结果的函数,很明显{x y\z}
形式的方法比写成lambda的函数快得多,尽管我不确定优化的实现引擎盖下。
q)\t {(1)(1+x)\(x*y)}[0.005;1,1000000#0]
15
q)\t {{z+x*(1+y)}\[1;x;(x*y)]}[0.005;1,1000000#0]
711
虽然您的方法使用两次扫描,但两者都是{x y\z}
形式,因此从我的角度来看非常有效。使用纯增量方法仅对输入进行一次扫描的好处是因为无法将其置于这种更有效的形式,例如重新排列方法中的(1f-x;1f)*y
:{sqrt (flip {(1f-x;1f)*y+x*(d,1f)*d:z-y[1]}[x]\[(0;first y);y]) 0}
不能预先计算,因为我们没有可用的所有EMA值(根据需要计算每个循环)。
我将继续寻找两种方法的改进,我很想知道是否有人能在效率方面打败你的方法