Running VWAP Calculation Using Reactive Extensions for .NET


Reactive Framework Labs

This article is one from the “Processing Financial Data with Microsoft Reactive Framework (Reactive Extensions for .NET)” series of articles that demonstrate some basic applications of Rx framework to financial data. This article shows how to calculate a running VWAP (volume weighted average price over a defined window of time). Other articles in the series are:

Visual Studio 2008 solution containing full source code for all examples can be downloaded here.

Calculating VWAP/Sliding Window Implementation

We will use this simple “Trade” type to represent a trade event. To simplify things we will only consider Price and Volume:

class Trade
{
    public double Price { get; set; }
    public int Volume { get; set; }
}

The following “TradeWithVWAP” type wraps underlying trade and attaches running VWAP value to it. It is used for calculation output:

class TradeWithVWAP
{
    public Trade Trade { get; set; }
    public double VWAP { get; set; }
}

Our main module starts with a simple market data generator that produces infinite stream of random prices ($30 to $33 range) at random volumes (1,000 to 100,000 shares) at a random frequency (0 to 3 seconds between trades). BuildVwapFeed functions takes generated trade stream and converts it to another stream with running VWAP attached to every trade. And finally we simply subscribe to VWAP-wrapped feed and output the results.

static void Main(string[] args)
{
    // Market data simulator
    var rnd = new Random();
    IObservable<Trade> feed =
        Observable.Defer(() =>
            Observable.Return(new Trade
            {
                Price = Math.Round(30.0 + 3 * rnd.NextDouble(), 2),
                Volume = 1000 + rnd.Next(0, 100000) / 100 * 100
            })
            .Delay(TimeSpan.FromSeconds(3 * rnd.NextDouble())))
        .Repeat();
    
    // Build a wrapper feed to add running VWAP to each trade
    IObservable<TradeWithVWAP> vwap = BuildVwapFeed(
        feed,
        TimeSpan.FromSeconds(5));

    // Subsribe and print results
    vwap.Subscribe(f => Console.WriteLine(
        "Price={0}, Volume={1:#,##0}, VWAP={2}",
        f.Trade.Price,
        f.Trade.Volume,
        f.VWAP));
    Console.ReadKey(true);
}

“BuildVwapFeed” takes two parameters: underlying feed and desired sliding window for VWAP calculation. The first thing it does is time stamping the incoming feed. This is to keep track of an individual trade position within a sliding window. Time stamping is built into Reactive Framework and is as simple as applying a “Timestamp” operator. Timestamp<T> takes a stream of type T and converts it to a stream of Timestampted<T>. Then we allocate a list of Timestampted<T> – this is where we keep the trades currently inside our sliding window.

The “Do” operator is used to maintain the sliding window. The “Do” operator simply repeats the stream it wraps but can produce arbitrary side effects. We use the operator to add new trades to sliding window and to remove trades that have expired.

After the sliding window is updated we no longer need the timestamp. We get rid of it using another Rx built-in operator: RemoveTimestamp<T>. The last code block transforms incoming feed into “VWAP-stampted” by using the sliding window to calculate and attach running VWAP to each trade:

private static IObservable<TradeWithVWAP> BuildVwapFeed(
    IObservable<Trade> feed,
    TimeSpan slidingWndLen)
{
    // Timestamp original feed
    var timestampted = feed.Timestamp();

    // Maintain a sliding window of recent trades
    var wnd = new List<Timestamped<Trade>>();
    var slidingWindowFeed = timestampted.Do(f =>
    {
        // remove expired trades
        while (
            wnd.Count > 0 &&
            f.Timestamp - wnd.First().Timestamp > slidingWndLen)
        {
            wnd.RemoveAt(0);
        }
        // add newest trade
        wnd.Add(f);
    });

    // Calculate running VWAP from trades in the sliding window
    var vwap =
        from w in slidingWindowFeed.RemoveTimestamp()
        let windowVolume = wnd.Sum(l => l.Value.Volume)
        let windowTotal = wnd.Sum(
            l => l.Value.Volume * l.Value.Price)
        select new TradeWithVWAP
        {
            Trade = w,
            VWAP = Math.Round(windowTotal / windowVolume, 2)
        };
    return vwap;
}

There are many other ways to produce VWAP on-the-fly. The implementation shown does not claim to be very efficient. But it does demonstrate how easy, almost trivial, it is to implement non-trivial stream transformations with Rx. Building your own CEP engine may soon become as easy as LINQ, Rx, and .NET…

Advertisements
6 comments

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

%d bloggers like this: