Exemple #1
0
    def testDecode(self):
        protocol = importlib.import_module("pyfix.FIX44")
        codec = Codec(protocol)
        inMsg = b'8=FIX.4.4\x019=817\x0135=J\x0134=953\x0149=FIX_ALAUDIT\x0156=BFUT_ALAUDIT\x0143=N\x0152=20150615-09:21:42.459\x0170=00000002664ASLO1001\x01626=2\x0110626=5\x0171=0\x0160=20150615-10:21:42\x01857=1\x0173=1\x0111=00000006321ORLO1\x0138=100.0\x01800=100.0\x01124=1\x0132=100.0\x0117=00000009758TRLO1\x0131=484.50\x0154=2\x0153=100.0\x0155=FTI\x01207=XEUE\x01454=1\x01455=EOM5\x01456=A\x01200=201506\x01541=20150619\x01461=FXXXXX\x016=484.50\x0174=2\x0175=20150615\x0178=2\x0179=TEST123\x0130009=12345\x01467=00000014901CALO1001\x019520=00000014898CALO1\x0180=33.0\x01366=484.50\x0181=0\x01153=484.50\x0110626=5\x0179=TEST124\x0130009=12345\x01467=00000014903CALO1001\x019520=00000014899CALO1\x0180=67.0\x01366=484.50\x0181=0\x01153=484.50\x0110626=5\x01453=3\x01448=TEST1\x01447=D\x01452=3\x01802=2\x01523=12345\x01803=3\x01523=TEST1\x01803=19\x01448=TEST1WA\x01447=D\x01452=38\x01802=4\x01523=Test1 Wait\x01803=10\x01523= \x01803=26\x01523=\x01803=3\x01523=TestWaCRF2\x01803=28\x01448=hagap\x01447=D\x01452=11\x01802=2\x01523=GB\x01803=25\x01523=BarCapFutures.FETService\x01803=24\x0110=033\x01'
        msg, remaining = codec.decode(inMsg)

        self.assertEqual("8=FIX.4.4|9=817|35=J|34=953|49=FIX_ALAUDIT|56=BFUT_ALAUDIT|43=N|52=20150615-09:21:42.459|70=00000002664ASLO1001|626=2|10626=5|71=0|60=20150615-10:21:42|857=1|73=1=>[11=00000006321ORLO1|38=100.0|800=100.0]|124=1=>[32=100.0|17=00000009758TRLO1|31=484.50]|54=2|53=100.0|55=FTI|207=XEUE|454=1=>[455=EOM5|456=A]|200=201506|541=20150619|461=FXXXXX|6=484.50|74=2|75=20150615|78=1=>[79=TEST123]|30009=12345|467=00000014903CALO1001|9520=00000014899CALO1|80=67.0|366=484.50|81=0|153=484.50|79=TEST124|453=3=>[448=TEST1|447=D|452=3|802=2=>[523=12345|803=3, 523=TEST1|803=19], 448=TEST1WA|447=D|452=38|802=4=>[523=Test1 Wait|803=10, 523= |803=26, 523=|803=3, 523=TestWaCRF2|803=28], 448=hagap|447=D|452=11|802=2=>[523=GB|803=25, 523=BarCapFutures.FETService|803=24]]|10=033", str(msg))
