Click here to Skip to main content
15,885,244 members
Articles / Web Development / HTML

Mock FIX Trading Server

Rate me:
Please Sign up or sign in to vote.
4.92/5 (16 votes)
13 Aug 2014CPOL24 min read 59.8K   1.5K   51   24
A mock FIX trading server for use when testing FIX trading clients

Introduction

In the sweltering (well, for Britain) summer of 2013 we at Heathmill decided to create a demonstration trading UI client that can use Automated Trading (AT) rules. As is standard in the finance world we wanted the client to communicate using the FIX protocol, however we couldn’t find a mock FIX server or engine to test out our client.

This FIX server, as detailed below, can be used for testing FIX client applications. It handles the incoming FIX session connections and orders from the clients and uses basic auto-matching behaviour to allow orders to be traded. This article is about the Domain Model for the system, FIX message handling and the design and implementation of the auto-matching server. Another article will follow which will outline automated trading via synthetic orders and the AT Order Book demo trading client itself.

This isn’t an article about trading (nor am I in any position to write such a thing) so I won’t go into any detail on trading. If you want to know about the risks of high leverage, naked short selling, Elliott waves or anything like that then I’d suggest a trip to Investopedia to get you started.

The code

The server is written in C# 4.0 and .NET 4 using Visual Studio 2010. It uses NuGet to obtain 3rd party packages (build instructions1).

Example Client

The solution file also contains an example client to use with the server in the Heathmill.FixAT.ATOrderBook project. There's a separate Code Project article that talks about the client.

So What Does the Server Do?

  • Accepts connections from FIX clients
  • Supports Good-‘til-Cancelled Limit orders
  • Auto-matches orders to execute trades
  • Sends execution reports for orders and trades to connected clients
  • Supports FIX 4.2 and FIX 4.4 sessions

If any of that doesn’t make sense then fear not, I’ll explain more about the terminology used in the rest of the article.

What is FIX?

FIX stands for Financial Information eXchange, the protocol devised in the 90s in an attempt to create a common language for electronic trading systems. On a very simple level FIX defines a series of messages and message exchange workflows to represent financial information and workflows.

See the Wikipedia article and the FIX Protocol Organisation website for more detail on FIX. More on how we actually use FIX in the “How do we use FIX?” section below, after we’ve introduced our Domain Model.

Domain Model

At Heathmill we're fans of Domain Driver Design (also see Eric Evans’s tome2 of the same name for an excellent discussion of the matter) and so we decided to create a simple domain model for our system. The domain is centred on the concept of an Order and how Orders are sorted and matched, and is shared between the AT Order Book client and the server.

Being a Domain Model, this section also serves as an introduction to the core domain concepts for our trading platform. If you’re familiar with trading systems then you can probably just jump straight to either the “How do we use FIX?” section or the “Server Design” section below depending on what you want to know or find interesting.

Order

Orders are one of the core concepts of any trading platform. An order represents how much someone is willing to pay to either buy or sell a specified amount of a particular contract. So, for example, if I’m willing to pay $38 per share for 1000 Microsoft shares then I would enter a Bid order (aka Buy order) for {price=38, quantity=1000, contract=MSFT, side=Bid} into the system. If you were willing to sell 500 Microsoft shares for $39 you would enter an Ask order (aka Offer or Sell order) of {price=39, quantity=500, contract=MSFT, side=Ask} into the system.

Orders are sometimes referred to by the common shorthand of quantity@price, e.g. 1000@38 and 500@39 for the examples above. Users of the system are generally shown an Order Stack for each Contract they’re interested in, where an order stack is a list of the Bid and Ask orders for that contract, sorted so that the best prices are at the top of the stack.

Types of Order

There are a number of types or order that FIX supports; since this server is just for testing purposes what it supports is perhaps best shown from the code:

C#
// TODO Support the other types in QuickFix.Fields.OrdType
public enum OrderType
{
    //Market,
    Limit,
    //Stop,
    //StopLimit,
}

A limit order is an order placed to buy or sell a specific quantity of something at a specified price or better. If you’re curious about what the other order types are then it’s worth looking them up on Investopedia.

Since the server is here to test and demonstrate the AT Order Book and the fact that it can create synthetic orders that mimic order types that are not supported on an existing server, the only types of order that are supported on the server are Good ‘til Cancelled orders with no hidden quantity and no All-or-None option.

