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

This is a sequel to Part 1 of my introduction to building a node.js implementation of a Forex FIX Protocol Client for LMAX. After you have heard some basics let’s now get to the hard facts. At the end of this post we should be able to logon to the LMAX market feed server. This may sound not very complicated – but believe me, there is a lot to talk about.

For a better understanding of the used variables let’s have a look at our config object:

var account = {
  broker: 'LMAX',
  number: '123456789', 
  username: 'my_username',
  password: 'my_password',
  trade: {
      ...
  },
  feed: {
    targetCompID: 'LMXBDM',
    heartbeatIntervalId: null,
    msgSeqNum: 1,
    senderCompID: 'my_username',
    client: null,
    heartBeat: null,
    internal: {
      host: '127.0.0.1',
      port: 14433
    },
    messageBuffer: {}
  }
}

I think the variables are explaining themselves relatively well by their names. One of the first questions that comes to your head may be ‘Why do we connect to localhost?’. The reason is quite simple, LMAX requires a SSL connection. A fast and reliable way is the usage of stunnel.

I will not describe the installation or handling of stunnel in this chapter. But if you need the stunnel config for LMAX here it is:

#[LMAX Trade Live]
#client = yes
#accept = 127.0.0.1:14432
#connect = XXXXXX:443
#sslVersion = TLSv1
#options = NO_SSLv2
#options = NO_SSLv3

#[LMAX Feed Live]
#client = yes
#accept = 127.0.0.1:14433
#connect = XXXXXX:443
#sslVersion = TLSv1 
#options = NO_SSLv2
#options = NO_SSLv3

As I am not interested in supporting any kind of misuse I replaced the IPs with XXXXXX. But as you are (will be) a loyal LMAX customer they will be happy to provide you with the required information.

Now, that we can reach the LMAX server, we establish the socket connection as described in Part 1 and send our credentials for authentication. In the example the non printable ‘\x01’ has been replaced with whitespaces:

8=FIX.4.4 9=108 35=A 49=my_username 56=LMXBDM 34=1 52=20170525-06:55:21.406 98=0 108=30 141=Y 553=my_username 554=my_password 10=049

As you can see: Completely intuitive. Just kidding, let’s extract all the used tags for a logon and try to to understand them step by step:

8 = ‘BeginString’ The used FIX version.
9 = ‘BodyLength’ The number of chars of the body, another possibility to split the incoming chunks into complete messages. But I prefer searching the checksum tag as described in Part 1. But there is no philosophy behind this decision.
35 = ‘MsgType’ The message type defines the content of the message, for message type ‘A’ my client defines the body as follows:

const MSGTYPES = {
  'A': {
    name: 'Logon',
    body: [
      'EncryptMethod',
      'HeartBtInt',
      'ResetSeqNumFlag',
      'Username',
      'Password']
  },
...

49 = ‘SenderCompID’ Identifier of the sending system. For LMAX this value is identical to the username.
56 = ‘TargetCompID’ Identifier of the receiving system. LMAX has two different identifiers, depending on the connection you establish, market feed or trading.
34 = ‘MsqSeqNum’ A sequence number as for example used in TCP connections as a unique identifier for every sent message.
52 = ‘SendingTime’ A simple timestamp and a possible reason for sudden disconnects while trying to logon if the timezone of your server differs from LMAX’ timezone configuration (UTC/GMT for Equinix LD4 datacenter).

Now we come to the individual body of the Logon message as described in the code block above.

98 = ‘EncryptMethod’ As we already use the stunnel tunnel LMAX accepts that we do not use any encryption. For this tag – as for all others – you can find information concerning the FIX specification here.
108 = ‘HeartBtInt’ The heart beat interval tells LMAX after how many seconds you send heart beat messages to confirm that you are still alive.
141 = ‘ResetSeqNumFlag’ If Y this tells LMAX that you do not continue the ‘MsqSeqNum’ of the last connection but reset the sequence.
553 = ‘Username’
554 = ‘Password’

This tag terminates every message:
10 = ‘CheckSum’ The best way to describe the checksum logic:

function getCheckSum(msg) {
    var sum = 0;
    for (var i in msg)
        if (msg.hasOwnProperty(i))
            sum += (msg.charCodeAt(i));
    return ("00" + (sum % 256)).slice(-3);
}

If all the information in your sent logon message are correct and consistent, LMAX replies with a logon confirmation that looks more or less like this:

8=FIX.4.4 9=77 35=A 49=LMXBDM 56=my_username 34=1 52=20170525-06:55:21.497 98=0 108=30 141=Y 10=057

If you achieve a logon confirmation: Congratulations! If not, feel free to contact me.

Kind regards

Artur