Exemple #2
0
 def testDecode(self):
     protocol = importlib.import_module("pyfix.FIX44")
     codec = Codec(protocol)
     inMsg = b'8=FIX.4.4\x019=817\x0135=J\x0134=953\x0149=FIX_ALAUDIT\x0156=BFUT_ALAUDIT\x0143=N\x0152=20150615-09:21:42.459\x0170=00000002664ASLO1001\x01626=2\x0171=0\x0160=20150615-10:21:42\x01857=1\x0173=1\x0111=00000006321ORLO1\x0138=100.0\x01800=100.0\x01124=1\x0132=100.0\x0117=00000009758TRLO1\x0131=484.50\x0154=2\x0153=100.0\x0155=FTI\x01207=XEUE\x01454=1\x01455=EOM5\x01456=A\x01200=201506\x01541=20150619\x01461=FXXXXX\x016=484.50\x0174=2\x0175=20150615\x0178=2\x0179=TEST123\x01467=00000014901CALO1001\x0180=33.0\x01366=484.50\x0181=0\x01153=484.50\x0179=TEST124\x01467=00000014903CALO1001\x0180=67.0\x01366=484.50\x0181=0\x01153=484.50\x01453=3\x01448=TEST1\x01447=D\x01452=3\x01802=2\x01523=12345\x01803=3\x01523=TEST1\x01803=19\x01448=TEST1WA\x01447=D\x01452=38\x01802=4\x01523=Test1 Wait\x01803=10\x01523= \x01803=26\x01523=\x01803=3\x01523=TestWaCRF2\x01803=28\x01448=hagap\x01447=D\x01452=11\x01802=2\x01523=GB\x01803=25\x01523=BarCapFutures.FETService\x01803=24\x0110=033\x01'
     msg, remaining = codec.decode(inMsg)
     self.assertEqual(
         "8=FIX.4.4|9=817|35=J|34=953|49=FIX_ALAUDIT|56=BFUT_ALAUDIT|43=N|52=20150615-09:21:42.459|70=00000002664ASLO1001|626=2|71=0|60=20150615-10:21:42|857=1|73=1=>[11=00000006321ORLO1|38=100.0|800=100.0]|124=1=>[32=100.0|17=00000009758TRLO1|31=484.50]|54=2|53=100.0|55=FTI|207=XEUE|454=1=>[455=EOM5|456=A]|200=201506|541=20150619|461=FXXXXX|6=484.50|74=2|75=20150615|78=2=>[79=TEST123|467=00000014901CALO1001|80=33.0|366=484.50|81=0|153=484.50, 79=TEST124|467=00000014903CALO1001|80=67.0|366=484.50|81=0|153=484.50]|453=3=>[448=TEST1|447=D|452=3|802=2=>[523=12345|803=3, 523=TEST1|803=19], 448=TEST1WA|447=D|452=38|802=4=>[523=Test1 Wait|803=10, 523= |803=26, 523=|803=3, 523=TestWaCRF2|803=28], 448=hagap|447=D|452=11|802=2=>[523=GB|803=25, 523=BarCapFutures.FETService|803=24]]|10=033",
         str(msg))
Exemple #3
0
 def __init__(self, engine, protocol, sock=None, addr=None, observer=None):
     self.codec = Codec(protocol)
     self.engine = engine
     self.connectionState = ConnectionState.CONNECTED
     self.session = None
     self.addr = addr
     self.observer = observer
     self.msgBuffer = b''
     self.heartbeatPeriod = 30.0
     self.msgHandlers = []
     self.sock = sock
     self.heartbeatTimerRegistration = None
     self.expectedHeartbeatRegistration = None
     self.socketEvent = FileDescriptorEventRegistration(self.handle_read, sock, EventType.READ)
     self.engine.eventManager.registerHandler(self.socketEvent)