In reality order behaviour such as like All-or-None or Immediate-or-Cancel would be very hard to create synthetic versions of and would almost certainly need to be implemented on the server. However, other order types such as Good-‘til-Date, Market Orders and Stop/Limit Orders are candidates for synthetic order types. Hidden Quantity / Iceberg orders are actually the example synthetic order type for the Heathmill AT Order Book client.

Contract

As mentioned above each order is placed on a given contract. In the system we’ve created here a contract is simply represented as a symbol (e.g. MSFT, AAPL, EURUSD). This would be enough for a basic stock or forex trading system but many other systems (commodities, options, equity derivatives, etc) have far more complicated contracts involving things like delivery dates, strike prices, underlying contracts etc.

For the testing we need the simple symbol contract is sufficient. Extending contracts to embrace the added complexity of things like contract expiry, front month rolling, options pricing etc is left (as so many things are) as an exercise for the reader.

Order Sorting

As mentioned above, orders are usually sorted so that the “best” order is at the top of the list (“stack”). For a Bid this is the order with the highest price (person willing to pay the most) and for an Offer this is the order with the lowest price (person willing to sell for the least).

Orders with the same price have to be sorted using different criteria, and in our case the sorting is then done by earlier last update time, then larger quantity and then an arbitrary tie-break (internal ID). This is a fairly standard way of sorting orders in a trading platform and is done to reward the trader that has had their order at that price in the market longest.

As you can imagine order sorting is important when considering auto-matching of orders, and speaking of which.

Order Matching

There are, broadly speaking, two ways of carrying out trades on a trading platform. The first, generally known as click-trading, is where a user actively selects the order they wish to trade (often by double-clicking or right-clicking, hence the name) and the server removes the order from the system and generates a trade3. Our server does not support click-trading, although as the forthcoming article about our AT Order Book client shows it uses a common trick to circumvent the server’s limitation, namely adding a matching order on the opposite side of the market.

What our server does support is the other main style of carrying out trades: auto-matching. This is where the server automatically generates trades when there is a Bid order and an Ask order at the same price: if I’m prepared to pay $38.50 to buy MSFT shares and you’re prepared to sell your MSFT shares at $38.50 then we have a deal!

Auto-matching (often just referred to as Matching) also has to consider the situation where there is more than one order at the best price (aka top-of-book) for a given side of the market. If there are two 100@38.50 orders on the Bid side and you enter an Offer of 200@38.50 then you’re not going to be happy if it only trades one of the bids so the matching algorithm must work out what total quantity is available on each side of the market at the top-of-book.

The matching algorithm our server uses is not a complicated algorithm; some of the trickier things to deal with in matching (e.g. All-or-None orders, Immediate-or-Cancel orders) are not in our system. It simply gets all the orders at the top-of-book, works out which side has the least quantity and proceeds to match orders for each market side in turn until that quantity is filled.

As ever the whole truth lies in the code, and you can see all the details by looking at the code in StandardOrderMatcher.cs.

How do we use FIX?

The Heathmill FIX AT client and server communicate via the QuickFIX/n library. QuickFIX/n is a native .NET version of the C++ QuickFIX library and supports FIX 4.1, 4.2, 4.3, 4.4 and 5.0 via type-safe message handling and implementation of the Initiator / Acceptor pattern from FIX. QuickFIX/n communicates using TCP via sockets.

Our server implements support for FIX 4.2 and FIX 4.4, mainly as an example of how we would support client connections from multiple FIX versions.

The main application class (ServerApplication) is an implementation of the QuickFix.IApplication interface and inherits from QuickFix.MessageCracker, as recommended by QuickFIX/n.

As an abstraction from the nitty-gritty of FIX and FIX versioning, and as an aid to testability, we have used Facades when sending FIX messages. We have also factored out the FIX message generation and translation into a Domain-Driven-Design-compatible services assembly, Heathmill.FixAT.Services

Heathmill.FixAT.Services

This service assembly handles FIX message generation and translation between Domain objects and FIX fields and messages. The IFixMessageGenerator interface is provided as a way of making calling code FIX-version-agnostic, and the nitty-gritty of turning, say NewOrderSingle messages into orders is handed by TranslateFixMessages and TranslateFixFields.

FIX Message Workflow

For a given financial workflow there is a FIX workflow describing which FIX messages to send and in what order. In this section we’ll go through the workflows the Heathmill system supports and show the FIX messages that are sent in each case. In each case where the workflow is initiated by the trader / client the first use case diagram represents the success case (e.g. the new order is accepted) whereas the second represents the failure case (e.g. the new order is rejected for, say, invalid price).

