2011-12-09 6 views
8

में एक कतार पर घातीय मूविंग औसत की गणना करें मेरे पास इसमें जोड़े गए मानों के चलते औसत की गणना करने के लिए एक साधारण कक्षा है। मैं इसे इस तरह का उपयोग करें:सी #

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 वापसी करना चाहते हैं। उद्धरणों में कतारबद्ध वस्तुओं के घातीय औसत को आप कैसे लिखेंगे?

मुझे एहसास है कि आपको कक्षा में अल्फा संपत्ति जोड़ने की आवश्यकता होगी, लेकिन मुझे यकीन नहीं है कि गणित को गणना के लिए कैसे पूरा किया जाए।

उत्तर

14

कैसे LINQ के साथ के बारे में:

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

मैं कहना है कि वास्तविक समय वित्तीय डेटा के लिए, इस अत्यधिक अक्षम है। पिछले EMA मान को कैश करना और उपरोक्त (निरंतर-समय) पुनरावृत्ति-सूत्र के साथ एक नए उद्धरण पर इसे अपडेट करना एक बेहतर तरीका होगा।

+0

अल्फा अनिर्धारित रहता है। आपने इसके लिए क्या सेट किया? – Levitikon

+1

@Levitikon: देखें [Exponential_moving_average] (https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average)। "गुणांक α भार घटाने की डिग्री का प्रतिनिधित्व करता है, 0 और 1 के बीच एक स्थिर चिकनाई कारक। उच्च α पुराने अवलोकनों को तेजी से छूट देता है।" – Ani

2

घातीय मूविंग औसत के लिए कतार की आवश्यकता नहीं है क्योंकि आपको केवल पिछले ईएमए का ट्रैक रखने की आवश्यकता है।

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

यहाँ की @ एक अलग एपीआई के साथ 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; 
}