2

I wrote an initiator using the Python API for QuickFIX 1.13.3.

It simply sends a message of type TradeCaptureReport (code: AE) to an acceptor. I should receive a TradeCaptureReportAck (indeed, I receive it if I use another client), but nothing comes back.

Using Wireshark I could see that logon and logout are performed correctly and the heartbeat is kept properly as well.

The Application I have written is defined as follows:

import sys
import time
import thread
import quickfix as fix
import quickfix44 as fix44
from datetime import datetime

class Application (fix.Application):
    orderID = 0
    execID = 0
    tradeID = 0
    global settings

    def onCreate (self, sessionID):
        self.sessionID = sessionID
        print ("Application created - session: " + sessionID.toString ())

    def onLogon (self, sessionID):
        print ("Logon")

    def onLogout (self, sessionID):
        print ("Logout")

    def onMessage (self, message, sessionID):
        print (message)

    def toAdmin (self, message, sessionID):
        msgType = fix.MsgType ()
        message.getHeader ().getField (msgType)
        if (msgType.getValue () == fix.MsgType_Logon):
            message.setField (fix.Password (settings.get (self.sessionID).getString ("Password")))
            message.setField (fix.ResetSeqNumFlag (True))

    def fromAdmin (self, message, sessionID):
        pass

    def toApp (self, message, sessionID):
        pass

    def fromApp (self, message, sessionID):
        pass

    def genOrderID (self):
        self.orderID += 1
        return repr (self.orderID)

    def genTradeReportID (self):
        self.tradeID += 1
        return repr (self.tradeID)

    def genExecID (self):
        self.execID += 1
        return repr (self.execID)

    def run (self):
        time.sleep (5)
        self.queryEnterOrder ()
        time.sleep (5)

    def queryEnterOrder (self):
        print ("\nTradeCaptureReport (AE)\n")
        trade = fix.Message ()
        trade.getHeader ().setField (fix.BeginString (fix.BeginString_FIX44))
        trade.getHeader ().setField (fix.MsgType (fix.MsgType_TradeCaptureReport))

        trade.setField (fix.TradeReportTransType (fix.TradeReportTransType_NEW))       # 487
        trade.setField (fix.TradeReportID (self.genTradeReportID ()))                  # 571
        trade.setField (fix.TrdSubType (4))                        # 829
        trade.setField (fix.SecondaryTrdType (2))                  # 855
        trade.setField (fix.Symbol ("MYSYMBOL"))                   # 55
        trade.setField (fix.LastQty (22))                          # 32
        trade.setField (fix.LastPx (21.12))                        # 31
        trade.setField (fix.TradeDate ((datetime.now ().strftime ("%Y%m%d"))))                      # 75
        trade.setField (fix.TransactTime ((datetime.now ().strftime ("%Y%m%d-%H:%M:%S.%f"))[:-3]))  # 60
        trade.setField (fix.PreviouslyReported (False))            # 570

        group = fix44.TradeCaptureReport ().NoSides ()

        group.setField (fix.Side (fix.Side_SELL))                  # 54
        group.setField (fix.OrderID (self.genOrderID ()))          # 37
        group.setField (fix.NoPartyIDs (1))                        # 453
        group.setField (fix.PartyIDSource (fix.PartyIDSource_PROPRIETARY_CUSTOM_CODE)) # 447
        group.setField (fix.PartyID ("CLEARING"))                  # 448
        group.setField (fix.PartyRole (fix.PartyRole_CLEARING_ACCOUNT))                # 452
        trade.addGroup (group)

        group.setField (fix.Side (fix.Side_BUY))                   # 54
        group.setField (fix.OrderID (self.genOrderID ()))          # 37
        group.setField (fix.NoPartyIDs (1))                        # 453
        group.setField (fix.PartyIDSource (fix.PartyIDSource_PROPRIETARY_CUSTOM_CODE)) # 447
        group.setField (fix.PartyID ("CLEARING"))                  # 448
        group.setField (fix.PartyRole (fix.PartyRole_CLEARING_ACCOUNT))                # 452
        trade.addGroup (group)

        fix.Session.sendToTarget (trade, self.sessionID)

Which is run thanks to the following snippet:

file = sys.argv[1]
settings = fix.SessionSettings (file)
application = Application ()
storeFactory = fix.FileStoreFactory (settings)
initiator = fix.SocketInitiator (application, storeFactory, settings)

initiator.start ()
application.run ()
initiator.stop ()

Update

The exchange of messages goeas as follows (I = Initiator, A = Acceptor):

1. I ---------- LOGON -----------> A
2. I <--------- LOGON ------------ A
3. I ---- TradeCaptureReport ----> A
4. I ---------- LOGOFF ----------> A
5. I <--------- LOGOFF ----------- A

As you can spot, between 3. and 4. a message of type TradeCaptureReportAck is missing.

Any hint is most welcome!

Jir
  • 2,985
  • 8
  • 44
  • 66
  • Why are you logging off after sending a message and not waiting for the ACK, which maybe the case why you aren't receiving an ACK ? – DumbCoder Mar 27 '12 at 16:06
  • I think that 5 seconds is more than enough to receive an ACK, considered that the ACKs to the logon and logoff procedures are correctly received almost immediately. However, I increased the time to 35 seconds, and I also manage to send/receive the heartbeat. Still no TradeCaptureReportAck is coming back. – Jir Apr 02 '12 at 20:44

2 Answers2

0

Try implementing your fromAdmin and fromApp method, you should be seeing your return FIX messages here. Check if your TradeCaptureReportAck reaches here and confirm they follow the same calls as logon, logout and heartbeat. And implement your onMessage method, or check if you receive any FIX message here. This should be your place where you should be seeing the ACK return message.

DumbCoder
  • 5,696
  • 3
  • 29
  • 40
  • I implemented all the methods you mentioned. Stil, I cannot see anything coming back. It is strange, though. The `TradeCaptureReport` message I send is acknowledged by TCP (so it is correctly received by the server). – Jir Mar 26 '12 at 12:22
  • @Jir - That means is your other side is sending any ACK message at all for your message ? Check what is happening at other side if you can. There should be some message being received at your end either an ACK or a reject. – DumbCoder Mar 26 '12 at 13:02
  • I've updated the original post by adding the messages exchanged (at the FIX level). To answer your question, no, no ACK/reject is received by the initiator. – Jir Mar 27 '12 at 14:11
0

If your message sequence number is not our of sync, then they never sent the act you are looking for! Instead of logging off, you should at least wait around for a heartbeat to check the sequence number before logging off.

Phil Cooper
  • 5,747
  • 1
  • 25
  • 41
  • I've tried to increase the time to 35 seconds (see comment above). The heartbeat is correctly sent/received but there's no sign of TradeCaptureReportAck. – Jir Apr 02 '12 at 20:45