Exemple #4
0
class Connection:
    def __init__(self):
        self.isServer = False
        self.messages = []

        protocol = importlib.import_module("pyfix.FIX44")
        self.codec = Codec(protocol)

        s = 1
        mock_session = mock.Mock()
        mock_session.senderCompId = "sender"
        mock_session.targetCompId = "target"
        mock_session.allocateSndSeqNo.return_value = s

        msg = FIXMessage(self.codec.protocol.msgtype.NEWORDERSINGLE)
        msg.setField(self.codec.protocol.fixtags.Price, "123.45")
        msg.setField(self.codec.protocol.fixtags.OrderQty, 9876)
        msg.setField(self.codec.protocol.fixtags.Symbol, "VOD.L")
        msg.setField(self.codec.protocol.fixtags.SecurityID, "GB00BH4HKS39")
        msg.setField(self.codec.protocol.fixtags.SecurityIDSource, "4")
        msg.setField(self.codec.protocol.fixtags.Symbol, "VOD.L")
        msg.setField(self.codec.protocol.fixtags.Account, "TEST")
        msg.setField(self.codec.protocol.fixtags.HandlInst, "1")
        msg.setField(self.codec.protocol.fixtags.ExDestination, "XLON")
        msg.setField(self.codec.protocol.fixtags.Side, 1)
        msg.setField(self.codec.protocol.fixtags.ClOrdID, "abcdefg")
        msg.setField(self.codec.protocol.fixtags.Currency, "GBP")

        rptgrp1 = FIXContext()
        rptgrp1.setField("611", "aaa")
        rptgrp1.setField("612", "bbb")
        rptgrp1.setField("613", "ccc")

        msg.addRepeatingGroup("444", rptgrp1, 0)

        for i in range(0, 20):
            encoded = self.codec.pack(msg, mock_session)
            self.messages.append(self.codec.parse(encoded.encode('utf-8'))[0])

    def isServer(self):
        return self.isServer

    def name(self):
        return "A Session"

    def messages(self):
        return self.messages
Exemple #5
0
    def testEncode(self):
        from datetime import datetime

        print("%s" % (datetime.utcnow()))

        mock_session = mock.Mock()
        mock_session.senderCompId = "sender"
        mock_session.targetCompId = "target"
        mock_session.allocateSndSeqNo.return_value = 1

        protocol = importlib.import_module("pyfix.FIX44")
        codec = Codec(protocol)

        msg = FIXMessage(codec.protocol.msgtype.NEWORDERSINGLE)
        msg.setField(codec.protocol.fixtags.Price, "123.45")
        msg.setField(codec.protocol.fixtags.OrderQty, 9876)
        msg.setField(codec.protocol.fixtags.Symbol, "VOD.L")
        msg.setField(codec.protocol.fixtags.SecurityID, "GB00BH4HKS39")
        msg.setField(codec.protocol.fixtags.SecurityIDSource, "4")
        msg.setField(codec.protocol.fixtags.Symbol, "VOD.L")
        msg.setField(codec.protocol.fixtags.Account, "TEST")
        msg.setField(codec.protocol.fixtags.HandlInst, "1")
        msg.setField(codec.protocol.fixtags.ExDestination, "XLON")
        msg.setField(codec.protocol.fixtags.Side, 1)
        msg.setField(codec.protocol.fixtags.ClOrdID, "abcdefg")
        msg.setField(codec.protocol.fixtags.Currency, "GBP")

        rptgrp1 = FIXContext()
        rptgrp1.setField("611", "aaa")
        rptgrp1.setField("612", "bbb")
        rptgrp1.setField("613", "ccc")

        msg.addRepeatingGroup("444", rptgrp1, 0)

        rptgrp2 = FIXContext()
        rptgrp2.setField("611", "zzz")
        rptgrp2.setField("612", "yyy")
        rptgrp2.setField("613", "xxx")
        msg.addRepeatingGroup("444", rptgrp2, 1)

        result = codec.encode(msg, mock_session)
        expected = '8=FIX.4.4\x019=201\x0135=D\x0149=sender\x0156=target\x0134=1\x0152=20150619-11:08:54.000\x0144=123.45\x0138=9876\x0155=VOD.L\x0148=GB00BH4HKS39\x0122=4\x011=TEST\x0121=1\x01100=XLON\x0154=1\x0111=abcdefg\x0115=GBP\x01444=2\x01611=aaa\x01612=bbb\x01613=ccc\x01611=zzz\x01612=yyy\x01613=xxx\x0110=255\x01'
        self.assertEqual(expected, result)
