Click here to Skip to main content
15,883,901 members
Articles / Web Development / HTML

WPF FIX Automated Trading Client

Rate me:
Please Sign up or sign in to vote.
4.93/5 (17 votes)
13 Aug 2014CPOL16 min read 43.6K   1.3K   56   20
A demo WPF synthetic order book client UI that manages synthetic orders and submits firm orders to a trading server via FIX

Heathmill WPF FIX AT Client

Introduction

Heathmill's Automated Trading (AT) client demonstrates synthetic order management - how to organise AT rules into a convenient "synthetic order book" user interface (the AT Order Book Client as I’ll refer to it from now on). The client uses a standard of the finance world, FIX, to communicate with a remote trading platform.

In a previous article we talked about a mock FIX auto-matching server we wrote to test our AT Order Book client against. That article contains a brief introduction to FIX, an explanation of how we use FIX messages and a walk-through of the design and code of the auto-matching server.

Here we focus on the AT Order Book client and how it can use AT rules to create "synthetic" orders. These AT orders are referred to as synthetic because they represent trading rules created by a trader (and often only on the client-side), rather than the conventional "firm" orders that are binding offers to buy or sell an amount of something at the specified price. These synthetic orders often aren't much use by themselves, and in our demo AT system they are turned into firm orders by the client and sent via FIX to the trading server. The client also has to deal with the FIX messages coming back from the server and update the synthetic orders to reflect the activity on the server.

Of course, any system that automatically generates firm orders on a live trading server has to be thoroughly tested. Buggy or test/non-production software unleashing a flood of firm orders at crazy prices can lose a lot of money very quickly, as Knight Capital found out the hard way. This is just a demo system and so isn't tested to production code level; however we have designed it so that it can be unit tested and I'll mention a couple of things we did to help keep the client-side code testable.

If this sounds interesting to you then why not download both this AT Order Book client and the Mock FIX server and have a play with the entire demo AT system.

So What Does the Client Do?

  • Connects using FIX 4.4 to a FIX trading server
    • In this case the Mock FIX server from our previous article
  • Displays the orders on the server as sorted order stacks for each contract
  • Submits Limit orders to the server
  • Allows click-trading of orders
  • Create, activate and suspend Iceberg automated trading synthetic orders

The mock FIX server we wrote doesn't actually support click trading so this is done by adding a matching order on the other side of the market to the order being traded; an all-too-common trick/workaround/hack (delete as appropriate) even in real-world trading software.

About the Code

The client is written in C# 4.0 using .NET 4 in Visual Studio 2010 using WPF and the MVVM pattern. The project for the client executable is Heathmill.FixAT.OrderBook.

The basic structure of the client application is based on the UIDemo project by the QuickFIX/n chaps, and some of the classes in the client are either heavily based on, or borrowed entirely from that project. It’s worth reading about UIDemo on the QuickFIX/n site if you’re interested in having a play with either this client or the mock FIX server. Keep in mind this is a demo client so it is prototype code rather than production quality.

Link to the code

The code for the AT Order Book Client is part of the solution for the Mock Server article and can be found at that article's Browse Code link 1.

The Client

Before we go into examples or details, here’s a screenshot of the main window of the client that we can refer back to later:

Heathmill WPF FIX AT Client

As you can see the screen is split into two sections: a Market View that shows the orders in the system as order stacks per symbol, and an AT Orders section which shows any synthetic orders created by Automated Trading rules.

Automated Trading

In this context Automated Trading (AT) is using one or more rules to create orders that have certain behaviours automated. These orders are known as synthetic orders. An example might help here.

Let’s say you want to have an order that is always 5 pips worse than the best price in the market. Rather than having to watch the screen like a hawk and adjust your order every time the best price in the market changes, and run the risk of missing a big move in the market while you make some coffee, things would be a lot easier if the order just updated itself. That’s where automated trading comes in: if you had the option of creating on order that pegs itself against the best order in the market at bestPrice-0.0005 then this would make using the kind of trading strategy vastly simpler, less time intensive and less error prone.

