J'ai une classe simple pour calculer la moyenne mobile des valeurs que j'ajoute. Je l'utilise comme ceci:
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 { ??? } } }
4 Réponses :
Que diriez-vous de LINQ:
return Quotes.DefaultIfEmpty() .Aggregate((ema, nextQuote) => alpha * nextQuote + (1 - alpha) * ema);
alpha est indéfini. Qu'avez-vous mis pour ça?
@Leviti "Le coefficient α représente le degré de diminution de la pondération, un facteur de lissage constant entre 0 et 1. Un α plus élevé réduit les observations plus anciennes plus rapidement."
Ne pas avoir besoin d'une file d'attente pour une moyenne mobile exponentielle, car il vous suffit de garder une trace de l'EMA précédent.
Vous n'utilisez pas votre champ _lookback code> pour quoi que ce soit. Il suffirait de l'utiliser que dans la CTOR.
Voici une version minimale de la réponse de @ Mattwolf avec une API légèrement différente et en utilisant C # 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; }
Je pense qu'il y a un petit tweak nécessaire à la réponse de @ Ani. La valeur initiale serait définie sur "Alpha * NextQuote" au lieu de "NextQuote". La solution la plus facile est de définir la valeur de la graine initiale pour correspondre au premier enregistrement, puis la première itération devient Alpha * S1 + (1 - alpha) * S1:
return Quotes .DefaultIfEmpty() .Aggregate(Quotes.FirstOrDefault() ?? 0.0, (ema, nextQuote) => alpha * nextQuote + (1 - alpha) * ema);