Introduction

The EU’s Markets in Financial Instruments MIFID II Directive, will introduce significant changes for investment firms and other financial markets participants when the EU member states implemented them in January 2018. This article discusses the capability for existing TREP clients to transmit pre-trade FIX messages to registered Approved Publication Arrangements (APA) to satisfy MIFID II regulatory requirements.

In many cases, data subject to pre-trade reporting obligations is already available via TREP in the form of MarketPrice updates which are shared via OMM posts. The OMM to FIX Gateway will act as an additional endpoint for OMM post messages, and convert them to FIX format using a simple transformation directive and forward them to the configured APA for processing.

The OMM to FIX Gateway connects to APAs via the FIX protocol using the QuickFIX/J engine, logs all FIX traffic, and support a simple management interface.

Due to limitations of the TREP Post mechanism, the gateway ACKs or NACKs the receipt of messages after they are successfully converted, but before they are routed over FIX to the APA.

TREP Requirements

The OMM to FIX gateway is compatible with TREP versions 2 and 3. Messages are delivered to it with on-stream or off-stream OMM Post messages.

OMM to FIX Gateway Requirements

The OMM to FIX gateway requires any machine running Java, with a minimum of 2GB of memory. Gradle is also required to build the OMM to FIX gateway and pull down dependencies. Docker is required to run the Docker image if you chose that option.

Downloading and building

The zip file containing the OMM to FIX gateway Java source, build scripts and Thomson Reuters libraries can be downloaded and unzipped on any machine running Java and Gradle.

In the directory containing the file build.gradle, run the command “gradle makeDist“. This will create a file named apagateway_dist.tar.gz. This file can then be moved to the location from where the OMM to FIX gateway will be run.

Building a Docker image

Included in the downloaded zip file is a Dockerfile that can be used to create a Docker image. Run “docker build -t e3pa-gateway:latest" from the directory with the Dockerfile.

Directory Structure

package/        -- root directory
app/            -- all software for the gateway
client/omm/     -- FIX and UPA dictionaries
rules/          -- rules.json file location
gateway.sh      -- script to start E3PA
utils.sh        -- script used by gateway.sh

Running the OMM to FIX gateway server

The OMM to FIX gateway can be run from a shell script or can be run from a Docker image. Both methods are described below.

To start the OMM to FIX server extract the apagateway_dist.tar.gz file created after you ran the gradle build and go to the package directory. Run the gateway.sh with the --server option to start the server. There are many command line options available:

gateway.sh --server <command-line options>

TREP options

-a      --adhuser          ADH user id
-i      --serviceid        TREP service id to advertise
-y      --service          TREP service name to advertise
-f      --fixdictionary    FIX dictionary file
-x      --fixenums         FIX enums
-q      --postdictionary   OMM Post dictionary
-w      --postenums        OMM Post enums

FIX options

-s         --sender          FIX sender comp ID
-t         --target          FIX target comp ID
-e         --fixaddress      Remote APA FIX host/ip
-g         --fixport         Remote APA FIX port
-k         --version         FIX version (typically FIXT.1.1 for APA)
-st        --starttime       FIX connection start time (hh:mm:ss)
-et        --endtime         FIX connection end time (hh:mm:ss)
-j         --heartbeat       FIX heartbeat interval, default: 30 seconds

Logging/Config options

-R       --rulesfile      path to transformation rules file
-fl      --filelog        FIX file log path
-z       --json           JSON log path

A sample start command might look like:

./gateway.sh --server -a rmds -i 256 --service AUTEX_APA -s AUTEX -t APA_DEST -e 198.100.10.92 -g 7000 -k FIXT.1.1 --fixdictionary ./client/omm/FDMFixFieldDictionary --fixenums ./client/omm/FDMenumtypes.def --postdictionary ./client/omm//RDMFieldDictionary --postenums ./client/omm/enumtype.def --rulesfile ./rules/rules.json --filelog ./logs --json ./logs

Defining JSON Transformation Rules

