Java TCP Handler for CME iLink3
- 1 Introduction
- 2 About CME iLink 3 Binary Order Entry Platform
- 3 Getting Started with iLink3 Integration
- 4 Package Structure
- 4.1 Libraries (lib)
- 4.2 Scripts (scripts)
- 5 How to Run in Console
- 6 Key Interfaces and Features
- 6.1 SBESession
- 6.2 SBESessionState
- 6.3 SBEDecoder
- 6.4 SessionStorage
- 6.5 MessageStorage
- 6.5.1 FileMessageStorage
- 6.6 CMEConnection
- 7 Message Processing
- 8 Handling New Business Messages or Fields in CME iLink 3 Protocol
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:
ilink3-order-entry-without-binaries-${version}.jar
: This JAR file contains the core logic for establishing and managing the CME session.ilink3-binary-${version}.jar
: This JAR file includes all the business and session-level message definitions for the iLink 3 protocol, generated from theilinkbinary.xml
descriptor.ilink3-order-entry-1.0.1-small.jar
: This JAR file is responsible for decoding incoming messages.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.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.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:
Transformer.groovy
: This class contains methods for converting messages between FIX and FIXP formats.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:
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).Verify that the
JAVA_HOME
environment variable is set correctly and points to a Java 21 installation.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
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
Navigate to the
scripts
folder in your terminal and execute theMain.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:
CREATED
: The session has been created but has not yet attempted to connect. This state is often used to initialize resources.NEGOTIATED
: The negotiation response has been received. This state might be skipped if the session is recovered from a previous one.ESTABLISHED
: The Establishment Acknowledgement message has been received. The session is now ready for processing messages.REJECTED
: A negotiation rejection or establishment rejection message was received from the server.TERMINATING
: This state is entered before a terminate message is sent. It's useful for suspending message sending threads.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:
PUA-iLink_1739608077283678000.in
: File containing incoming binary messages.PUA-iLink_1739608077283678000.ndx.in
: Index file for incoming messages.PUA-iLink_1739608077283678000.out
: File containing outgoing binary messages.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.