Here AT does not refer to using AI, algorithms, ultra-low latency etc to automatically trade; that’s generally known as algorithmic trading and is not something we’ll go into at all.

Iceberg Orders

The synthetic order type we are using as a demonstration is what’s known as an iceberg order: so-called because, like an iceberg, most of its volume is hidden from sight. Orders for large quantities can often move the market against the trader (due to supply and demand), so it can be in a trader’s interest to only show a fraction of their actual quantity to the market at any one time.

For an iceberg order the trader submits their order with the total quantity they wish to trade and a visible quantity that will be shown to the other traders in the market (the "clip size"). So, for example, if you had 100,000 MSFT shares to sell you might submit an iceberg order of 100,000 with a clip size of 10,000. The synthetic iceberg order would then submit a real order to the trading system for 10,000 MSFT shares, and when this order was fully traded submit another order for 10,000 MSFT shares ("refilling the order"). It would then keep refilling the order until the total of 100,000 MSFT shares is traded.

Our iceberg order also allows you to specify a price delta, as most do, which is the amount that the price of the order is changed when refilling the order. Let’s say you have an order at a price of 1.50 with a delta of 0.01, when the order is refilled for the first time the price of the new actual order submitted to the trading system will be 1.49 (for a buy-order, 1.51 for a sell-order). The second refill will be at 1.48, the third at 1.47 etc. This allows a trader to take into account that if their order is hit then the market is moving in their direction and so the next order they submit (refill) should be at a worse price. Well, worse for the market, better for the trader!

How an iceberg order refills itself

A Sample Iceberg Scenario

Let’s demonstrate how the iceberg order works by going through a sample scenario.

Note that we use a shorthand notation for orders of the form quantity@price (e.g. 1000@1.3902 is a price of 1.3902 and a quantity of 1000).

There are already a number of orders in the system before we start, as you can see from the screenshot below. First we add a buy-side iceberg order for USDCHF at price 0.881, total quantity 10000, clip size 1000, delta 0.001 and activate it. At this point the market looks like this:

The market after inserting and activating the iceberg order but before any trades occur

Our newly activated iceberg order has inserted a regular order (ClOrdID 5017) for 1000@0.881 which sits proudly atop the order stack on the buy-side.

Next someone (actually me since this is a demo but in real life it would be another user) adds a matching order for USDCHF on the sell side of 1000@0.881. This causes a full match of the underlying regular order, so the iceberg refills and submits a new order at a price of (0.881 – 0.001) = 0.880. As you can see from the next screenshot:

After trading at 0.881 the iceberg refills itself by inserting a new order for 1000@0.880

If you look at the USDCHF order stack you can see that our new underlying order (still with ClOrdID 5017) is not top of the stack; that honour goes to the existing order of 100@0.880 (ClOrdID 1013) that was already in the market. The new underling order is next in the stack.

So let’s put in another matching sell order, but this time let’s make it for 2100@0.880. What happens now is that this new sell order causes the following things to happen:

  • Fully matches ClOrdID 1013 100@0.880, leaving 2000@0.880 remaining quantity.
  • Fully matches our underlying of 1000@0.880, leaving 1000@0.880.
  • The iceberg refills by submitting a new underlying order, but with the price delta this new order is 1000@0.879. Since this is now the only buy order left and is at a worse price than the remaining sell order quantity (1000@0.880) that’s where things stop.

So we now have 1000@0.879 at top of book for buy-side and the remaining quantity of the second sell side order, 1000@0.880, on the sell-side:

After trading at 0.880 the iceberg refills itself again at 1000@0.879, since this is worse than the top sell order matching stops

Design

The AT Order Book Client is a WPF application that uses the MVVM pattern. The Heathmill.FixAT.ATOrderBook assembly contains the main application, the xaml for the WPF view and is responsible for creating the view models and the various interface implementations passed into the view models and other classes. The view model and model classes are contained in the Heathmill.FixAT.Client assembly, as are the classes for server communication.

Class diagram, excluding factory classes

Design for Testability

The IServerFacade and IMessageSink are present to aid unit testing of the code. Even though this is a prototype and a high-coverage test suite was not on the roadmap this sort of thing is so ingrained in my coding that I can’t help myself!

