如何有效地计算移动标准偏差 [英] How to efficiently calculate a moving Standard Deviation

查看:200
本文介绍了如何有效地计算移动标准偏差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面你可以看到我的C#的方法来计算布林带每个点(均线,上涨波段,下跌波段)。



正如你可以看到这个方法使用2循环使用移动平均计算移动标准偏差。它用于包含一个额外循环过去n个周期来计算移动平均值。这一次我可以通过添加新的点值在循环的开始total_average和去除我删除 - N点值在循环结束



我的现在的问题基本上是:?我可以去除剩余的内环以类似的方式,我与均线管理

 公共静态无效AddBollingerBands(编号排序列表<日期时间,字典<字符串,双>>的数据,诠释期间,INT因子)
{
双total_average = 0;

的for(int i = 0; I< data.Count();我++)
{
total_average + = data.Values​​ [I] [亲密];

如果(I> =时间 - 1)
{
双total_bollinger = 0;
双平均= total_average /期;

为(INT X = 1; X>(I - 期); x--)
{
total_bollinger + = Math.Pow(data.Values​​ [X] [关闭] - 平均,2);
}

双重标准偏差=的Math.sqrt(total_bollinger /期);

data.Values​​ [I] [bollinger_average] =平均值;
data.Values​​ [I] [bollinger_top] =平均+因子*标准偏差;
data.Values​​ [I] [bollinger_bottom] = AVERAGE - 因子×标准偏差;

total_average - = data.Values​​ [我 - 周期+ 1] [亲密];
}
}
}


解决方案

答案是肯定的,你可以。在80年代中期我在FORTRAN开发了这样一个算法(可能不是原装)的过程监测和控制应用程序。不幸的是,那是在25年前,我不记得确切的公式,但该技术是一个用于移动平均的延伸,具有二阶计算,而不只是线性的。






在你的代码看一些后,我认为我可以苏斯了我是如何做到了当时的情况。 ?请注意你的内循环是如何制作的平方和:

 为(INT X = 1; X>(I  - 期); x--)
{
total_bollinger + = Math.Pow(data.Values​​ [X] [关闭] - 平均,2);
}

在大致相同的方式,你的平均必须要有原本有值的总和?只有两个区别是顺序(其功率2,而不是1),您减去平均每个值你方之前。现在看起来是分不开的,但实际上他们可以分开的:

  SUM(i = 1; N){(V [我]  -  K)^ 2} 

  SUM(I = 1..N){v [I] ^ 2 -2 * v [I] * K + K ^ 2} 

变成

  SUM(我= 1..1){v [I] ^ 2 -2 * v [I] * K} + K ^ 2 * N 

这是

  SUM(I = 1..N){v [I] ^ 2 } + SUM(I = 1..N){ -  2 * v [I] * K} + K ^ 2 * N 

这也是

  SUM(I = 1..N){v [I] ^ 2 } + SUM(I = 1..N){ -  2 * v [I]} * K + K ^ 2 * N 

现在的第一项只是平方和,您处理,在您为平均做值的总和相同的方式。最后一项( K ^ 2 * N )只是普通的平方倍周期。既然你的时间划分的结果,无论如何,你可以添加新的均方没有额外的循环。



最后,在第二个任期内( SUM(-2 * v [I])* K ),因为 SUM(v [I])=总= K * N 你那么可以将它更改成这样:

  -2 * K * K * N 

或只是 -2 * K ^ 2 * N ,这是-2倍的平均平方一旦时间( N )又分为了。所以最终的综合公式为:

  SUM(I = 1..N){V [I] ^ 2}  -  N * K ^ 2 

  SUM(I = 1..N){值[I] ^ 2}  - 期*(平均^ 2)

(一定要检查该有效性,因为我得出它把我的头顶部)



和合并到你的代码看起来应该是这样的:

 公共静态无效AddBollingerBands(REF排序列表<日期时间,字典<字符串,双> >的数据,诠释期间,INT因子)
{
双total_average = 0;
双TOTAL_SQUARES = 0;

的for(int i = 0; I< data.Count();我++)
{
total_average + = data.Values​​ [I] [亲密];
TOTAL_SQUARES + = Math.Pow(data.Values​​ [I] [亲密],2);

如果(I> =时间 - 1)
{
双total_bollinger = 0;
双平均= total_average /期;

双重标准偏差=的Math.sqrt((TOTAL_SQUARES - Math.Pow(total_average,2)/周期)/期);
data.Values​​ [I] [bollinger_average] =平均值;
data.Values​​ [I] [bollinger_top] =平均+因子*标准偏差;
data.Values​​ [I] [bollinger_bottom] = AVERAGE - 因子×标准偏差;

total_average - = data.Values​​ [我 - 周期+ 1] [亲密];
}
}
}