These use cases show the message types being sent and the key fields that differentiate the message (e.g. ExecType for an ExecutionReport). There are also a whole slew of other fields to fill in for the various messages (e.g. LeavesQty, CumQty, AvgPrice) that are used to indicate the state of the system. Please see the code (e.g. Fix44MessageGenerator) for the full details of grinding through the message fields. Also, fixwiki.org is an excellent resource for explaining the message fields and their expected values.

User adds an order

Adding an order

User cancels an order

Cancelling an order

User updates an order

When updating an existing order we have implemented it using an OrderCancel and a NewOrderSingle from the client because we didn’t have time to extend our server to handle OrderCancelReplace messages. It is, therefore, currently implemented in the same way as using the “User cancels an order” and then the “User adds an order” workflows above.

However if time allowed then the workflow we should have had is:

How updating an order should work

The server fills an order when matching

When the server fills an order

Note that for a partial fill then ExecType.PARTIAL_FILL and OrdStatus.PARTIALLY_FILLED should be used instead.

ClOrdID

All orders in the system are assigned an identifier by the client when they are submitted called the ClOrdID. A new ClOrdID for an order must also be specified when cancelling that order. From fixwiki.org:

“Unique identifier for Order as assigned by the buy-side (institution, broker, intermediary etc.) ... Uniqueness must be guaranteed within a single trading day. ... “

Since our system is only a demo system the client simply uses an increasing counter with baseline offsets based on the order type.

ExecID

You may notice from the code that some of the server generated FIX messages have an execID field. To quote fixwiki.org:

“Unique identifier of execution message as assigned by sell-side (broker, exchange, ECN)”

In our case this is just a monotonically increasing counter that is maintained and incremented by the server. A commercial server would need to ensure that this identifier is indeed unique and that (to quote fixwiki.org again):

“Uniqueness must be guaranteed within a single trading day or the life of a multi-day order.”

On our server this ID is not persisted so a server restart means the ID will be reset so an intra-day reset would be A Bad Thing. Yet another of those production-vs-prototype things!

Server Design

The server is based around a few design patterns (Command, Facade, and Strategy), Repositories and Mediators and judicious use of queues, message handlers and Tasks.

The major infrastructure classes are shown below in a class diagram. Methods, properties etc are not shown in the hope of keeping it readable.

Major server classes

The architecture is relatively simple: the guts are an input command queue with command processor and an output command queue with command processor. The incoming FIX messages are handled via an IFixMessageHandler and the translated commands placed on the input queue. The input command processor handles the input command asynchronously using a Task and places a command on the output queue to indicate the result. The output command processor then synchronously processes the output command (e.g. SendAcceptNewOrder, SendRejectNewOrder) and sends the appropriate message back to the client, and any other connected clients if needs be.

I’ll go over some of the actual mechanics of processing these commands in the next section.

Server Implementation: Edited Highlights

There is a fair amount of code for the server, and some of it is concerned with the mundane housekeeping tasks that any system like this must do (e.g. storing orders and then looking them up again). It would probably bore you to tears were I to talk you through each and every line of code so what we’ll do instead is go over some of the more important things that happen in the server in more detail at the code level.

Commands, queues and processors

The main processing mechanism in the server is based around the Command Pattern. The commands are derived from a typical command interface ICommand:

C#
namespace Heathmill.FixAT.Server.Commands
{
    internal interface ICommand
    {
        void Execute();
    }
}

Each derived command class then carries out whatever actions it needs to when executed. As an example we’ll look at what Commands.AddOrder does in the “Server receives a new message” section below. The various derived commands are created via the CommandFactory.

There are two queues: an input queue for incoming commands and an output queue for outgoing commands. Each of these queues is an instance of CommandQueue, which is just a wrapper around a Queue<ICommand> with simple locking:

C#
internal class CommandQueue : ICommandQueue
{
    private readonly Queue<ICommand> _queue = new Queue<ICommand>();
    private readonly object _queueLock = new object();

    public void Enqueue(ICommand command)
    {
        lock (_queueLock)
        {
            _queue.Enqueue(command);
        }
    }

    public ICommand Dequeue()
    {
        lock (_queueLock)
        {
            return _queue.Count > 0 ? _queue.Dequeue() : null;
        }
    }