As well as being as a mock/fake/stub injection point, IServerFacade is also a Facade and thus serves as an abstraction from the nitty-gritty of FIX messaging and allows us to express the server in more domain-friendly terms for callers, e.g. CreateOrder rather than exposing the implementation of creating and sending NewOrderSingle FIX messages. It would also allow us to connect to non-FIX servers in future without needing to rip out hardwired FIX code.

C#
public interface IServerFacade
{
    void Start();
    void Stop();

    bool CreateOrder(OrderRecord orderDetails);

    bool CancelOrder(string symbol,
                     string clOrdID,
                     MarketSide side,
                     string orderID);

    bool UpdateOrder(OrderRecord oldOrderDetails, OrderRecord newOrderDetails);

    string GetServerSessionID();
    
    event Action<OrderStatus, OrderRecord> OrderExecutionEvent;

    event Action LogonEvent;
    event Action LogoutEvent;
}

IMessageSink is an idea I was introduced to by F# MVP Phil Trelford as a way of allowing unit tests for the VM error and message handling without message boxes popping up and other similar test-ruining behaviour. It also helps enforce the MVVM ideal of having no UI code in the VM.

C#
public interface IMessageSink
{
    void Trace(Func<string> message);
    void Message(Func<string> message);
    void Error(Func<string> message);
}

You can then implement a mock version of this for tests and another version for when you’re actually running the application that merrily pops up message boxes:

C#
public class StandardMessageSink : IMessageSink
{
    // ...

    public void Trace(Func<string> message)
    {
        System.Diagnostics.Trace.WriteLine(message());
    }

    public void Message(Func<string> message)
    {
        if (_messageCallback != null)
            _messageCallback(message());
    }

