FIIDL - FIX Interactive Interface Definition Language (part three)


Let’s look into this in more depth and work through some examples...

A normal manual FIX implementation may have a workflow that can be described in words like this:
At time t sell-side system waits passively for a buy-side to connect
At time t2 Buy-side issues login
At time t3 Sell-side receives login and responds with login
At time t4 Buy-side sends heartbeat message
At time t5 Sell-side sends heartbeat message
At time t5 Session is declared live and the test is passed.
This is the sort of thing that a FIX on-boarder in a buy-side, sell-side, vendor or exchange does all day every day.
Now, let’s look at a different way to express this




In this case we have time increasing as we move down the page.
In both cases these representations are flawed.  There are many issues but the first one to consider is time.  There is no reason for the heartbeat messages to arrive in the order expressed. So if the above workflow is taken as the exact representation of the truth then a test scenario where the sell-side sends the heartbeat before the buy-side will result in a failure.

If we look at a more complex scenario we can see that the representation of a workflow in written English or in some form of visio diagram is flawed.

At this point I commend to the reader to have a look online for references to “Finite State Machines”.  (for example: http://en.wikipedia.org/wiki/State_diagram) The finite state machine is a well developed way to represent complex systems by breaking the system down to a set of states, inputs and outputs.

There is an XML format to represent this: http://www.w3.org/TR/scxml/

This is an extract from the Wikipedia page http://en.wikipedia.org/wiki/SCXML




This is represented in XML like this:


<?xml version="1.0" encoding="UTF-8"?>
< scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="ready">
    <state id="ready">
        <transition event="watch.start" target="running"/>
    </state>
    <state id="running">
        <transition event="watch.split" target="paused"/>
        <transition event="watch.stop" target="stopped"/>
    </state>
    <state id="paused">
        <transition event="watch.unsplit" target="running"/>
        <transition event="watch.stop" target="stopped"/>
    </state>
    <state id="stopped">
        <transition event="watch.reset" target="ready"/>
    </state>
< /scxml>

Now, let’s take that into the world of FIX. Below is a selective, partial implementation of SCXML for FIX 4.2.  Please note that this is very much in the realm of exploratory, proof-of-concept and is a long way from production ready.
 
<?xml version="1.0" encoding="UTF-8"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initial="engine.not.running">
    <state id="engine.not.running">
        <transition event="engine.start.commence" target="engine.is.starting"/>
    </state>
    <state id="engine.is.starting">
        <transition event="engine.start.complete" target="engine.is.running"/>
        <transition event="engine.start.failed" target="engine.not.running"/>
    </state>
    <state id="engine.is.stopping">
        <transition event="engine.stop.complete" target="engine.not.running"/>
        <transition event="engine.stop.failed" target="engine.is.running"/>
    </state>
   <state id="engine.is.running">
        <transition event="engine.stop.commence" target="engine.is.stopping"/>
        <transition event="engine.sessions.ADD.$session" target="engine.$session.is.stopped"/>
    </state>
    <state id="engine.$session.is.stopped">
        <transition event="engine.$session.SEND.login" target=" engine.$session.is.starting"/>
        <transition event="engine.stop.commence " target="engine.is.stopping"/>
    </state>
    <state id="engine.$session.is.stopping">
        <transition event="engine.$session.RECEIVE.logout" target="engine.$session.is.stopped"/>
        <transition event="engine.$session.failed" target="engine.not.running"/>
    </state>
    <state id="engine.$session.is.starting">
        <transition event="engine.$session.RECEIVE.login" target="engine.$session.is.running"/>
        <transition event="engine.$session.failed" target="engine.not.running"/>
    </state>
<state id="engine.$session.is.running">
        <transition event="engine.$session.RECEIVE.logout" target="engine.$session.is.running"/>
        <transition event="engine.$session.RECEIVE.TestRequest" target="engine.$session.Process. TestRequest"/>
        <transition event="engine.$session.RECEIVE.ResendRequest" target="engine.$session.Process. ResendRequest"/>
        <transition event="engine.$session.RECEIVE.Heartbeat" target="engine.$session.Process. Heartbeat"/>
        <transition event="engine.$session.RECEIVE.Reject" target="engine.$session.Process.Reject"/>
        <transition event="engine.$session.SEND.logout" target="engine.$session.is.stopping"/>
        <transition event="engine.$session.failed" target="engine.not.running"/>
        <transition event="engine.$session.ADD.$fixmessage[OUT]" cond="35==D,59==0" target="$fixmessage[OUT]:35=D.is.sending"/>
        <transition event="engine.$session.ADD.$fixmessage[OUT]:35=K" target="$fixmessage[OUT]:35=K.is.sending"/>
    </state>
    <state id="$fixmessage[OUT]:35=D.is.sending">
        <transition event="$fixmessage[IN]" cond="35==8,39==A" target="$fixmessage[OUT]:35=D.PendingNew"/>
        <transition event="$fixmessage[IN] " cond="35==8,39==8" target="$fixmessage[OUT]:35=D.Rejected"/>
        <transition event="$fixmessage[IN] " cond="35==8,39==1" target="$fixmessage[OUT]:35=D.PartiallFilled"/>
        <transition event="$fixmessage[IN] " cond="35==8,39==2" target="$fixmessage[OUT]:35=D.Filled"/>
    </state>
<scxml>


There are a number of syntactical issues to note:

  1. engine.not.running is the starting state.  This is a pretty arbitrary starting point. We could start with server.that.runs.engine.not.running – but I think it’s not too relevant. No need to go further up the stack than needed.


  2. $session means – a specific instance of a session running on that engine.  The point here is that each FIX session should be isolated from the others (even when they are logically linked – classic example being in FX where one session will handle market data and one will handle transactional messages between the counterparty firms).

  3. engine.$session.SEND.login  could also be engine.$session.ADD.$fixmessage[OUT]:35=A.  The reason I have split this is to draw a difference between session related messages and messages that may be sent or received in large numbers such as quotes, orders or executions.

  4. The syntax looks a little clunky with a lot of is.sending, is.stopping and so on.  This is an artefact of the asynchronous nature of FIX.  Since FIX runs over TCP/IP you are never sure if any message sent is received, so unless you receive acknowledgement of receipt you are always in a state of “I sent it, not sure it arrived, not sure it was parsed, not sure it was processed.”

  5. You can consider the transition event names as including a namespace.  As an example, for the transition event="engine.$session.ADD.$fixmessage[OUT]:35=D" we set the as target="$fixmessage[OUT]:35=D.is.sending" So we have removed the “engine.$session.” from the target state.  This simplifies navigation and presentation.

  6. While writing this I have been thinking of the way that socket.io and primus handles asynchronous event driven programming. 

One of the key points to consider here is that the workflow modelling that should be embedded within FIIDL should encompass the entire stack.  If you think of a FIX engine it has a tiny amount of state to persist (sequence numbers, IP addresses, port numbers, messages that have been received from the internal OMS but not yet sent out) so a state machine is pretty poor in explaining the workflow.  The real value to FIIDL is to include all of the workflow logic from the downstream systems as well. Once we have embedded the entire stack workflow then we are able to accurately model the stack states, inputs and outputs.
All well and good, but where will this go?  My view is that FIIDL is an elegant solution to a problem that everyone in the world of FIX encounters.  I will try and raise this within the FIX “proper channels” but I suspect have that the next test for FIIDL will be within a bank that wants to integrate multiple systems and wants to automate all or part of the testing.  Take as an example, a bank that has an old technology market gateway system.  If that gateway is described using FIIDL then the systems with which it interacts will be able to understand what they can and cannot do based upon the business logic of the system.
In short – build out FIIDL to solve internal problems before offering it out to clients of a bank or exchange who seek a shorter testing and release cycle.

Comments