Reference: stack overflow
其实pandas ewm已经很好用了,除了有点慢,也不是很慢,为什么我要搞个numpy的版本呢?
因为期货主连数据回测时有个最大的问题就是合约切换,那个切换时的价格跳动是无效的,会产生虚假信号,但是如果直接把回测数据做前复权,如果是价差策略,早期的价差会非常不准确。而且在实盘时用pandas不断的append数据,那是罪恶,所以干脆搞个numpy的版本。
我是用的Reference里面的代码改的,但不是最高票答案,而是 james 的答案,james 的答案准确度非常的高,思路清晰,james 是直接把rolling的结果全部计算出来了,而我只需要计算单个值,所以改出来后的代码也是很快的,不需要像高票答案一样把速度做到极致,然而 adjust=True 的情况下又没有做出来。
然后 var 就直接参考的 pandas 的文档做的计算,很简单。
简单讲一个ewm(指数加权移动),把指数和加权结合起来,我曾经在ML中用ewm的mean做过测试,ewm预测价格的效果确实要好一些。ewm有个span的参数可以供我们计算移动平均,移动方差使用,但是要注意span并不是window,window是只取window大小的数据,但是span=10是可以取1000甚至更多的数据参与计算的,只是由span计算出alpha,来改变里面权重的计算方法而已。
下面代码的计算结果和pandas的一模一样,非常棒,在我自己的numpy rolling中计算简直不要太快。
# 原版 rolling ewma 代码,做参考用,可以借鉴其中的weight及各程矩阵构造思路,还不错
def ewma(x, alpha):
'''
Returns the exponentially weighted moving average of x.
Parameters:
-----------
x : array-like
alpha : float {0 <= alpha <= 1}
Returns:
--------
ewma: numpy array
the exponentially weighted moving average
'''
# Coerce x to an array
x = np.array(x, copy=False)
n = x.size
# Create an initial weight matrix of (1-alpha), and a matrix of powers
# to raise the weights by
w0 = np.ones(shape=(n,n)) * (1-alpha)
p = np.vstack([np.arange(i,i-n,-1) for i in range(n)])
print(p)
# Create the weight matrix
w = np.tril(w0**p,0)
# Calculate the ewma
print(x[::np.newaxis])
return np.dot(w, x) / w.sum(axis=1)
def my_ewma(x, window):
n = x.size
alpha = 2/(1+window)
x = x[::-1]
w0 = np.ones(n) * (1-alpha)
p = np.arange(0,n,1)
w = w0**p
ewm = np.dot(w, x) / w.sum()
return ewm
def my_ewvar(ewma, x, window):
n = x.size
alpha = 2 / (1 + window)
w0 = np.ones(n) * (1 - alpha)
p = np.arange(0, n, 1)
w = w0 ** p
with_bias = my_ewma(x ** 2, window) - ewma ** 2
scaler = w.sum() ** 2/(w.sum() ** 2 - (w**2).sum())
return with_bias * scaler
ewma_np = my_ewma(ibm.values, windowSize)
ewmvar_np = my_ewvar(ewma_np, ibm.values, windowSize)
Comments
comments powered by Disqus