2011-12-09 63 views
8

私が追加する値の移動平均を計算するためのシンプルなクラスがあります。私はこのようにそれを使用します。C#のキューで指数移動平均を計算する

MovingAverage ma = new MovingAverage(); 
ma.push(value1); 
ma.push(value2); 
... 
Console.Writeline(average.Average); 

//the class 
public class MovingAverage 
{ 
    public int Period = 5; 
    private Queue<double> Quotes = new Queue<double>(); 

    public void Push(double quote) 
    { 
     if (Quotes.Count == Period) 
      Quotes.Dequeue(); 
     Quotes.Enqueue(quote); 

    } 
    public void Clear() 
    { 
     Quotes.Clear(); 
    } 
    public double Average { get { if (Quotes.Count == 0) return 0; return Quotes.Average(); } } 
    public double ExponentialMovingAverage 
    { 
     get 
     { 
      ??? 
     } 
    } 
} 

私もExponentialMovingAverageを返すために、このクラスを拡張したいと思います。どのようにしてQuotesのQueued項目のExponential Averageを返しますか?

クラスにAlphaプロパティを追加する必要があることがわかりましたが、計算の計算方法はわかりません。

答えて

14

どのようにLINQで約:

return Quotes.DefaultIfEmpty() 
      .Aggregate((ema, nextQuote) => alpha * nextQuote + (1 - alpha) * ema); 

私はリアルタイムの財務データのために、これは非常に非効率的であることを指摘します。はるかに良い方法は、以前のEMA値をキャッシュし、上記の(定数時間)繰り返し式を使用して新しい見積もりに更新することです。あなたが唯一の前のEMAを追跡する必要があるため

+0

アルファが定義されていないC#を使用します。あなたはそれのために何を決めましたか? – Levitikon

+1

@Levitikon:[Exponential_moving_average](https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average)を参照してください。係数αは、0と1との間の一定の平滑化係数である重み付けの減少の程度を表す。αが大きいほど、より古い観察がより迅速に行われる。 – Ani

2

Doが移動平均指数のキューを必要としません。

public class ExponentialMovingAverageIndicator 
{ 
    private bool _isInitialized; 
    private readonly int _lookback; 
    private readonly double _weightingMultiplier; 
    private double _previousAverage; 

    public double Average { get; private set; } 
    public double Slope { get; private set; } 

    public ExponentialMovingAverageIndicator(int lookback) 
    { 
     _lookback = lookback; 
     _weightingMultiplier = 2.0/(lookback + 1); 
    } 

    public void AddDataPoint(double dataPoint) 
    { 
     if (!_isInitialized) 
     { 
      Average = dataPoint; 
      Slope = 0; 
      _previousAverage = Average; 
      _isInitialized = true; 
      return; 
     } 

     Average = ((dataPoint - _previousAverage)*_weightingMultiplier) + _previousAverage; 
     Slope = Average - _previousAverage; 

     //update previous average 
     _previousAverage = Average; 
    } 
} 
+0

'_lookback'フィールドは何も使用しません。 ctorでのみ使用すれば十分です。 –

3

はここで若干異なるAPIを持つMattWolfの答え@最小限のバージョンだし、7

public sealed class FloatExponentialMovingAverageCalculator 
{ 
    private readonly float _alpha; 
    private float _lastAverage = float.NaN; 

    public FloatExponentialMovingAverageCalculator(int lookBack) => _alpha = 2f/(lookBack + 1); 

    public float NextValue(float value) => _lastAverage = float.IsNaN(_lastAverage) 
     ? value 
     : (value - _lastAverage)*_alpha + _lastAverage; 
}