Posts in  ddfplus

6.20.2013

Part 3 - Integrating with ddfplus - Reactive benefits with commodity option barrier events

Barchart Market Data Solutions provides real-time market data feeds (ddfplus quote service) for equities, indices, futures and foreign exchange markets. I've worked with their platform in the past which makes this a great opportunity to share how these techniques work with a real system.

Creating the observable quote stream

In Part 1 I described how to wrap an event based interface to create an observable quote stream. The ddfplus API comes with a simple Client interface exposing several events, one of which we can use to be notified of new quotes (NewQuote). Here's how we create the quote stream:

    private static IObservable<Quote> CreateQuoteStream(Client client)
    {
        return Observable
            .FromEventPattern<Client.NewQuoteEventHandler, Client.NewQuoteEventArgs>(h => client.NewQuote += h, h => client.NewQuote -= h)
            .Select(e => e.EventArgs.Quote);
    }

Thanks to using a real system and running an integration test, I discovered that FromEventPattern is the overload to use, the reason: use FromEventPattern if the events follow the standard .net (sender, args) convention. Lastly, I added a Select to project just the quote into my new quote stream.

Testing

If you would like to add some confidence in this transformation, consider a smoke test. The client will always return the "last" quote per symbol upon connecting. This will give you the ability to expect some data in a smoke test.

An alternative or complementary strategy would be to setup notifications if you don't receive quotes when you expect them. This is a great way to proactively address risk in a real time system. I'll address techniques to add this monitoring in subsequent posts.

Beyond this there's not much to test as the Rx framework is doing the heavy lifting and is well tested.

ddfplus quote source

Obviously hooking up to the event isn't enough, we need to tell the client to start listening for data and what to listen for. Fortunately this is very simple:

public class ddfplusQuoteSource
{
    private readonly Client _Client;
    public readonly IObservable<Quote> QuoteStream;

    public ddfplusQuoteSource()
    {
        _Client = new Client();
        QuoteStream = CreateQuoteStream(_Client);
        SetupConnection();
    }

    private static IObservable<Quote> CreateQuoteStream(Client client)

    private void SetupConnection()
    {
        Connection.Username = Config.UserName;
        Connection.Password = Config.Password;
    }

    public void Start(IEnumerable<string> symbols)
    {
        _Client.Symbols = String.Join(",", symbols);
    }

    public void Stop()
    {
        _Client.Symbols = string.Empty;
        Connection.Close();
    }
}

Steps

  • Create a Client instance.
  • Create the observable using our CreateQuoteStream above.
  • Set user name and password.
  • To start, provide a list of comma delimited symbols.
  • To stop, clear the symbol list.

Testing this out

Now let's put this to use to print quotes to the console:

var source = new ddfplusQuoteSource();
source.QuoteStream.Subscribe(PrintQuote);
var symbols = new[] {"ZC^F"};
source.Start(symbols);

Steps

  • Create our observable adapter ddfplusQuoteSource
  • Subscribe and print quotes using PrintQuote
  • Start listening for CME Globex Corn futures, ZC indicates CME Globex Corn, ^F indicates all futures contracts

Here's what we're printing:

private static void PrintQuote(Quote quote)
{
    var currentSession = quote.Sessions["combined"];
    Console.WriteLine(new {quote.Symbol, currentSession.Day, currentSession.Timestamp, currentSession.High, currentSession.Low});
}

Quotes have two sessions: current (called "combined") and previous. For new lows and highs we are only interested in the current session.

Next

Creating a simple observable adapter is pretty straightforward with the ddfplus API. Next, we'll look at adding some separation and testing between the ddfplus API and our application, like we did in Part 2.