Building a node.js implementation of a Forex FIX Protocol Client for LMAX – Part 1

For those who do not know what the FIX Protocol is: “The Financial Information eXchange (FIX) protocol is an electronic communications protocol initiated in 1992 for international real-time exchange of information related to the securities transactions and markets.” (Wikipedia).

Brokers, banks and many other players in the financial market use the fix protocol for financial communication. In the forex world – from the perspective of avergage guys like us – the FIX protocol is the pro version of Metatrader.

Advantages: Much smaller spreads, no technical limitation concerning the implementation, reliable connection latency (as the requests are not redirected), no “Last Look” (LMAX)

The combination of an extremley low latency (if you use a server with an interconnect to LMAX) and the missing “Last Look” for your opponent lead to a very low slippage.

Disadvantages: Usually the initial deposit is higher. (LMAX “Professional”: 10.000$/€)

What do you need to know to be able to implement the FIX protocol by yourself? You have to know which version of the FIX Protocol your broker offers (LMAX clients use FIX 4.4) and you have to know which functions you actually need. As the protocol grew over the years and is used for a long list of financial uses cases, it has many more functions than you will ever need for simple forex trading. If you want to browse the specification details of the FIX Protocol I can recommend www.onixs.biz.

A FIX connection consists of a socket connection for the exchange of request and response messages. LMAX uses separate connections for data feed and trading:

for (var connection in {"feed": '', "trade": ''}) {

  var host = account[connection][type].host;
  var port = account[connection][type].port;

  (function () {
    var client = new net.Socket();
    var clonedConnection = clone(connection, false);
    var clonedHost = clone(host, false);
    var clonedPort = clone(port, false);
    account[clonedConnection].client = client;

    client.connect(clonedPort, clonedHost);

    client.on('connect', function () {
      client.send = function (message) {
        client.write(message);
      };
      // Logon
      client.send(createMessage({
        connection: clonedConnection,
        MsgType: MSGTYPESR['Logon'].tag
      }));
      account[clonedConnection].heartBeat
          = setInterval(function () {
        client.send(createMessage({
          connection: clonedConnection,
          MsgType: MSGTYPESR['HeartBeat'].tag
        }));
      }, 30000);
    });
    var buffer = '';
    client.on('data', function (data) {
      ...
    });
    ...
  }());
}

FIX messages are concated tag-value pairs. Tag-value pairs are terminated by the non printable ASCII ‘\x01’. Every message ends with a checksum Tag “10”. Based on those information you can extract messages from the incoming chunk stream:

client.on('data', function (data) {
  var chunkString = data.toString();
  for (var c = 0; c < chunkString.length; c++) {
    buffer += chunkString[c]
    if (chunkString[c] == '\x01') {
      if (buffer.length > 7) {
        if (buffer[buffer.length - 5] == '=' 
            && buffer[buffer.length - 6] == '0' 
            && buffer[buffer.length - 7] == '1' 
            && buffer[buffer.length - 8] == '\x01') {
            parse(clonedConnection, buffer)
            buffer = ''
        }
      }
    }
  }
});

As described tag “10” is the “CheckSum” tag, an extract from my list of necessary tags:

...
8: {
  name: 'BeginString',
  default: "'FIX.4.4'"
},
9: {
  name: 'BodyLength',
  default: "body.length"
},
10: {
  name: 'CheckSum',
  default: 'getCheckSum(msg)'
},
11: {
  name: 'ClOrdID',
  default: 'getRandomId()'
},
...

What do we know now? We know somehting about the basics of the communication and the message structure. But how to logon, how to send keep alives, how….. That’s what I will explain in the next posts.

In case of questions, ideas, remarks or improvements: Feel free to comment or contact me directly.

Kind regards

Artur Brylka