    public void Clear()
    {
        lock (_queueLock)
        {
            _queue.Clear();
        }
    }
}

A production server would no doubt want a slightly more heavyweight queuing mechanism, such as a proper Producer-Consumer queue, a blocking circular buffer or some other method that allows for controlling the size of the queue and possibly the rate at which items are enqueued and dequeued.

Incoming FIX messages are translated into commands and placed on the input command queue. These are then processed by the input CommandProcessor. The CommandProcessor creates a long running task to dequeue commands from the input queue and then calling Execute on the ICommand object using the command processing Strategy given to the processor:

C#
internal class CommandProcessor
{
    private readonly CancellationTokenSource _cancellationTokenSource;
    private readonly ICommandQueue _commandQueue;
    private readonly ICommandProcessingStrategy _processingStrategy;

    public CommandProcessor(ICommandProcessingStrategy processingStrategy,
                            ICommandQueue commandQueue)
    {
        _processingStrategy = processingStrategy;
        _commandQueue = commandQueue;

        _cancellationTokenSource = new CancellationTokenSource();
        var token = _cancellationTokenSource.Token;
        var task = new Task(
            () =>
                {
                    while (!token.IsCancellationRequested)
                    {
                        var cmd = _commandQueue.Dequeue();
                        while (cmd != null)
                        {
                            _processingStrategy.ProcessCommand(cmd.Execute);
                            cmd = commandQueue.Dequeue();
                        }
                        Thread.Sleep(100);
                    }
                },
            token,
            TaskCreationOptions.LongRunning);
        task.Start();
    }

    public void Stop()
    {
        _cancellationTokenSource.Cancel();
    }
}

The processing strategy for the input queue is an asynchronous, task-based one:

C#
internal class TaskBasedCommandProcessingStrategy : ICommandProcessingStrategy
{
    private readonly TaskFactory _taskFactory = new TaskFactory();

    public void ProcessCommand(Action processingFunction)
    {
        _taskFactory.StartNew(processingFunction);
    }
}

Note that this means the server is not a real-time server: there is nothing to guarantee that any given input command will be executed within a particular time-period. For a real-time server you would need a task scheduler of some kind to ensure that tasks are completed within a certain time limit, such as in Alexy Shelest’s excellent Code Project article on his real-time WPF trading UI.

When the input commands are executed they place a task on the output queue based on the result of their actions (e.g. SendAcceptNewOrder if an AddOrder task succeeds). The output queue and output command processor work in exactly the same way as the input queue, except that the command processing strategy in this case is a synchronous one:

C#
internal class SynchronousCommandProcessingStrategy : ICommandProcessingStrategy
{
    public void ProcessCommand(Action processingFunction)
    {
        processingFunction();
    }
}

The commands placed on the output queue communicate the result of the incoming FIX messages back out to the sending FIX Session (and other connected FIX Sessions where appropriate) or to send notifications when order matching occurs.

When a FIX client connects

When a FIX client connects it does so by creating a FIX Session; all communication with the client is then carried out via this Session.

Building on top of the QuickFix.MessageCracker class and implementing QuickFix.IApplication, the main Application class (ServerApplication) receives the incoming FIX sessions and assigns a message handler based on the version of FIX the session is using:

C#
public class ServerApplication : MessageCracker, IApplication
{
    // ...

    public void OnCreate(SessionID sessionID)
    {
        try
        {
            _sessionMediator.AddSession(sessionID, GetHandler(sessionID)); 
        }
        catch (FixATServerException e)
        {
            _messageCallback("ERROR: " + e.Message);
        }
    }

    // ...

    private IFixMessageHandler GetHandler(SessionID sessionID)
    {
        switch (sessionID.BeginString)
        {
            case BeginString.FIX42:
                return _fix42MessageHandler;
            case BeginString.FIX44:
                return _fix44MessageHandler;
            default:
                throw new FixATServerException(
                    string.Format("FIX version {0} not supported by server",
                                  sessionID.BeginString));
        }
    }

    // ...
}

Incoming messages from that FIX session are then handled by the IFixMessageHandler instance associated with the session.

The other main event that happens when a Session connects occurs in the ServerApplication.OnLogon method:

C#
public void OnLogon(SessionID sessionID)
{
    try
    {
        _sessionMediator.SessionLoggedIn(sessionID);
        _sessionMediator.SendOrders(sessionID, _orderMediator.GetAllOrders());
    }
    catch (FixATServerException e)
    {
        _messageCallback("ERROR: " + e.Message);
    }
}

