/
Java TCP Handler for CME iLink3

Java TCP Handler for CME iLink3

Introduction

This document describes a Java TCP Handler designed to interact with the Chicago Mercantile Exchange (CME) iLink3 Binary Order Entry Platform. This handler leverages the low-latency capabilities of the iLink 3 protocol to enable efficient order entry and management.

About CME iLink 3 Binary Order Entry Platform

CME iLink 3 is the latest generation of CME Group's electronic trading platform. It provides a high-performance, low-latency interface for accessing CME's diverse range of futures and options markets. Key characteristics of iLink 3 include:

  • Binary Protocol: iLink 3 utilizes a binary protocol (based on the Simple Binary Encoding - SBE standard) which is more efficient and faster than traditional text-based protocols like FIX. This results in reduced message sizes and lower processing overhead, leading to improved latency.

  • TCP/IP Connectivity: iLink 3 uses standard TCP/IP for network communication, making it compatible with existing network infrastructure.

  • Session-Based: Trading via iLink 3 requires establishing a session with the CME gateway. This session management includes negotiation, establishment, and termination phases.

  • Order Entry and Management: The platform supports a wide range of order types and functionalities for entering, modifying, and canceling orders.

  • Enhanced Security: iLink 3 incorporates security features to ensure the integrity and confidentiality of trading information.

For more detailed information about the iLink 3 Binary Order Entry Platform, please refer to the official CME Group documentation: https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457220858/iLink+3+Binary+Order+Entry

Getting Started with iLink3 Integration

Session Initialization

The following code snippet demonstrates the simplest way to establish a session:

CMEConnection connection = CMEConnection .builder() .setFirm("FIRM") .setAccessKeyId("yx4]kSB06-o}7Z7wJSwD") .setSessionId("B82") .setSessionSignatureKey("~LIWFnuO8YMfkjrezA532V@~`}40H'1dX") .setKeepAliveInterval(6000) .setTransport(new TcpTransport("host", 1234)) .build(); SBESession session = connection.createILink3Session(); session.addSessionListener(new SessionListener() { @Override public void onMessage(SBEDecodedMessage message, SBESession session) { // Handle incoming messages here } @Override public void onSendingError(SBEEncodedMessage message, Throwable ex, SBESession session) { // Handle sending errors here } @Override public void onSessionStatusChanged(SBESessionState state, SBESession session) { // Respond to session status changes } }); session.connect();

This code creates a CMEConnection using a builder pattern, setting essential parameters like firm ID, access key, session ID, and transport details. It then creates an ILink3Session from this connection and adds a SessionListener to handle incoming messages, sending errors, and session status changes. Finally, it initiates the connection.

Sending Messages

The following code snippet shows the basic structure for sending a message:

QuoteCancel528Encoder quoteCancel = MessageUtils.wrapILink3(QuoteCancel528Encoder.class); quoteCancel.location("location"); quoteCancel.senderID("senderId"); quoteCancel.manualOrderIndicator(ManualOrdIndReq.Automated); // Define repeating groups, even when empty, to ensure smooth processing quoteCancel.noQuoteEntriesCount(1) .next() .securityID(75667); quoteCancel.noQuoteSetsCount(0); cmeSession.send(new SBEEncodedMessage(quoteCancel));

This example demonstrates how to create and populate a QuoteCancel528Encoder message. It's important to note that even if a repeating group has no entries, it must be declared with a count of zero (e.g., quoteCancel.noQuoteSetsCount(0)). Failure to do so will result in a decoding error on the CME side.

Package Structure

The package consists of two main folders: scripts and lib.

Libraries (lib)

The lib folder contains the following Java libraries:

  1. ilink3-order-entry-without-binaries-${version}.jar: This JAR file contains the core logic for establishing and managing the CME session.

  2. ilink3-binary-${version}.jar: This JAR file includes all the business and session-level message definitions for the iLink 3 protocol, generated from the ilinkbinary.xml descriptor.

  3. ilink3-order-entry-1.0.1-small.jar: This JAR file is responsible for decoding incoming messages.

  4. fixaj-{qualifier}-{version}.jar, fixaj engine-{qualifier}-{version}.jar, trove.jar: These libraries provide support for persistent message storage. If a custom message storage solution is implemented, these JAR files can be excluded from the classpath.

  5. typeconverter-1.0.jar: This library is required to run the Groovy scripts and can be excluded from the classpath during runtime if the scripts are not needed.

  6. argona-{version}.jar: This JAR file contains child dependencies for the binary message objects.

Scripts (scripts)

The scripts folder contains Groovy classes designed for testing the CME connection in a console environment. These scripts are particularly useful for certification and integration testing. The following classes are included:

  1. Transformer.groovy: This class contains methods for converting messages between FIX and FIXP formats.

  2. Main.groovy: This is a console application that allows you to establish a CME connection using specific configuration parameters.

Additionally, the package may include a license file. Before running the ilink-order-entry library, the license file should be copied to the root folder of the launcher (the classpath root) or to the user's home directory.

How to Run in Console

To establish a CME connection using the Groovy console, follow these steps:

  1. Ensure that the Groovy SDK is downloaded and its bin directory is included in your system's PATH environment variable (e.g., Groovy 5.0.0).

  2. Verify that the JAVA_HOME environment variable is set correctly and points to a Java 21 installation.

  3. Prepare a properties file named channel-settings.properties with your connection details. Here's an example:

    channels=ILink3,AnotheIlink channel.ILink3.host=69.50.114.20 channel.ILink3.port=42459 channel.ILink3.sessionId=A0N channel.ILink3.accessKeyId=<your access key, provided by CME> channel.ILink3.firm=FRM01 channel.ILink3.key=<your secret key, provided by CME> channel.ILink3.keepAliveInterval=60000 channel.AnotheIlink.host=69.50.112.174 channel.AnotheIlink.port=42351 channel.AnotheIlink.sessionId=BMD channel.AnotheIlink.accessKeyId=<your access key, provided by CME> channel.ILink3.firm=001 channel.ILink3.key=<your secret key, provided by CME> channel.ILink3.keepAliveInterval=60000
  4. Create a file containing the FIX messages you want to test, formatted as shown below:

    8=FIX.4.29=18535=CX1505=05297=16227237839459164001324=A582=11816=01031=W9726=01676=11671=31691=acc1692=C1693=241691=FRM011692=C1693=11691=USER11692=C1693=1185290=1234536023=1234510=100 8=FIX.4.29=23335=D49=A0N56=CME34=1650=FRM01142=US57=G52=20150914-10:04:24.580369=1544=5.038=548=7474266954=19726=15392=USER311=Order_11505=02422=123455297=173807457928705099699=6.09537=US110=11138=5432=2025013040=459=61028=018=15906=A9373=06881=05409=0845=6.09562=7.010=093
  5. Navigate to the scripts folder in your terminal and execute the Main.groovy script using the following command:

    groovy -cp ../lib/* Main.groovy channel-setting.properties

Key Interfaces and Features

This section outlines the most important interfaces and features provided by the library.

SBESession

This interface exposes the essential methods for interacting with the counterparty server. The built-in implementation, AbstractCMESession, handles the core CME connection flow. ILink3Session extends this to specifically support the iLink 3 protocol.

SBESessionState

This enum class defines the possible states of a session:

  1. CREATED: The session has been created but has not yet attempted to connect. This state is often used to initialize resources.

  2. NEGOTIATED: The negotiation response has been received. This state might be skipped if the session is recovered from a previous one.

  3. ESTABLISHED: The Establishment Acknowledgement message has been received. The session is now ready for processing messages.

  4. REJECTED: A negotiation rejection or establishment rejection message was received from the server.

  5. TERMINATING: This state is entered before a terminate message is sent. It's useful for suspending message sending threads.

  6. TERMINATED: The terminate message has been received from the CME server.

SBEDecoder

This interface provides the API for decoding incoming binary messages. To initialize the decoder for a CME connection, call the method CMEConnection.setDecoder(SBEDecoder decoder). By default, the CMEConnection creates an instance of the DecoderImpl class.

The DecoderImpl parses SBE-generated classes within the Java classpath, including JAR files in the same folder, to create a mapping for decoding. To specify the packages to be parsed, use the constructor new DecoderImpl("iLinkBinary, mrktData"). The default constructor parses classes within the iLinkBinary package.

Note: Ensure that the necessary SBE-generated classes are included in the classpath to avoid decoding errors.

SessionStorage

This interface is responsible for maintaining session state parameters across trading weeks, such as the session UUID, sequence numbers, and incoming/outgoing messages. The default implementation is provided by the DefaultStorage class, which is initialized by default. To use a custom session storage implementation, call the CMEConnection.setSessionStorage method before creating the session.

MessageStorage

This interface handles the persistence of outgoing and incoming business messages. The current implementation is FileMessageStorage. To utilize a custom message storage mechanism, use the methods SessionStorage.getIncomingMessageStorage() and SessionStorage.getOutgoingMessageStorage().

FileMessageStorage

This implementation stores all messages in files with names like the following:

  1. PUA-iLink_1739608077283678000.in: File containing incoming binary messages.

  2. PUA-iLink_1739608077283678000.ndx.in: Index file for incoming messages.

  3. PUA-iLink_1739608077283678000.out: File containing outgoing binary messages.

  4. PUA-iLink_1739608077283678000.ndx.out: Index file for outgoing messages.

Note: Message storage only persists business-level messages. If a message fails to send due to an error, it will not be saved, and the SessionListener will be notified via the void onSendingError(SBEEncodedMessage message, Throwable ex, SBESession session) method. Handling such scenarios (e.g., through a backup process) is the responsibility of the client application.

CMEConnection

This class serves as a composer, holding connection settings and providing the necessary interaction components to each other.

Message Processing

Typically, all messages within an SBESession are processed synchronously. This ensures a predictable and sequential handling of messages as they arrive.

Retransmission requests are handled asynchronously, outside the main synchronous message processing flow, allowing normal message processing to continue without interruption.

Sequence Processing

Sequence numbers are assigned to business messages immediately before they are sent. The sequence number is incremented only if the message is sent successfully without errors.

To reset the sequence, for example, upon receiving a NotApplied message, the SessionStorage.resetSequence(Long sequence) method can be called.

Retransmission Process in SBESession

As outlined in the CME iLink 3 Documentation, the retransmission process is inherently supported by the SBESession. This feature is vital for ensuring message delivery and handling in case of connection issues or network problems.

The SBEDecodedMessage.isRetransmitted() method can be used to determine if a received message is part of a retransmission. It's important to be aware that retransmitted messages might originate from a previous session. This is a crucial consideration for maintaining the integrity of message sequences across different trading sessions.

Key Points:

  • Automatic Support: Retransmission is automatically managed within the SBESession, minimizing the need for manual intervention.

  • Retransmission Flag: The SBEDecodedMessage.isRetransmitted() method indicates whether a message is a retransmitted message.

  • Messages from Previous Sessions: Retransmitted messages can sometimes originate from previous sessions, which needs to be considered in session management logic.

Manually Initiating a Retransmission Request

To manually request a retransmission of specific messages, you can call the addRetransmissionRequest method. This provides a mechanism to handle situations where automatic retransmission might not occur as expected.

For the most accurate and comprehensive information regarding the session layer and message handling in the iLink 3 system, always consult the official CME Group documentation.

NotApplied Messages

In the context of SBESession, NotApplied messages, which typically indicate sequence gaps or other issues, are not processed by default. The handling of these messages is intentionally left to the client application to accommodate their specific operational requirements and error handling strategies.

The following example demonstrates how to implement a listener in a client system to react to NotApplied messages. This example assumes the client's strategy is to reset the sequence upon receiving such a message:

mdpSession.addSessionListener(new SessionListener() { @Override public void onMessage(SBEDecodedMessage message, SBESession session) { if (message.getMessage() instanceof NotApplied513Decoder) { // Client-specific logic to handle NotApplied message // In this example, the client chooses to reset the sequence session.sendSequence(null); } } });

Handling New Business Messages or Fields in CME iLink 3 Protocol

When the CME iLink 3 protocol introduces new business messages or additional fields, you need to regenerate the decoder classes using the updated descriptor file and replace the iLink-binary.jar file. The following Maven plugin configuration demonstrates how to automate this process:

<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>exec</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>uk.co.real-logic</groupId> <artifactId>sbe-tool</artifactId> <version>1.28.3</version> </dependency> </dependencies> <configuration> <classpathScope>test</classpathScope> <executable> ${java.home}\bin\java.exe </executable> <arguments> <argument>-Dsbe.output.dir=${project.basedir}\src\main\generated</argument> <argument>-Dsbe.target.language=java</argument> <argument>-Dsbe.java.generate.interfaces=true</argument> <argument>-Dsbe.decode.unknown.enum.values=true</argument> <argument>-cp</argument> <classpath/> <argument>uk.co.real_logic.sbe.SbeTool</argument> <argument>${project.basedir}\src\main\resources\sbe\ilinkbinary.xml</argument> </arguments> </configuration> </plugin>

This Maven plugin configuration uses the sbe-tool to generate Java source code from the ilinkbinary.xml descriptor file. The generated code will include the definitions for the new messages and fields. After running this plugin, you will need to rebuild your project to incorporate the changes.

Related content