    public void Error(Func<string> message)
    {
        MessageBox.Show(message(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

Another fairly common trick is to have your messaging / logging code take a Func<string> rather than a string, so that your code doesn’t spend time formatting, say, Trace message strings that are going to be ignored when running in production.

Talking to the Mock FIX Server

Communication with the Mock FIX server is dealt with by the FixServerFacade implementation of IServerFacade, and this uses a FIX Client encapsulated in the (rather poorly named 2) ClientApplication class. ClientApplication is largely based on the QuickFIX/n UIDemo application class UIDemo.QFApp and follows their recommended pattern of implementing QuickFix.IApplication and inheriting from QuickFix.MessageCracker.

We’ve also kept the IFixStrategy interface from the QuickFIX/n UIDemo project. We don’t really use it (the only strategy is an EmptyFixStrategy) however it does provide a useful extension point should the need ever arise for the client to talk to a server that has its own custom FIX fields (as many commercial trading servers do).

Business Logic

Since the business logic for any of the AT synthetic order types lives entirely in the client in our demo system, it constitutes the bulk of the Model. A commercial trading client might well be better off having a local AT order server to keep the client as thin as possible, but for a prototype we can live with a little bit of UI fatness.

The ATOrderMediator is where most of the non-rule-specific business logic of the client lies. It subscribes to the OrderExecutionEvent of the server facade. This means that whenever an order is added, cancelled or matched the AT order mediator finds out about it and takes the appropriate action.

The IcebergOrder type is essentially a state machine that also tracks the quantity left in the iceberg order and refills it when the underlying order is fully matched. The state tracks whether the iceberg order is suspended or activated and handles sending and cancelling underlying orders on the server based on this (following the logic discussed in the Iceberg Orders section).

SmartDispatcher

This is a handy little class taken from the QuickFIX/n UIDemo project designed to simplify getting around the “UI elements can only be updated on the thread that owns them” thing.

You set the Dispatcher instance to use via a call to SetDispatcher:

C#
// Set the main UI dispatcher
SmartDispatcher.SetDispatcher(mainWindow.Dispatcher);

Then subsequent client code can call SmartDispatcher.Invoke to avoid any unwanted cross-thread related exceptions.

FIX Messages

The Code Project article about the Heathmill mock FIX server goes into more detail about the FIX messages sent between client and server for the supported use cases of the system. It also talks more about how we actually deal with FIX sessions and message translation via QuickFIX/n and our own library.

However, to be very brief, the following FIX messages are sent from the client to the server:

  • NewOrderSingle when adding an order.
  • OrderCancelRequest when cancelling an order.

The server sends the following messages to the client:

  • ExecutionReport (with an appropriate ExecType field) when a client action succeeds or an order match occurs.
  • ExecutionReport with ExecType.REJECTED if an attempt to add an order fails.

Unit Testing

If you’ve read about or used MVVM then you know that one of the advantages of this pattern is that the View Model and Model should contain no UI code and can therefore be unit tested. Unfortunately time didn’t allow for much unit testing given that this is a prototype, but were this production code (or if we were being good TDD people) then it would warrant/have much greater test coverage.

As it is the focus of what unit testing was done was on the business logic of the iceberg order, see TestIcebergOrder.cs for the details. Moq was useful when creating a mock for IServerFacade where needed.

There are a number of areas where the testing could be fairly easily extended without too much refactoring. The area that immediately springs to mind is testing how order changes on the server are handled by the client code. A fake IServerFacade with a canned list of calls to OrderExecutionEvent could be used to test the order update handling of the OrderBookViewModel and the order stacks it creates for regular order display.

The fake server could also be used to test how the ATOrderMediator updates AT orders in response to server actions. Although some of this is already covered by the Iceberg Order behavioural tests it would be a good idea to also test things like IcebergOrder.MarketOrderCanceled being called when an OrderExecutionEvent is raised with OrderStatus.Canceled for the OrderRecord corresponding to the underlying order.

It would also be quite easy to test the connection status displayed in the main UI status bar by unit testing ConnectionViewModel.ConnectionStatus by providing a fake IServerFacade implementation with pre-cooked raising of LogonEvent and LogoffEvent.

Also, given that we have our own friendly Mock FIX Server to connect to it would be possible to write system-level tests. It would require some infrastructure work, but creating test drivers that prod the code at the VM level and then see how it responds when dealing with an actual (albeit friendly) server would be invaluable in building confidence in a commercial system. Even more so if the friendly server was scriptable.

How to Connect Two Clients to the Mock FIX Server

I’ve not gone much into how to setup the config for the client (or the Mock FIX Server for that matter) as it’s taken straight from the QuickFIX/n demo system. However one thing that is worth mentioning is how to tweak the client config to allow more than one client to connect to the server.

The quickfix.cfg file specifies the details of the FIX Session to use to connect in the [SESSION] section. The server will only expect one Session with a given SenderCompID so to connect a second client change this ID to a different one that the server is expecting (e.g. CLIENT2). The list of Sessions the server expects can be found in FixAtServer.cfg.

Incidentally modifying quickfix.cfg file is also how you change the version of FIX to use for the client’s SESSION. Don’t actually change it though unless you want to write some FIX handling code or break things; the client currently only supports FIX 4.4.

Conclusion

I’ve introduced you to the Heathmill FIX AT Order Book client and given a brief introduction to Automated Trading and the Iceberg synthetic order type. Iceberg orders really are just the tip of the iceberg (sorry) of what AT can do, and traders are getting more and more demanding of their trading clients as markets move faster due to the proliferation of electronic and algorithmic trading. Adding AT rules to an existing client could be a good move to pacify them, after all nobody wants an angry trader yelling at them.

So, what have we ended up with? Like the Mock FIX Server this is prototype code for demonstration purposes and definitely not suitable for use in anger in production. Apart from the fact that it’s not the prettiest or slickest UI you’ll ever see, the performance is untested, it lacks some basic order management functionality (like actually cancelling or updating market orders) and the error handling, reporting and messaging is pretty basic. But such is the nature of prototypes; the purpose is not to create a commercial trading screen but to demonstrate AT synthetic orders and how useful they can be. I hope we’ve done that.

Footnotes

  1. If anyone knows how to share git repositories between articles properly then that would be a much better solution!
  2. The name ClientApplication is a leftover from the early stages when the app was just this class spewing out messages to screen ... it really ought to have a more descriptive and accurate name.

History

  • 2014-06-05 Initial Version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Argus Media
United Kingdom United Kingdom
Mark Shield is a senior developer at Argus Media. He enjoys coding / tinkering in a variety of languages (C++, C#, Python, F# to name a few) and playing his ever increasing bass guitar collection in his ever decreasing spare time.

Comments and Discussions

 
Generalcan this be used in high frequency trading? Pin
Southmountain23-Jan-16 18:39
Southmountain23-Jan-16 18:39 
GeneralRe: can this be used in high frequency trading? Pin
Mark_Shield24-Jan-16 7:04
Mark_Shield24-Jan-16 7:04 
QuestionLooks awesome and build but how to run? Pin
rtanana15-Aug-14 9:48
rtanana15-Aug-14 9:48 
AnswerRe: Looks awesome and build but how to run? Pin
Mark_Shield15-Aug-14 10:26
Mark_Shield15-Aug-14 10:26 
QuestionNice Pin
Sacha Barber13-Aug-14 22:44
Sacha Barber13-Aug-14 22:44 
AnswerRe: Nice Pin
Mark_Shield13-Aug-14 22:55
Mark_Shield13-Aug-14 22:55 
GeneralMy vote of 5 Pin
Oleg A.Lukin13-Aug-14 19:20
Oleg A.Lukin13-Aug-14 19:20 
QuestionFull Real application sample in WPF Pin
kiquenet.com11-Jul-14 1:35
professionalkiquenet.com11-Jul-14 1:35 
AnswerRe: Full Real application sample in WPF Pin
Mark_Shield13-Aug-14 23:13
Mark_Shield13-Aug-14 23:13 
QuestionWhy WPF? Pin
Shao Voon Wong7-Jun-14 4:16
mvaShao Voon Wong7-Jun-14 4:16 
AnswerRe: Why WPF? Pin
kiquenet.com11-Jul-14 1:20
professionalkiquenet.com11-Jul-14 1:20 
AnswerRe: Why WPF? Pin
Mark_Shield13-Aug-14 23:04
Mark_Shield13-Aug-14 23:04 
I used WPF primarily as it's a technology I know and therefore I could create the demonstration client for this article reasonably quickly. You are correct in saying that WPF has some know performance issues, and so it might not be suitable for a high-performance trading screen working in very volatile markets.

However a lot of trading is done in markets that really aren't that fast-moving or liquid. Some commodities trading (e.g. European power, coal, gas) is done at a far slower pace than oil or FX trading and so microsecond or millisecond latencies aren't that important compared to UI functionality. Also the point of something like Automated Trading is to have a basic set of automated rules that deal with fast market interactions for you.
Questionsample solution Pin
fredatcodeproject5-Jun-14 22:46
professionalfredatcodeproject5-Jun-14 22:46 
AnswerRe: sample solution Pin
Mark_Shield5-Jun-14 23:26
Mark_Shield5-Jun-14 23:26 
GeneralRe: sample solution Pin
fredatcodeproject6-Jun-14 5:48
professionalfredatcodeproject6-Jun-14 5:48 
QuestionNice article about the WPF and how to organise AT rules into a convenient "synthetic order book" user interface Pin
Volynsky Alex5-Jun-14 22:44
professionalVolynsky Alex5-Jun-14 22:44 
AnswerRe: Nice article about the WPF and how to organise AT rules into a convenient "synthetic order book" user interface Pin
Mark_Shield5-Jun-14 23:20
Mark_Shield5-Jun-14 23:20 
QuestionRe: Nice article about the WPF and how to organise AT rules into a convenient "synthetic order book" user interface Pin
Volynsky Alex6-Jun-14 0:24
professionalVolynsky Alex6-Jun-14 0:24 
QuestionIs building a mock server really worth it? Pin
CatchExAs5-Jun-14 6:41
professionalCatchExAs5-Jun-14 6:41 
AnswerRe: Is building a mock server really worth it? Pin
Mark_Shield5-Jun-14 23:20
Mark_Shield5-Jun-14 23:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.