Calculating Moving Average of Stock Quotes with Reactive Extensions

I am getting into Rx – Reactive Extensions and ReactiveUI a bit as well and am going through the Rx Workshop on Channel 9.  The 5th episode in the series, which talks about grouping, buffers, windows and other advanced stream manipulation gave rise to an challenge I decided to undertake.

Given a stream of StockQuote[s], and the code attached to the exercise provides the following StockQuote class, how can we attach a 5, 10 or x- day moving average for the high, low, close, or other data point on the StockQuote class.

StockQuote class;


class StockQuote
{
  public string Symbol { get; set; }
  public DateTime Date { get; set; }
  public decimal Open { get; set; }
  public decimal High { get; set; }
  public decimal Low { get; set; }
  public decimal Close { get; set; }

  // helper methods omitted because they are irrelevant
}

I think I finally got it.  The code is below, but the approach the following:

  1. Add the Average properties to the original StockQuote class.  So if  you are averaging High and Low, add AverageHigh and AverageLow:

class StockQuote
{
 public string Symbol { get; set; }
 public DateTime Date { get; set; }
 public decimal Open { get; set; }
 public decimal High { get; set; }
 public decimal Low { get; set; }
 public decimal Close { get; set; }

 public decimal AverageHigh { get; set; }
 public decimal AverageLow { get; set; }

 // helper methods ommitted because they are irrelevant
}

2. Use the Buffer method to create sliding buffers of stockquotes you want to aggregate.  If each stock quote represents a day in life of the stock, then aggregating 10 StockQuote instances would create a 10-day moving average, aggregating 100 of them would create an 100-day moving average.  The more days you aggregate the slower the program would run.

Use the 2nd parameter to the buffer method to specify how many instances of the stock quotes separate one buffer from the next.  We’ll use value of 1 to create sliding buffers from one stock quote to the next.

3. Finally use the aggregate function to populate running averages for StockQuote instances  that appear last in the buffer list.


//Splitting a stream into buffers of 20 days, each buffer starting on the
//next StockQuote instance.  Because we are
//returning the last Stock Quote instance from the buffer
//the first output of this observable would be the 20th instance of the StockQuote
//with its averages calculated

var quotesWithMovingAverage = quotes.Where(q => q.Symbol == "MSFT")
    .Buffer(20, 1).Select(list => AverageHighLow(list));

private StockQuote AverageHighLow(IList<StockQuote> arg)
{
  int i = 0;
  var last = arg.Last();

  arg.Aggregate(arg.First(), (a, sq) =>
  {
    sq.AverageHigh = (a.AverageHigh * i  + sq.High) / (i + 1);
    sq.AverageLow = (a.AverageLow * i  + sq.Low) / (i + 1);
    ++i;
    return sq;
  });

  return last;
}

This may not be the ideal implementation. If anyone can suggest a better one, please comment.

Thanks.

Advertisements

One thought on “Calculating Moving Average of Stock Quotes with Reactive Extensions

  1. Pingback: Calculating Moving Average (or other aggregations) using LINQ | Software Development and more

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s