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
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.
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:
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.
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.
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!
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
email@example.com 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:
Our newly activated iceberg order has inserted a regular order (ClOrdID 5017) for
firstname.lastname@example.org 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
email@example.com. 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:
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
firstname.lastname@example.org (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
email@example.com. What happens now is that this new sell order causes the following things to happen:
- Fully matches ClOrdID 1013
firstname.lastname@example.org remaining quantity.
- Fully matches our underlying of
- The iceberg refills by submitting a new underlying order, but with the price delta this new order is
email@example.com. Since this is now the only buy order left and is at a worse price than the remaining sell order quantity (
firstname.lastname@example.org) that’s where things stop.
So we now have
email@example.com at top of book for buy-side and the remaining quantity of the second sell side order,
firstname.lastname@example.org, on the sell-side:
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.
Design for Testability
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.
public interface IServerFacade
bool CreateOrder(OrderRecord orderDetails);
bool CancelOrder(string symbol,
bool UpdateOrder(OrderRecord oldOrderDetails, OrderRecord newOrderDetails);
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.
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:
public class StandardMessageSink : IMessageSink
public void Trace(Func<string> message)
public void Message(Func<string> message)
if (_messageCallback != null)
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 is largely based on the QuickFIX/n
UIDemo application class
UIDemo.QFApp and follows their recommended pattern of implementing
QuickFix.IApplication and inheriting from
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).
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.
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.
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).
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
Then subsequent client code can call
SmartDispatcher.Invoke to avoid any unwanted cross-thread related exceptions.
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.
ExecType.REJECTED if an attempt to add an order fails.
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
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.
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
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.
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.
- 2014-06-05 Initial Version