In addition to letting the SessionMediator know that the Session has logged in it also send all the orders on the server to the newly connected Session. A newly connected client must be sent the existing orders in the system otherwise traders would only be able to trade with themselves; as you can appreciate this is pretty important for a trading platform!

Server receives a message from a client

This is the key part of almost any server; so what happens when our server gets an incoming FIX message from a client? We’ll go through the case where a FIX 4.4 client tries to add a new order to the system via a NewOrderSingle FIX message.

Receiving the message and putting a Command on the input queue

The message is received via the QuickFix.IApplication.FromApp method in ServerApplication:

C#
public void FromApp(Message message, SessionID sessionID)
{
    _messageCallback("IN:  " + message);
    try
    {
        Crack(message, sessionID);
    }
    catch (UnsupportedMessageType)
    {
        _messageCallback(
            string.Format("Unsupported message type: {0}", message.GetType()));
    }
}

This then calls QuickFix.MessageCracker.Crack which uses reflection to call the correct overload of OnMessage, in this case:

C#
public void OnMessage(NewOrderSingle n, SessionID sessionID)
{
    _fix44MessageHandler.OnMessage(n, sessionID);
}

The Fix44MessageHandler.OnMessage overload calls the Service assembly to translate the FIX message into an OrderDetails class, and then asks the MessageHandlerCommandFactory (a wrapper around the regular CommandFactory that adds convenience methods and deals with FIX SessionIDs) to enqueue an AddOrder command:

C#
internal class Fix44MessageHandler : IFixMessageHandler
{
    // ...

    public void OnMessage(NewOrderSingle n, SessionID sessionID)
    {
        var execID = _execIdGenerator();
        try
        {
            var orderData = TranslateFixMessages.Translate(n);
            _commandFactory.EnqueueAddOrder(_messageGenerator, sessionID, orderData, execID);
        }
        catch (QuickFIXException e)
        {
            var rejectMessage = "Unable to add order: " + e.Message;
            var message = CreateFix44Message.CreateRejectNewOrderExecutionReport(n,
                                                                                 execID,
                                                                                 rejectMessage);
            _fixFacade.SendToTarget(message, sessionID);
        }
    }

    // ...
}

MessageHandlerCommandFactory.EnqueueAddOrder then looks up the internal Session ID, uses the CommandFactory to create an AddOrder command and adds this to the input queue.

C#
internal class MessageHandlerCommandFactory
{
    // ...

    public void EnqueueAddOrder(IFixMessageGenerator messageGenerator,
                                SessionID sessionID,
                                OrderData orderData,
                                string execID)
    {
        var internalSessionID = _sessionMediator.LookupInternalSessionID(sessionID);
        var cmd = _commandFactory.CreateAddOrder(messageGenerator,
                                                 internalSessionID,
                                                 orderData,
                                                 execID);
        _commandFactory.IncomingQueue.Enqueue(cmd);
    }

    // ...
}

So we now have an AddOrder command on the input queue. In the not-too-distant future the input command processor will pick up the command from the input queue, which is where we rejoin the action.

Processing the AddOrder command

As seen above in the “Commands, queues and processors” section the input command processor dequeues commands from the input command queue and spins up a Task to call Execute on the command; AddOrder.Execute contains:

C#
internal class AddOrder : ICommand
{
    // ...

