zoz*_*zed 15 c# algorithm financial moving-average
用于计算简单移动平均值的最快库/算法是什么?我写了自己的,但是在33万项十进制数据集上花了太长时间.
这是我的方法的代码:
public decimal MA_Simple(int period, int ii) {
if (period != 0 && ii > period) {
//stp.Start();
decimal summ = 0;
for (int i = ii; i > ii - period; i--) {
summ = summ + Data.Close[i];
}
summ = summ / period;
//stp.Stop();
//if (ii == 1500) System.Windows.Forms.MessageBox.Show((stp.ElapsedTicks * 1000.0) / Stopwatch.Frequency + " ms");
return summ;
} else return -1;
}
Run Code Online (Sandbox Code Playgroud)
这Data.Close[]是一个固定大小(1 000 000)的十进制数组.
小智 12
您的主要问题是每次迭代都会丢失太多信息.如果要快速运行,则需要保留与帧长度相同的缓冲区.
此代码将运行整个数据集的移动平均值:
(不是真正的C#,但你应该明白)
decimal buffer[] = new decimal[period];
decimal output[] = new decimal[data.Length];
current_index = 0;
for (int i=0; i<data.Length; i++)
{
buffer[current_index] = data[i]/period;
decimal ma = 0.0;
for (int j=0;j<period;j++)
{
ma += buffer[j];
}
output[i] = ma;
current_index = (current_index + 1) % period;
}
return output;
Run Code Online (Sandbox Code Playgroud)
请注意,保持正在运行的cumsum可能很有吸引力,而不是保留整个缓冲区并计算每次迭代的值,但这对于很长的数据长度不起作用,因为累积的总和会增长得太大,以至于添加小的附加值将会导致舍入错误.
J.L*_*nes 10
public class MovingAverage
{
private Queue<Decimal> samples = new Queue<Decimal>();
private int windowSize = 16;
private Decimal sampleAccumulator;
public Decimal Average { get; private set; }
/// <summary>
/// Computes a new windowed average each time a new sample arrives
/// </summary>
/// <param name="newSample"></param>
public void ComputeAverage(Decimal newSample)
{
sampleAccumulator += newSample;
samples.Enqueue(newSample);
if (samples.Count > windowSize)
{
sampleAccumulator -= samples.Dequeue();
}
Average = sampleAccumulator / samples.Count;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,Math DotNet库有一个名为的类RunningStatistics,可以为您执行此操作。如果您只想在最后的“X”项上执行此操作,请MovingStatistics改用。
两者都将计算运行平均值、方差和标准偏差,仅通过一次运行,无需存储额外的数据副本。
如果数据是静态的,则可以对数组进行预处理,以使移动平均值查询变得非常快:
decimal[] GetCSum(decimal[] data) {
decimal csum[] = new decimal[data.Length];
decimal cursum = 0;
for(int i=0; i<data.Length; i++) {
cursum += data[i];
csum[i] = cursum;
}
return csum;
}
Run Code Online (Sandbox Code Playgroud)
现在,移动平均线的计算既简单又快速:
decimal CSumMovingAverage(decimal[] csum, int period, int ii) {
if(period == 0 || ii <= period)
return -1;
return csum[ii] - csum[ii - period];
}
Run Code Online (Sandbox Code Playgroud)