In order to convert OMM Post messages to FIX, you must specify mapping logic in a JSON file. The rules will be applied to each incoming post message and applied to convert it to FIX to be sent to the APA destination.

We have included sample rules files that follow a few APA pre-trade FIX specs, but since the OMM Post dictionaries are highly customized by clients, each user will need to tweak the JSON transformation rules to capture the OMM Post fields.

Let’s say we wish to define a JSON file to map OMM Post messages to the TRADEcho pre-trade quote offer FIX message. We will make the following assumptions as to the FID tags and values in the post message:

OMM Header key ITEMNAME = security id
8633 = quote id
16 = trade date
18 = trade time
25 = offer px
31 = offer size

The FIX spec for TRADEcho requires the following tags in the body:

35  = i (quote)
117 = QuoteId
60  = Timestamp for the quote (TransactTime)
296 = NoQuoteSets        
295 = NoQuoteEntries                
48  = Security ID                
22  = Security ID Source (4 = ISIN, etc.)                
133 = OfferPx                
135 = OfferSize

So we need to construct a JSON transformation rule that tells the OMM to FIX gatweay to do the following:

1. Make sure FID 25 and 31 are both present

2. Add FIX tag 35 = “i”

3. Move the value in FID 8632 to FIX tag 117

4. Concatenate FID 16 + 18 to FIX tag 60

5. Add FIX repeating group 296

6. Add FIX repeating group 295 in repeating group 296

7. Move security id from OMM Header to FIX tag 48 in repeating group 295

8. Add FIX tag 22 as “4” in repeating group 295

9. Move FID 25 to FIX tag 133 in repeating group 295

10. Move FID 31 to FIX tag 135 in repeating group 295

 

We start with defining the JSON body with empty conditions and actions:

{
 "messageRules": [
   {
     "conditionList": {
       "conditions": []
         },
     "matchActions": {
       "actions": []
     }
   }  ]
}

We can add as many “rules” as we like to the JSON, all will be evaluated for each condition that you define. Next add the conditions:

{
 "messageRules": [
   {
     "conditionList": {
       "conditions": [
         {
           "conditionType": "AND",
           "conditions": [
             {
               "conditionType": "PRESENT",
               "tagId": 25
             },
             {
               "conditionType": "PRESENT",
               "tagId": 31
             }
           ]
         }
       ]
     },
     "matchActions": {
       "actions": []
     }
   }
 ]
}

This will check for the existence of FID 25 and 31. If condition is met, the actions we define will be invoked:

{
 "messageRules": [
   {
     "conditionList": {
       "conditions": [
         {
           "conditionType": "AND",
           "conditions": [
             {
               "conditionType": "PRESENT",
               "tagId": 25
             },
             {
               "conditionType": "PRESENT",
               "tagId": 31
             }
           ]
         }
       ]
     },
     "matchActions": {
       "actions": [
         {
           "actionType": "ADD",
           "destTag": 35,
           "tagValue": "i"
         },
         {
           "actionType": "MOVE",
           "srcTag": 8632,
           "destTag": 117
         },
         {
           "actionType": "TIMESTAMP",
           "dateTag": 16,
           "timeTag": 18,
           "destTag": 60
         },
         {
           "actionType": "REPEATINGGROUP",
           "destTag": 296,
           "actions": [
             {
               "actionType": "REPEATINGGROUP",
               "destTag": 295,
               "actions": [
                 {
                   "actionType": "ITEMNAME",
                   "destTag": 48
                 },
                 {
                   "actionType": "ADD",
                   "destTag": 22,
                   "tagValue": "4"
                 },
                 {
                   "actionType": "MOVE",
                   "srcTag": 25,
                   "destTag": 133
                 },
                 {
                   "actionType": "MOVE",
                   "srcTag": 31,
                   "destTag": 135
                 }
               ]
             }
           ]
         }
       ]
     },
     "notMatchActions": {
       "actions": [
         {
           "actionType": "REJECT"
         }
       ]
     }

   }
 ]
}