Exemple #6
0
    def testEncode(self):
        from datetime import datetime

        print("%s" % (datetime.utcnow()))

        mock_session = mock.Mock()
        mock_session.senderCompId = "sender"
        mock_session.targetCompId = "target"
        mock_session.allocateSndSeqNo.return_value = 1

        protocol = importlib.import_module("pyfix.FIX44")
        codec = Codec(protocol)

        msg = FIXMessage(codec.protocol.msgtype.NEWORDERSINGLE)
        msg.setField(codec.protocol.fixtags.Price, "123.45")
        msg.setField(codec.protocol.fixtags.OrderQty, 9876)
        msg.setField(codec.protocol.fixtags.Symbol, "VOD.L")
        msg.setField(codec.protocol.fixtags.SecurityID, "GB00BH4HKS39")
        msg.setField(codec.protocol.fixtags.SecurityIDSource, "4")
        msg.setField(codec.protocol.fixtags.Symbol, "VOD.L")
        msg.setField(codec.protocol.fixtags.Account, "TEST")
        msg.setField(codec.protocol.fixtags.HandlInst, "1")
        msg.setField(codec.protocol.fixtags.ExDestination, "XLON")
        msg.setField(codec.protocol.fixtags.Side, 1)
        msg.setField(codec.protocol.fixtags.ClOrdID, "abcdefg")
        msg.setField(codec.protocol.fixtags.Currency, "GBP")

        rptgrp1 = FIXContext()
        rptgrp1.setField("611", "aaa")
        rptgrp1.setField("612", "bbb")
        rptgrp1.setField("613", "ccc")

        msg.addRepeatingGroup("444", rptgrp1, 0)

        rptgrp2 = FIXContext()
        rptgrp2.setField("611", "zzz")
        rptgrp2.setField("612", "yyy")
        rptgrp2.setField("613", "xxx")
        msg.addRepeatingGroup("444", rptgrp2, 1)

        result = codec.encode(msg, mock_session)
        expected = '8=FIX.4.4\x019=201\x0135=D\x0149=sender\x0156=target\x0134=1\x0152=20150619-11:08:54.000\x0144=123.45\x0138=9876\x0155=VOD.L\x0148=GB00BH4HKS39\x0122=4\x011=TEST\x0121=1\x01100=XLON\x0154=1\x0111=abcdefg\x0115=GBP\x01444=2\x01611=aaa\x01612=bbb\x01613=ccc\x01611=zzz\x01612=yyy\x01613=xxx\x0110=255\x01'
        self.assertEqual(expected, result)
