不同核的指数移动平均

1 投票
1 回答
1825 浏览
提问于 2025-04-18 15:34

我正在尝试复制一些公式,但在把数学公式转成代码时遇到了困难。

这里是简单的指数移动平均(Exponential Moving Average)

Exponential Moving Average

在C#中实现:

out[1] = values[1];
for (i in 2:N(X)) {
  tmp = (times[i] - times[i-1]) / tau;
  w = exp(-tmp);
  w2 = (1 - w) / tmp;
  out[i] = out[i-1] * w + values[i] * (1 - w2) + values[i-1] * (w2 - w);
}

在Python中实现:

mu = numpy.exp ((ts[1] - ts[0]) / self.tau)
nu = 1.0 - mu
return numpy.array ([
mu * el + nu * arr[0] for el, arr in zip (last, arrays)
])

我想能够指定不同的核(kernels),但不太确定该怎么做,具体可以参考这里:

EMA kernel MA

我这样做的目的是为了最终能够重现这里给出的移动差分:

enter image description here

谢谢大家的帮助!

1 个回答

1

这里有一种可能的方法,就是创建一个可以返回内核的函数。

根据我所看到的,这个函数的输入参数应该是 kerneltypeiotherInputs

一个简单的做法是:

for(int i = 1; i < values.length(); i++)
{
    tmp = (times[i] - times[i-1]) / tau;
    //w = exp(-tmp);
    //w2 = (1 - w) / tmp;
    List<Object> kernelInputsInital = new List<Object>();
    kernelInputsInitial.Add(tmp);  //takes in the first argument
    kernelInputsInitial.Add(true); //expected to calculate the first
    w = GetKernel(KernelType.Exponential, i, kernelInputsInitial);

    List<Object> kernelInputsSecondTerm = new List<Object>();
    kernelInputsSecondTerm.Add(w);  //takes in the first argument
    kernelInputsSecondTerm.Add(false); //expected to calculate the first
    w2 = GetKernel(KernelType.Exponential, i, kernelInputsInitial);

    out[i] = out[i-1] * w + values[i] * (1 - w2) + values[i-1] * (w2 - w);
    ....
}

当然,这个方法非常粗糙,还有很多地方可以改进,但主要目的是让大家明白这个思路。

我会用一个接口来表示内核,然后为每种内核创建不同的类。根据我的经验,这样写出来的代码既容易读懂又好维护,不过总是有改进的空间。

撰写回答