The actions will set FIX tag 35 = i, move FID 8632 to FIX 117, create FIX tag 60 from FID 16 + 18, create the nested repeating groups, and add FIX tag 48 as security id from the OMM header named ITEMNAME, set FIX tag 22 = 4, move FID 25 to FIX 133 and move FID 31 to FIX 135.

The notMatchActions will cause an OMM NACK to be generated back to the sender if the conditions are not met.

The rules file is specified with the --rulesfile parameter to the start script with. A different rules file should be defined for each APA destination and the appropriate loaded at startup.

Custom RDM Dictionaries

We have included the RDM dictionaries, however if you have customized your own you can specify the location using the ---postdictionary and --postenums options at startup.

OMM Post ACK/NACK

If the message is successfully accepted and transformed to FIX an OMM ACK message will be returned. This does not mean that the APA successfully accepted the FIX message, only that it was converted. If the message was not converted a NACK will be returned.

Logs

All outbound FIX messages to APAs and inbound from APAs are logged in standard FIX logs, along with all other FIX events.  All FIX messages are also logged in JSON formatted logs, which then can easily be loaded to a data storage application such as Elasticsearch. The FIX log directory and JSON log directory are each specified at startup using --filelog an --json options.

JMX Management

The QuickFIX/J engine supports standard JMX commands for FIX engine management. You can use any JMX compatible application, including JConsole. The default JMX port is 6998 and you can access it using JConsole by running jconsole 10.89.5.230:6998. QuickFIX/J commands are all under the org.quickfix MBean. See http://www.quickfixj.org/quickfixj/usermanual/1.6.3/usage/jmx.html for more info.



Sample JMX JConsole command screen

Running with Docker

The OMM to FIX Gateway has been built and tested on Docker and will be distributed via DockerHub. Docker is a software container platform that allows us to ship the entire E3PA environment in one package that can be run on any Docker-enabled host. The environment contains the operating system, Java version, etc., any libraries and settings. For more info on Docker see https://www.docker.com/what-docker.

To install the OMM to FIX Gateway you need build the Docker image as described earlier using “docker build” command.  To list the image(s) installed, including the one you just created, run “docker images” which will display something like::

REPOSITORY      TAG         IMAGE ID          CREATED         SIZE
e3pa            latest      2d94f587a47a      2 hours ago     704 MB

If you wish to install the image on a machine different from where you built it you must save the image on the build machine by running “docker save -o e3pa.tar e3pa”, then copying the tar file to the host where you want to run the image and then run “docker load -i e3pa.tar”. This will load and create the image.

Use the docker run command to start an instance, known as a container, of the OMM to FIX. You can use all the same parameters outlined above. The logs and JSON directories should be mapped using the -v Docker option and the ADS and JMX port mapped using the -p Docker option.

docker run --network=host --name E3PAGateway e3pa:latest

Docker options:

        -p <host ADS port>:14003
        -p <host JXM port>:6998
        -v <host log directory>:/var/log/APAGateway
        -v <host JSON rules directory>:/etc/APAGateway/rules

 thomsonreuters/e3pa-gateway:latest

OMM to FIX gateway options:

        --server
        -a <trep user id>
        -i <trep service id>
        --service <trep service name>
        -s <sender comp id>
        -t <target comp id>
        -e <remote FIX host>
        -g <remote FIX post>
        -k <FIX version>
        (additional options above)

A sample Docker run command might appear as:

docker run --network=host --name APAGateway -p 14003:14003 -p 6998:6998 -v /home/apauser/APA/logs:/var/log/APAGateway -v /home/apauser/APA/config:/etc/APAGateway/rules thomsonreuters/apa:latest --server -a rmds -i 256 --service AUTEX_APA -s SENDER_COMP_ID -t TARGET_COMP_ID -e 192.0.0.1 -g 7000 -k FIXT.1.1

The above command maps ports 14003 and 6998 from the host to the container, and the host file locations of the logs and the JSON config files under the user’s /home/apauser directory. This allows the user to use whichever ports and file locations they want on their local host without reconfiguring the Docker container.



Message Flow Overview