Below you can see my C# method to calculate Bollinger Bands for each point (moving average, up band, down band).

As you can see this method uses 2 for loops to calculate the moving standard deviation using the moving average. It used to contain an additional loop to calculate the moving average over the last n periods. This one I could remove by adding the new point value to total_average at the beginning of the loop and removing the i - n point value at the end of the loop.

My question now is basically: Can I remove the remaining inner loop in a similar way I managed with the moving average?

    public static void AddBollingerBands(ref SortedList<DateTime, Dictionary<string, double>> data, int period, int factor)
    {
        double total_average = 0;

        for (int i = 0; i < data.Count(); i++)
        {
            total_average += data.Values[i]["close"];

            if (i >= period - 1)
            {
                double total_bollinger = 0;
                double average = total_average / period;

                for (int x = i; x > (i - period); x--)
                {
                    total_bollinger += Math.Pow(data.Values[x]["close"] - average, 2);
                }

                double stdev = Math.Sqrt(total_bollinger / period);

                data.Values[i]["bollinger_average"] = average;
                data.Values[i]["bollinger_top"] = average + factor * stdev;
                data.Values[i]["bollinger_bottom"] = average - factor * stdev;

                total_average -= data.Values[i - period + 1]["close"];
            }
        }
    }

解决方案

The answer is yes, you can. In the mid-80's I developed just such an algorithm (probably not original) in FORTRAN for a process monitoring and control application. Unfortunately, that was over 25 years ago and I do not remember the exact formulas, but the technique was an extension of the one for moving averages, with second order calculations instead of just linear ones.


After looking at your code some, I am think that I can suss out how I did it back then. Notice how your inner loop is making a Sum of Squares?:

            for (int x = i; x > (i - period); x--)
            {
                total_bollinger += Math.Pow(data.Values[x]["close"] - average, 2);
            }

in much the same way that your average must have originally had a Sum of Values? The only two differences are the order (its power 2 instead of 1) and that you are subtracting the average each value before you square it. Now that might look inseparable, but in fact they can be separated:

SUM(i=1; n){ (v[i] - k)^2 }

is

SUM(i=1..n){v[i]^2 -2*v[i]*k + k^2}

which becomes

SUM(i=1..n){v[i]^2 -2*v[i]*k} + k^2*n

which is

SUM(i=1..n){v[i]^2} + SUM(i=1..n){-2*v[i]*k} + k^2*n

which is also

SUM(i=1..n){v[i]^2} + SUM(i=1..n){-2*v[i]}*k + k^2*n

Now the first term is just a Sum of Squares, you handle that in the same way that you do the sum of Values for the average. The last term (k^2*n) is just the average squared times the period. Since you divide the result by the period anyway, you can just add the new average squared without the extra loop.

Finally, in the second term (SUM(-2*v[i]) * k), since SUM(v[i]) = total = k*n you can then change it into this:

-2 * k * k * n

or just -2*k^2*n, which is -2 times the average squared, once the period (n) is divided out again. So the final combined formula is:

SUM(i=1..n){v[i]^2} - n*k^2

or

SUM(i=1..n){values[i]^2} - period*(average^2)

(be sure to check the validity of this, since I am deriving it off the top of my head)

And incorporating into your code should look something like this:

public static void AddBollingerBands(ref SortedList<DateTime, Dictionary<string, double>> data, int period, int factor)
{
    double total_average = 0;
    double total_squares = 0;

    for (int i = 0; i < data.Count(); i++)
    {
        total_average += data.Values[i]["close"];
        total_squares += Math.Pow(data.Values[i]["close"], 2);

        if (i >= period - 1)
        {
            double total_bollinger = 0;
            double average = total_average / period;

            double stdev = Math.Sqrt((total_squares - Math.Pow(total_average,2)/period) / period);
            data.Values[i]["bollinger_average"] = average;
            data.Values[i]["bollinger_top"] = average + factor * stdev;
            data.Values[i]["bollinger_bottom"] = average - factor * stdev;

            total_average -= data.Values[i - period + 1]["close"];
        }
    }
}

这篇关于如何有效地计算移动标准偏差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