forwardVenue Specific Settings   Table of ContentLogging Servicesforward
CME Specific Settings
Session Settings

  • SpecifyLastMsgSeqNumProcessed

    Option to specify the LastMsgSeqNumProcessed (tag 369) field, on every message sent. This is the required tag for the CME iLink system, so the option should be true.

  • RequestOnlyMissedMessages

    Option to turn on/off the alternative algorithm of the resend logic, which is compatible with the CME Enhanced Resend Logic. CME highly recommends using this logic, so the option should be true.

  • ResendRequestMaximumRange

    Option to set the maximum number of messages to be requested in one Resend Request (MsgType=2) message. For all resend requests, CME requires that the client system request the maximum limit of 2500 messages.

  • ConsiderRejectOnResendRequestAsGapFill

    By default, the FIX Engine disconnects the session when the "Session Level Reject" message is received in reply on the "Resend Request" message. However, CME services (e.g. Drop Copy) send the "Session Level Reject" message in some cases, in which the session should not be disconnected. Therefore, in such cases, the option should be true.

Migration to MSGW

CME MSGW does not require any new functionalities from the FIX Engine. There is only one main change on the application level. For MSGW, if you want to trade two different products on different Market Segment Gateways, then you need to create two FIX sessions with the same SenderCompId, SenderSubId, and TargetCompId, but with different TargetSubId in accordance with the particular Market Segment Gateway. After that, FIX sessions need to be connected to the corresponding IP address and port of the particular Market Segment Gateway. With the old CGW, you could do it by the one FIX session.

Note Note
In order to create two FIX sessions with the same SenderCompId and TargetCompId, you should use the constructor with the additional customSessionKey parameter.

Secure Logon

CME Globex implemented secure authentication for iLink and Drop Copy sessions on Convenience Gateway (CGW) and Market Segment Gateway (MSGW). The new logon procedure secures the client system logon with:

  • Customer identity verification - a client system logon request will be signed with security credentials issued and validated by CME Group.
  • Message confidentiality and integrity - to credential the logon message, the client system sends a keyed-hash message authentication code (HMAC) generated from a combination of the logon FIX tag values. When CME Globex receives the logon message, it uses the identical inputs to calculate the HMAC value to validate against the logon request. If the values do not match, CME Globex rejects the logon.

Customers must create secure key pairs for iLink and Drop Copy Sessions in the CME Customer Center.

CME Secure Logon requires to add several specific tags to Logon message, so our FIX Engine is ready to implement Secure Logon procedure. We have updated our CME Trading Client sample to help to implement Secure Logon.

Implementing Secure Logon consist of two parts: creating canonical request string and calculating HMAC. Canonical request string is just a union of several tags from Logon message. Please note, that Session fills values of some fields like SendingTime right before message sent, so its values can be taken from OutboundSessionMsgEvent event. To calculate HMAC a standard .NET classes, from System.Security.Cryptography, are used.

The detailed description of the CME Secure Logon procedure can be found on the CME Globex API Secure Logon page.

Example

The sample below demonstrates the basics of implementing CME Secure Logon.

C#
private void session_OutboundSessionMsgEvent(object sender, OutboundSessionMsgEventArgs args)
{
    args.ModifiedMsg = new Message(args.Msg);

    if (args.Msg.Type == MsgType.Logon)
    {
        if (!string.IsNullOrEmpty(accessKeyID) && !string.IsNullOrEmpty(secretKey))
        {
            args.ModifiedMsg.Set(Tags.EncodedTextLen, accessKeyID.Length);
            args.ModifiedMsg.Set(Tags.EncodedText, accessKeyID);
            args.ModifiedMsg.Set(encryptedPasswordMethodTag, "CME-1-SHA-256");
            args.ModifiedMsg.Remove(Tags.EncryptMethod);

            string canonicalRequest = CreateCanonicalRequest(args.ModifiedMsg, (Session)sender);
            string hash = CalculateHmac(canonicalRequest, secretKey);
            args.ModifiedMsg.Set(encryptedPasswordLenTag, hash.Length);
            args.ModifiedMsg.Set(encryptedPasswordTag, hash);
        }
    }
}

private string CreateCanonicalRequest(FIXForge.NET.FIX.Message customLogon, Session session)
{
    StringBuilder sb = new StringBuilder();

    char delimiter = '\n';

    sb.Append(session.OutSeqNum).Append(delimiter);
    sb.Append(customLogon.SenderCompID).Append(delimiter);
    sb.Append(customLogon[Tags.SenderSubID]).Append(delimiter);
    sb.Append(customLogon[Tags.SendingTime]).Append(delimiter);
    sb.Append(customLogon[Tags.TargetSubID]).Append(delimiter);
    sb.Append(session.HeartBtInt).Append(delimiter);
    sb.Append(customLogon[Tags.SenderLocationID]).Append(delimiter);
    sb.Append(customLogon[Tags.LastMsgSeqNumProcessed]).Append(delimiter);
    sb.Append(customLogon[tradingSystemNameTag]).Append(delimiter);
    sb.Append(customLogon[tradingSystemVersionTag]).Append(delimiter);
    sb.Append(customLogon[tradingSystemVendorTag]);

    return sb.ToString();
}

private string CalculateHmac(string canonicalRequest, string userKey)
{
    byte[] bytes = Base64UrlDecode(userKey);
    HMACSHA256 hmac = new HMACSHA256(bytes);
    byte[] requestBytes = Encoding.UTF8.GetBytes(canonicalRequest);
    byte[] hash = hmac.ComputeHash(requestBytes);
    return Base64UrlEncode(hash);
}