    public void Execute()
    {
        try
        {
            var order = _orderMediator.AddOrder(// ... order details);
            var successCmd = _commandFactory.CreateSendAcceptNewOrder(_sessionID, order);
            _commandFactory.OutgoingQueue.Enqueue(successCmd);

            // Kick off matching for the contract given we have a new order
            var matchOrders = _commandFactory.CreateMatchOrders(_orderData.Symbol);
            _commandFactory.IncomingQueue.Enqueue(matchOrders);
        }
        catch (FixATServerException e)
        {
            var rejectMessage = "Unable to add order: " + e.Message;
            var rejectCmd = _commandFactory.CreateSendRejectNewOrder(// ...);
            _commandFactory.OutgoingQueue.Enqueue(rejectCmd);
        }
    }
}

As you can see this is where the action happens. Firstly it asks the OrderMediator to add a new order. The OrderMediator carries out various pieces of validation before adding the order to the OrderRepository. If any of the validation fails then it throws a FixATServerException and the handling code adds a SendRejectNewOrder command to the output queue. In this case we’d jump directly to the “Processing the output command” section below. However, let’s now assume that the order is valid and is added to the OrderRepository successfully.

In the case where the order is added successfully the code then does two things: firstly it creates a SendAcceptNewOrder command to the output queue indicating success and then goes on to add a MatchOrders command for the order’s symbol to the input queue. Since we have a new order in the system then there are now new possible matches for that symbol and the MatchOrders command will initiate order matching. That’s where we’ll leave matching until we get to the Order Matching section below.

So we now either have a SendAcceptNewOrder or a SendRejectNewOrder command on the output queue, so time to jump to where the output queue CommandProcessor picks up our newly added command.

Processing the output command

We return to things when the output CommandProcessor dequeues the output command and executes it. Being optimistic let’s look at the SendAcceptNewOrder case in detail and I’ll mention the SendRejectNewOrder failure case briefly at the end:

C#
internal class SendAcceptNewOrder : ICommand
{
    // ...

    public void Execute()
    {
        _sessionMediator.NewOrderAccepted(_sessionID, _order);
    }
}

Well that’s just handing it off to the SessionMediator, so what does it do?

C#
internal class SessionMediator
{
    // ...

    public void NewOrderAccepted(FixSessionID ownerSessionID, IOrder order)
    {
        var orders = new List<IOrder> {order};
        foreach (var sessionID in GetAllLoggedInSessions())
        {
            SendOrders(sessionID, orders);
        }
    }

    // ...

    public void SendOrders(FixSessionID sessionID, List<iorder> orders)
    {
        var fixID = _sessionIDMap.GetBySecond(sessionID);

        Action<IFixMessageHandler> messageSendF =
               handler => handler.SendOrdersToSession(fixID, orders);

        _sessionRepository.SendMessageToHandler(sessionID, messageSendF);
    }

    // ...
}
</iorder>

Since the order was added to the system we need to tell all of the connected clients about it, hence the loop over all logged in sessions. SendOrders then looks up the external session ID (QuickFix.SessionID) and asks the SessionRepository to send a message to the FIX Session by calling SendMessageToHandler and passing it an Action to call IFixMessageHandler.SendOrdersToSession.

C#
internal class SessionRepository : ISessionRepository
{
    private readonly object _lock = new object();

    private readonly Dictionary<FixSessionID, SessionContext> _sessions =
        new Dictionary<FixSessionID, SessionContext>();

    public void AddSession(FixSessionID sessionID, IFixMessageHandler messageHandler)
    {
        lock (_lock)
        {
            _sessions.Add(sessionID, new SessionContext(messageHandler));
        }
    }

    // ...

    public void SendMessageToHandler(FixSessionID sessionID, Action<IFixMessageHandler> f)
    {
        lock (_lock)
        {
            var handler = _sessions[sessionID];
            f(handler.MessageHandler);
        }
    }
}

If you have a particularly good memory (or have just re-read the “When a FIX client connects” section) then you may remember that when a FIX session connects it is assigned the appropriate IFixMessageHandler derived class based on the version of FIX it is using. Here we can see that when the session is added to the repository in AddSession this IFixMessageHandler is stored in a Dictionary (via a SessionContext object) and associated with the Session’s FixSessionID. Now all that needs to be done is to generate the FIX messages (an ExecutionReport with ExecType.NEW) for the new Order and send it to the FIX Session, which is what SendOrdersToSession does:

C#
internal class Fix44MessageHandler : IFixMessageHandler
{
    // ...

    private readonly IFixFacade _fixFacade;
    private readonly IFixMessageGenerator _messageGenerator;

    // ...

    public void SendOrdersToSession(SessionID sessionID, IEnumerable<IOrder> orders)
    {
        foreach (var order in orders)
        {
            var msg =
                _messageGenerator.CreateNewOrderExecutionReport(order, _execIdGenerator());
            _fixFacade.SendToTarget(msg, sessionID);
        }
    }

    // ...
}

So that’s the success case, what do we do if the order fails validation and is rejected? Well, it’s very similar except that the SendRejectNewOrder command causes an ExecutionReport with an ExecType.REJECTED field that is sent only to the Session which tried to add the order.

Order Matching

As we saw above a MatchOrders command is added to the input queue when a new order is successfully added to the system. When executed, this command causes matching to be started for a given symbol.

This triggers the StandardOrderMatcher to automatch orders and produce a list of OrderMatch objects, each of which details either a full or partial match. These matches are then turned into ExecutionReport FIX messages and sent to connected clients. In an attempt to keep this article shorter than War and Peace we won’t go into it in any more detail here, but if you want to follow it through yourself then start at MatchOrders.Execute and follow the yellow brick road.

Unit tests

There are some unit tests, although not as many as I’d really like. The Domain coverage is getting towards a tolerable level but the rest of the system is not as well covered. Of particular use during development were the order-sorting tests and the matching tests, which allowed the perennially awkward matching edge cases to be covered far more easily than via manual testing.

Needless to say that for a commercial system I’d thoroughly recommend far more extensive unit testing, integration testing and system tests.

Looking Back

As mentioned in the introduction this server was created in the summer of 2013. It’s now spring 2014 and this is the first time I’ve looked at it in months. When going back over the code I noticed a few things with the benefit of hindsight. No doubt there are many other things that could be improved (and plenty of TODO suggestions in the code), but the ones that sprang to mind when writing this were:

  • Input commands should probably not be adding replies directly to the output queue, there should be some sort of Mediator / Governor class which is in control of adding the reply commands to the output queue. The tasks could indicate success or failure to this class or supply the return Command object to it, and the Mediator / Governor would then add the appropriate command to the queue.
    • Further to this the AddOrder command should definitely not be adding the MatchOrders command to the input queue. Again this should be something the Mediator / Governor does if AddOrder.Execute indicates success.
  • Why is the output queue synchronous rather than asynchronous? I think it was to ensure that clients did not receive certain messages out of order, so for instance in the case where a new order is added and then matched straight away there was no danger of the client receiving the order filled message before the order added message.
  • It would be neater, and easier to create tests for, if the dependency injection was done via a DI framework (e.g. MEF, Castle Windsor) rather than having ServerApplication creating and passing interfaces around all over the place.
  • Why do some of the interface implementations have different naming conventions? For example for IFoo some are called StandardFoo while others are just called Foo. It must just have been down to day-of-the-week and not-enough-time-to-refactor style issues.

Conclusion

We’ve introduced the Heathmill mock FIX trading server and presented the Domain Model used for the system. We talked a little bit about how the system uses FIX messages to communicate, then took a look at the design of the server and walked through selected parts of the codebase for the server.

The FIX messages are based around the client sending NewSingleOrder and OrderCancelRequest messages and the server replying with various flavours of ExecutionReports.

The server is based on the Command Pattern and translates between Commands and FIX messages. It uses an input and an output queue with command processors to execute the Commands and relies on sorted order stacks to auto-match orders.

We walked through the code used when a FIX Session connects, when a client sends a NewOrderSingle FIX message to the server and when the server fully or partially matches orders.

You might be asking “Can I use this server for testing my FIX client?”. Of course, please do! That’s what it’s there for.

Given that you might well ask “Can I use this server for commercial purposes?”. There’s nothing to stop you. Should you? Absolutely not! Well, not unless you like really angry clients.

I’ve tested the server with 2 connected clients and for some basic workflows but it’s certainly not ready for production; it’s been designed and written for use in testing and should be taken as such. It might deadlock with more clients, there’s nothing to stop one client sending thousands of messages per second and exhausting the server memory as the input queue grows to gargantuan proportions, performance beyond 2 clients with a few orders in the system hasn’t been tested, it’s not real-time, it doesn’t persist any data whatsoever, there is no permissioning so all clients can see all details of all orders, and possibly many other such "features" just waiting to surprise and delight.

Acknowledgements

The server code makes use of a class called Heathmill.FixAT.Utilities.BidirectionalDictionary. This class is almost entirely based on one of Jon Skeet’s many excellent Stack Overflow answers. I’m almost certain that at least some of the methods in DictionaryExtensions are from Stack Overflow as well, but I can’t remember where from (if they are). Statistically they’re likely by Jon Skeet as well since he probably answers >50% of all C# Stack Overflow questions himself...

Footnotes

  1. To build the solution:
    • If you've not used NuGet before then install NuGet using the Visual Studio Extension Manager (via the Tools menu or via download)
    • Restore the NuGet packages:
      • Right-click on the Solution in Solution Explorer and choose "Enable NuGet Package Restore"
        • This will create a .nuget directory under the solution directory
      • Right-click on the Solution in Solution Explorer and choose "Manage NuGet Packages for Solution ..."
      • Click "Restore" in the top-right corner
      • See the page on NuGet Package Restore for more info
    • Build the solution as usual
  2. Domain Driven Design; Evans, Eric; Addison Wesley; ISBN-10: 0321125215; ISBN-13: 978-0321125217
  3. There is a lot more to click-trading than just selecting a price. Most systems will allow a user to sweep-volume (i.e. trade a number of orders to trade a particular quantity), basket-deal several orders at once or only trade part of the quantity of an order, for example. Pre-trade risk or credit systems may prevent certain counterparties from trading with each other so some orders may be untradeable. A commercial trading platform has a lot to consider when dealing with click trading; thankfully a demonstration system can do something much simpler (in this case, not support it!).

History

  • 2014-04-10 Initial Version
  • 2014-06-05 Added code for an AT Order Book client as an example FIX client and added a link to the Code Project article about it.

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

 
QuestionError Pin
thawpeek19-Apr-17 0:32
thawpeek19-Apr-17 0:32 
Generalcan this be used to simulate high frequency trading? Pin
Southmountain20-Jan-16 14:34
Southmountain20-Jan-16 14:34 
GeneralRe: can this be used to simulate high frequency trading? Pin
Mark_Shield24-Jan-16 7:15
Mark_Shield24-Jan-16 7:15 
QuestionThku vm for share idea but why Fix not Fast? Pin
Alexey KK27-Dec-15 19:13
professionalAlexey KK27-Dec-15 19:13 
AnswerRe: Thku vm for share idea but why Fix not Fast? Pin
Mark_Shield24-Jan-16 7:10
Mark_Shield24-Jan-16 7:10 
GeneralRe: Thku vm for share idea but why Fix not Fast? Pin
Alexey KK24-Jan-16 7:54
professionalAlexey KK24-Jan-16 7:54 
GeneralRe: Thku vm for share idea but why Fix not Fast? Pin
Mark_Shield24-Jan-16 10:12
Mark_Shield24-Jan-16 10:12 
GeneralRe: Thku vm for share idea but why Fix not Fast? Pin
Alexey KK24-Jan-16 11:14
professionalAlexey KK24-Jan-16 11:14 
QuestionURGENT!! BUILD A PLATFORM FOR ME Pin
Member 112812322-Dec-14 22:15
Member 112812322-Dec-14 22:15 
QuestionI work in FX and I like what you have done here Pin
Sacha Barber13-Aug-14 22:43
Sacha Barber13-Aug-14 22:43 
Good job.
AnswerRe: I work in FX and I like what you have done here Pin
Mark_Shield13-Aug-14 22:49
Mark_Shield13-Aug-14 22:49 
QuestionSource code Pin
gaurav.gupta8124-Jul-14 3:04
gaurav.gupta8124-Jul-14 3:04 
AnswerRe: Source code Pin
Mark_Shield13-Aug-14 22:47
Mark_Shield13-Aug-14 22:47 
QuestionGood work! Pin
Volynsky Alex5-Jun-14 22:32
professionalVolynsky Alex5-Jun-14 22:32 
GeneralMy vote of 5 Pin
Merlin Brasil14-Apr-14 9:43
Merlin Brasil14-Apr-14 9:43 
GeneralMy vote of 5 Pin
CatchExAs10-Apr-14 21:38
professionalCatchExAs10-Apr-14 21:38 
GeneralRe: My vote of 5 Pin
Mark_Shield10-Apr-14 22:28
Mark_Shield10-Apr-14 22:28 
GeneralRe: My vote of 5 Pin
CatchExAs10-Apr-14 22:40
professionalCatchExAs10-Apr-14 22:40 
GeneralRe: My vote of 5 Pin
Southmountain11-Apr-14 6:06
Southmountain11-Apr-14 6:06 
GeneralMy vote of 5 Pin
Oleg A.Lukin10-Apr-14 19:35
Oleg A.Lukin10-Apr-14 19:35 
GeneralRe: My vote of 5 Pin
Mark_Shield10-Apr-14 22:23
Mark_Shield10-Apr-14 22:23 
GeneralMy vote of 5 Pin
Volynsky Alex10-Apr-14 11:51
professionalVolynsky Alex10-Apr-14 11:51 
GeneralRe: My vote of 5 Pin
Mark_Shield10-Apr-14 22:23
Mark_Shield10-Apr-14 22:23 
GeneralRe: My vote of 5 Pin
Volynsky Alex10-Apr-14 22:32
professionalVolynsky Alex10-Apr-14 22:32 

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.