This article describes the FIX-over-FAST connectivity using the B2BITS FIX Antenna Java (tm) library.
The FAST protocol (FIX Adapted for STreaming) is a technology standard developed by FIX Protocol Ltd., specifically aimed at optimizing data representation on the network. It is used to support high-throughput, low latency data communications between financial institutions. In particular, it is a technology standard that offers significant compression capabillities for transporting high-volume market data feeds and creating ultra low latency applications.
Using B2BITS FIX Antenna Java(tm) a user can establish connection with a FIX-over-FAST oriented remote site. Current users are also able to migrate from FIX to FIX-over-FAST without significant code modifications.
This example provides a simple functionality for connecting to CME server and reading data from it. The data is converted from the FAST format to the FIX format. The converted data is printed to console.
package com.epam.example; import com.epam.common.transport.client.udp.UDPTransport; import com.epam.fast.full.session.client.FASTClientFactory; import com.epam.fast.full.session.client.FastChannel; import com.epam.fast.full.session.client.FastListener; import com.epam.fix.FIXVersion; import com.epam.fix.message.FIXFieldList; import com.epam.fix.message.constants.FIXT11; import com.epam.fixengine.*; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class CMEFastClientSample { public static void main(String[] args) throws FileNotFoundException { final FASTClientFactory clientFactory = FASTClientFactory.createFASTFactory(new FileInputStream("templates.xml")); // create one chanel for connecting to the CME // snapshots final FastChannel snapshots = clientFactory.createFASTChannel(new UDPTransport("224.0.26.1", 10001), new FastListener() { public void onFIXMessage(FIXFieldList message) { System.out.println(message); } }); // incremental updates final FastChannel incremental = clientFactory.createFASTChannel(new UDPTransport("224.0.26.1", 10002), new FastListener() { public void onFIXMessage(FIXFieldList message) { System.out.println(message); } }); //Instrumental Replay final FastChannel replay = clientFactory.createFASTChannel(new UDPTransport("224.0.26.1", 10003), new FastListener() { public void onFIXMessage(FIXFieldList message) { System.out.println(message); } }); // TCP Replay SessionParameters details = new SessionParameters(); details.setFixVersion(FIXVersion.FIX42); details.setHost("224.0.26.1"); details.setHeartbeatInterval(30); details.setPort(10003); details.setSenderCompId("senderId"); details.setTargetCompId("targetId"); // this is a generic factory for all standard FIXVersions FIXSessionFactory factory = new StandardFIXSessionFactory(); // create a session we intend to work with final FIXSession session; try { session = factory.createSession(details); } catch (IOException e) { throw new RuntimeException(e); } // listener for incoming messages and session state changes FIXSessionListener application = new FIXSessionListener() { // this method will be called every time session state is changed public void onSessionStateChange(SessionState sessionState) { System.out.println("Session state changed:" + sessionState); // this callback is called upon session state change if (sessionState == SessionState.DISCONNECTED) { // end this session session.dispose(); } } // processing incoming messages public void onNewMessage(FIXFieldList message) { System.out.println("New application level message type: " + message.getTag(FIXT11.Header.MsgType).getStringValue() + " received "); // this callback is called upon a new message arrival } }; // setting listener for incoming messages session.setFIXSessionListener(application); try { // connect to the channels snapshots.connect(); incremental.connect(); replay.connect(); } catch (IOException e) { throw new RuntimeException(e); } } }
As far as FAST does not support the full range of FIX types, mapping between FAST and FIX types is needed. The following table lists all conversion paths.
| FAST type | FIX application type | Comments |
| u32 | i32 | Value must be in range [0, 2^31) |
| u64 | i64 | Value must be in range [0, 2^63) |
| u32 | i64 | Value must be in range [0, 2^32) |
| u64 | u32 | |
| u32 | u64 | Value must be in range [0, 2^32) |
| i32 | u64 | Value must be in range [0, 2^31) |
| i32 | i64 | Value must be in range (-2^31, 2^31) |
| i64 | i32 | |
| u64 | i32 | |
| u32 | char | Value must be in range [0, 2^7) |
| u32 | ascii | Value of string should be an integer in range [0, 2^32) |
| u64 | ascii | Value of string should be an integer in range [0, 2^64) |
| i64 | ascii | Value of string should be an integer in range (-2^64, 2^64) |
| ascii | bool | The value of '\001' will be interpreted as true; otherwise it will be interpreted as false. |
| ascii | char | |
| ascii | i32 | |
| ascii | i64 | |
| i32 | char |
This sections explains how to create a CME application step-by step with samples. The usual scenario to get it to work is:
CME FAST Adaptor library allows application to subscribe to one or multiple instruments, supports all the features of CME market data channels including recovery. The CME distribution package includes the tool application. This is console application which supports market recovery and subcribtion to instruments.
The parameters is created in the following way:
// creates the application params ApplicationParams params = new ApplicationParams(); // sets uri to config file params.setUriToConfig(uriToConfig); // sets uri to templates file params.setUriToTemplates(uriToTemplates);
The application listener is created in the following way:
// creates the application listener ApplicationListener cmeAppListener = new ApplicationListener() { public void process(FIXFieldList message) { // process message code here } public void onError(String secDesc, long secID, String error) { // process error code here } };
The application instance is created in the following way:
Application application = new ApplicationImpl(params, cmeAppListener);
// creates the instrument listener InstrumentListener instrumentListener = new InstrumentListener(){ public void onSubscribed(String secDesc, long secID) { } public void onUnsubscribed(String secDesc, long secID) { } ......... .................. public void process(FIXFieldList fixMessage) { } public void onSnapshot(String secDesc, long secID, FIXFieldList msg) { } public void onBookReset(String secDesc, long secID) { } public void onError(String secDesc, long secID, String error) { } }; // subscribe by 'SYMBOL' application.subscribeBySecurityDesc("SYMBOL", instrumentListener, RecoveryOptions.Market);
The application is closed in the following way:
application.unsubscribeAll(); application.stop();
1.6.3