connamara / quickfixn

QuickFIX/n implements the FIX protocol on .NET.
http://quickfixn.org
Other
463 stars 552 forks source link

Enhanced CME Globex Resend Logic #841

Open dominicpalmer opened 3 months ago

dominicpalmer commented 3 months ago

Hi @gbirchmeier,

CME Globex supports both basic resend logic and what it describes as 'Enhanced' resend logic. Differences between the two are outlined in CME Globex documentation: https://www.cmegroup.com/confluence/display/EPICSANDBOX/Session+Layer+-+Resend+Request

They warn:

Basic FIX resend logic, while currently support will be phased out. ALL CLIENT SYSTEMS WILL BE REQUIRED TO MIGRATE TO ENHANCED CME GLOBEX RESEND LOGIC. For new system development, it is imperative that enhanced CME Globex resend logic be implemented.

Is enhanced resend logic something that QuickFIX/n may support, now or in the future? Ideally, wrapped up behind a config flag.

Thanks

gbirchmeier commented 3 months ago

I feel like it is, and I think I even worked on or at least verified it. But it's been a looooong time since I did that and I'm trying to remember.

I think maybe it's MaxMessagesInResendRequest? I believe we wrote that to pass CME Autocert like 10 years ago.

dominicpalmer commented 3 months ago

MaxMessagesInResendRequest of 2500 is something CME requires for both 'basic' and 'enhanced' resend logic. But the 'enhanced' requirements go further:

  • A newly detected message sequence gap must be distinguished from a continuation of a gap and a new gap versus a duplicate Resend Request must be issued accordingly.
  • When a message sequence number gap is newly detected (the sequence number received is greater than expected), issue a new Resend Request on its own sequence number. The requested sequence number range must be the next expected sequence number to infinity.
  • For each subsequent message that constitutes a continuation of the gap, issue a duplicate Resend Request. This message must be sent on the same message sequence number of the original Resend Request, tag 43-PossDupFlag must be set to 'Y' and tag 122-OrigSendingTime must not be sent.
  • The FIX Engine should detect receipt of the first message sent in response to a previous Resend Request and discontinue issuing the Resend Requests marked PossDup.
  • The FIX Engine should issue a new Resend Request, if needed, only after the receipt of the counterparty's response has been completed.
  • For resend requests from the Client System to CME Globex, both basic and enhanced resend logic are supported.

At a high level:

So, looking at where out of seq messages are handled: https://github.com/connamara/quickfixn/blob/3200a309c1ff05ced8fcf7a6966d2f5f3c278a79/QuickFIXn/Session.cs#L1064

In particular:

protected void DoTargetTooHigh(Message msg, SeqNumType msgSeqNum)
{
    string beginString = msg.Header.GetString(Fields.Tags.BeginString);

    Log.OnEvent("MsgSeqNum too high, expecting " + _state.NextTargetMsgSeqNum + " but received " + msgSeqNum);
    _state.Queue(msgSeqNum, msg);

    if (_state.ResendRequested())
    {
        ResendRange range = _state.GetResendRange();

        if (!SendRedundantResendRequests && msgSeqNum >= range.BeginSeqNo)
        {
            Log.OnEvent("Already sent ResendRequest FROM: " + range.BeginSeqNo + " TO: " + range.EndSeqNo + ".  Not sending another.");
            return;
        }
    }

    GenerateResendRequest(beginString, msgSeqNum);
}

This looks to me like the flag SendRedundantResendRequests can be used to prevent clients sending any further resend requests, while a resend is already requested. But there's no logic to send the same resend request using the msgSeqNum of the first resend request sent on a gap opening, with PossDupFlag=Y.

So my hunch was that the 'enhanced' logic isn't there, but if autocert is passed then it must be? One of the tests in the Autocert+ spec (dated 2022) explicitly requires use of the enhanced resend logic. See page 20: https://www.cmegroup.com/tools-information/webhelp/autocert-drop-copy4/Content/AutoCert-Drop-Copy-4.pdf

gbirchmeier commented 3 months ago

I think you are right, and QF/n does not fully support CME Globex Enhanced Resend.

This is a big deal, and I am very interested in helping get this support into QF/n.

I think the most annoying part will be writing new and accurate Acceptance tests to capture the intended new behavior. Updating the implementation will be the easy(er) part.