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