Exemple #7
0
class FIXConnectionHandler(object):
    def __init__(self, engine, protocol, sock=None, addr=None, observer=None):
        self.codec = Codec(protocol)
        self.engine = engine
        self.connectionState = ConnectionState.CONNECTED
        self.session = None
        self.addr = addr
        self.observer = observer
        self.msgBuffer = b''
        self.heartbeatPeriod = 30.0
        self.msgHandlers = []
        self.sock = sock
        self.heartbeatTimerRegistration = None
        self.expectedHeartbeatRegistration = None
        self.socketEvent = FileDescriptorEventRegistration(self.handle_read, sock, EventType.READ)
        self.engine.eventManager.registerHandler(self.socketEvent)

    def address(self):
        return self.addr

    def disconnect(self):
        self.handle_close()

    def _notifyMessageObservers(self, msg, direction, persistMessage=True):
        if persistMessage is True:
            self.engine.journaller.persistMsg(msg, self.session, direction)
        for handler in filter(lambda x: (x[1] is None or x[1] == direction) and (x[2] is None or x[2] == msg.msgType), self.msgHandlers):
            handler[0](self, msg)

    def addMessageHandler(self, handler, direction = None, msgType = None):
        self.msgHandlers.append((handler, direction, msgType))

    def removeMessageHandler(self, handler, direction = None, msgType = None):
        remove = filter(lambda x: x[0] == handler and
                                  (x[1] == direction or direction is None) and
                                  (x[2] == msgType or msgType is None), self.msgHandlers)
        for h in remove:
            self.msgHandlers.remove(h)

    def _sendHeartbeat(self):
        self.sendMsg(self.codec.protocol.messages.Messages.heartbeat())

    def _expectedHeartbeat(self, type, closure):
        logging.warning("Expected heartbeat from peer %s" % (self.expectedHeartbeatRegistration ,))
        self.sendMsg(self.codec.protocol.messages.Messages.test_request())

    def registerLoggedIn(self):
        self.heartbeatTimerRegistration = TimerEventRegistration(lambda type, closure: self._sendHeartbeat(), self.heartbeatPeriod)
        self.engine.eventManager.registerHandler(self.heartbeatTimerRegistration)
        # register timeout for 10% more than we expect
        self.expectedHeartbeatRegistration = TimerEventRegistration(self._expectedHeartbeat, self.heartbeatPeriod * 1.10)
        self.engine.eventManager.registerHandler(self.expectedHeartbeatRegistration)


    def registerLoggedOut(self):
        if self.heartbeatTimerRegistration is not None:
            self.engine.eventManager.unregisterHandler(self.heartbeatTimerRegistration)
            self.heartbeatTimerRegistration = None
        if self.expectedHeartbeatRegistration is not None:
            self.engine.eventManager.unregisterHandler(self.expectedHeartbeatRegistration)
            self.expectedHeartbeatRegistration = None

    def _handleResendRequest(self, msg):
        protocol = self.codec.protocol
        responses = []

        beginSeqNo = msg[protocol.fixtags.BeginSeqNo]
        endSeqNo = msg[protocol.fixtags.EndSeqNo]
        if int(endSeqNo) == 0:
            endSeqNo = sys.maxsize
        logging.info("Received resent request from %s to %s", beginSeqNo, endSeqNo)
        replayMsgs = self.engine.journaller.recoverMsgs(self.session, MessageDirection.OUTBOUND, beginSeqNo, endSeqNo)
        gapFillBegin = int(beginSeqNo)
        gapFillEnd = int(beginSeqNo)
        for replayMsg in replayMsgs:
            msgSeqNum = int(replayMsg[protocol.fixtags.MsgSeqNum])
            if replayMsg[protocol.fixtags.MsgType] in protocol.msgtype.sessionMessageTypes:
                gapFillEnd = msgSeqNum + 1
            else:
                if self.engine.shouldResendMessage(self.session, replayMsg):
                    if gapFillBegin < gapFillEnd:
                        # we need to send a gap fill message
                        gapFillMsg = FIXMessage(protocol.msgtype.SEQUENCERESET)
                        gapFillMsg.setField(protocol.fixtags.GapFillFlag, 'Y')
                        gapFillMsg.setField(protocol.fixtags.MsgSeqNum, gapFillBegin)
                        gapFillMsg.setField(protocol.fixtags.NewSeqNo, str(gapFillEnd))
                        responses.append(gapFillMsg)

                    # and then resent the replayMsg
                    replayMsg.removeField(protocol.fixtags.BeginString)
                    replayMsg.removeField(protocol.fixtags.BodyLength)
                    replayMsg.removeField(protocol.fixtags.SendingTime)
                    replayMsg.removeField(protocol.fixtags.SenderCompID)
                    replayMsg.removeField(protocol.fixtags.TargetCompID)
                    replayMsg.removeField(protocol.fixtags.CheckSum)
                    replayMsg.setField(protocol.fixtags.PossDupFlag, "Y")
                    responses.append(replayMsg)

                    gapFillBegin = msgSeqNum + 1
                else:
                    gapFillEnd = msgSeqNum + 1
                    responses.append(replayMsg)

        if gapFillBegin < gapFillEnd:
            # we need to send a gap fill message
            gapFillMsg = FIXMessage(protocol.msgtype.SEQUENCERESET)
            gapFillMsg.setField(protocol.fixtags.GapFillFlag, 'Y')
            gapFillMsg.setField(protocol.fixtags.MsgSeqNum, gapFillBegin)
            gapFillMsg.setField(protocol.fixtags.NewSeqNo, str(gapFillEnd))
            responses.append(gapFillMsg)

        return responses

    def handle_read(self, type, closure):
        protocol = self.codec.protocol
        try:
            msg = self.sock.recv(8192)
            if msg:
                self.msgBuffer = self.msgBuffer + msg
                (decodedMsg, parsedLength) = self.codec.decode(self.msgBuffer)
                self.msgBuffer = self.msgBuffer[parsedLength:]
                while decodedMsg is not None and self.connectionState != ConnectionState.DISCONNECTED:
                    self.processMessage(decodedMsg)
                    (decodedMsg, parsedLength) = self.codec.decode(self.msgBuffer)
                    self.msgBuffer = self.msgBuffer[parsedLength:]
                if self.expectedHeartbeatRegistration is not None:
                    self.expectedHeartbeatRegistration.reset()
            else:
                logging.debug("Connection has been closed")
                self.disconnect()
        except ConnectionError as why:
                logging.debug("Connection has been closed %s" % (why, ))
                self.disconnect()

    def handleSessionMessage(self, msg):
        return -1

    def processMessage(self, decodedMsg):
        protocol = self.codec.protocol

        beginString = decodedMsg[protocol.fixtags.BeginString]
        if beginString != protocol.beginstring:
            logging.warning("FIX BeginString is incorrect (expected: %s received: %s)", (protocol.beginstring, beginString))
            self.disconnect()
            return

        msgType = decodedMsg[protocol.fixtags.MsgType]

        try:
            responses = []
            if msgType in protocol.msgtype.sessionMessageTypes:
                (recvSeqNo, responses) = self.handleSessionMessage(decodedMsg)
            else:
                recvSeqNo = decodedMsg[protocol.fixtags.MsgSeqNum]

            # validate the seq number
            (seqNoState, lastKnownSeqNo) = self.session.validateRecvSeqNo(recvSeqNo)

            if seqNoState is False:
                # We should send a resend request
                logging.info("Requesting resend of messages: %s to %s" % (lastKnownSeqNo, 0))
                responses.append(protocol.messages.Messages.resend_request(lastKnownSeqNo, 0))
                # we still need to notify if we are processing Logon message
                if msgType == protocol.msgtype.LOGON:
                    self._notifyMessageObservers(decodedMsg, MessageDirection.INBOUND, False)
            else:
                self.session.setRecvSeqNo(recvSeqNo)
                self._notifyMessageObservers(decodedMsg, MessageDirection.INBOUND)


            for m in responses:
                self.sendMsg(m)

        except SessionWarning as sw:
            logging.warning(sw)
        except SessionError as se:
            logging.error(se)
            self.disconnect()
        except DuplicateSeqNoError:
            try:
                if decodedMsg[protocol.fixtags.PossDupFlag] == "Y":
                    logging.debug("Received duplicate message with PossDupFlag set")
            except KeyError:
                pass
            finally:
                logging.error("Failed to process message with duplicate seq no (MsgSeqNum: %s) (and no PossDupFlag='Y') - disconnecting" % (recvSeqNo, ))
                self.disconnect()


    def handle_close(self):
        if self.connectionState != ConnectionState.DISCONNECTED:
            logging.info("Client disconnected")
            self.registerLoggedOut()
            self.sock.close()
            self.connectionState = ConnectionState.DISCONNECTED
            self.msgHandlers.clear()
            if self.observer is not None:
                self.observer.notifyDisconnect(self)
            self.engine.eventManager.unregisterHandler(self.socketEvent)


    def sendMsg(self, msg):
        if self.connectionState != ConnectionState.CONNECTED and self.connectionState != ConnectionState.LOGGED_IN:
            raise FIXException(FIXException.FIXExceptionReason.NOT_CONNECTED)

        encodedMsg = self.codec.encode(msg, self.session).encode('utf-8')
        self.sock.send(encodedMsg)
        if self.heartbeatTimerRegistration is not None:
            self.heartbeatTimerRegistration.reset()

        decodedMsg, junk = self.codec.decode(encodedMsg)

        try:
            self._notifyMessageObservers(decodedMsg, MessageDirection.OUTBOUND)
        except DuplicateSeqNoError:
            logging.error("We have sent a message with a duplicate seq no, failed to persist it (MsgSeqNum: %s)" % (decodedMsg[self.codec.protocol.fixtags.MsgSeqNum]))