RX: Converting a sequence from a sequence, for example. exponential moving average

How can you do in RX a simple sequence conversion from sequence?

Suppose we want to do an exponential moving average transformation of IObservable noisySequence.

Whenever noisySequence is ticking, emaSequence should point and return a value (previousEmaSequenceValue * (1-lambda) + latestNoisySequenceValue * lambda)

I think we use themes, but how exactly?

    public static void Main()
    {

        var rand = new Random();

        IObservable<double> sequence  = Observable
            .Interval(TimeSpan.FromMilliseconds(1000))
            .Select(value => value + rand.NextDouble());

        Func<double, double> addNoise = x => x + 10*(rand.NextDouble() - 0.5);

        IObservable<double> noisySequence = sequence.Select(addNoise);

        Subject<double> exponentialMovingAverage = new Subject<double>(); // ??? 


        sequence.Subscribe(value => Console.WriteLine("original sequence "+value));
        noisySequence.Subscribe(value => Console.WriteLine("noisy sequence " + value));
        exponentialMovingAverage.Subscribe(value => Console.WriteLine("ema sequence " + value));

        Console.ReadLine();
    }
+6
source share
3 answers

Here's how you can attach state to a sequence. In this case, it calculates the average of the last 10 values.

var movingAvg = noisySequence.Scan(new List<double>(),
(buffer, value)=>
{
    buffer.Add(value);
    if(buffer.Count>MaxSize)
    {
        buffer.RemoveAt(0);
    }
    return buffer;
}).Select(buffer=>buffer.Average());

Window ( ), .

noisySequence.Window(10)
   .Select(window=>window.Average())
   .SelectMany(averageSequence=>averageSequence);
+7

Buffer -

var movingAverage = noisySequence.Buffer(/*last*/ 3,
    /*move forward*/ 1 /*at a time*/)
    .Select(x => (x[0] + x[1] + x[2]) / 3.0);

, Scan, Aggregate , .

:

+4

! , Scan

    const double lambda = 0.99;
    IObservable<double> emaSequence = noisySequence.Scan(Double.NaN, (emaValue, value) =>
        {
            if (Double.IsNaN(emaValue))
            {
                emaValue = value;
            }
            else
            {
                emaValue = emaValue*lambda + value*(1-lambda);
            }
            return emaValue;
        }).Select(emaValue => emaValue);
+1

All Articles