def logon(senderCompID, targetCompID): msg = FIXMessage(msgtype.LOGON) msg.setField(fixtags.SenderCompID, senderCompID) msg.setField(fixtags.TargetCompID, targetCompID) msg.setField(fixtags.Username, Messages.USERNAME) msg.setField(fixtags.Password, Messages.PASSWORD) return msg
def testMsgConstruction(self): msg = FIXMessage("AB") msg.setField("45", "dgd") msg.setField("32", "aaaa") msg.setField("323", "bbbb") 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) self.assertEqual("45=dgd|32=aaaa|323=bbbb|444=2=>[611=aaa|612=bbb|613=ccc, 611=zzz|612=yyy|613=xxx]", str(msg)) msg.removeRepeatingGroupByIndex("444", 1) self.assertEqual("45=dgd|32=aaaa|323=bbbb|444=1=>[611=aaa|612=bbb|613=ccc]", str(msg)) msg.addRepeatingGroup("444", rptgrp2, 1) rptgrp3 = FIXContext() rptgrp3.setField("611", "ggg") rptgrp3.setField("612", "hhh") rptgrp3.setField("613", "jjj") rptgrp2.addRepeatingGroup("445", rptgrp3, 0) self.assertEqual("45=dgd|32=aaaa|323=bbbb|444=2=>[611=aaa|612=bbb|613=ccc, 611=zzz|612=yyy|613=xxx|445=1=>[611=ggg|612=hhh|613=jjj]]", str(msg)) grp = msg.getRepeatingGroupByTag("444", "612", "yyy") self.assertEqual("611=zzz|612=yyy|613=xxx|445=1=>[611=ggg|612=hhh|613=jjj]", str(grp))
def testAddExtractMultipleMsgs(self): journal = Journaler() msg = FIXMessage("AB") msg.setField("45", "dgd") msg.setField("32", "aaaa") msg.setField("323", "bbbb") rptgrp1 = FIXContext() rptgrp1.setField("611", "aaa") rptgrp1.setField("612", "bbb") rptgrp1.setField("613", "ccc") msg.addRepeatingGroup("444", rptgrp1, 0) session = FIXSession(1, "S1", "T1") for i in range(0, 5): msg.setField("34", str(i)) journal.persistMsg(msg, session, MessageDirection.OUTBOUND) msgs = journal.recoverMsgs(session, MessageDirection.OUTBOUND, 0, 4) for i in range(0, len(msgs)): msg.setField("34", str(i)) self.assertEqual(msg, msgs[i])
def testPickle(self): msg = FIXMessage("AB") msg.setField("45", "dgd") msg.setField("32", "aaaa") msg.setField("323", "bbbb") rptgrp1 = FIXContext() rptgrp1.setField("611", "aaa") rptgrp1.setField("612", "bbb") rptgrp1.setField("613", "ccc") msg.addRepeatingGroup("444", rptgrp1, 0) str = pickle.dumps(msg) msg2 = pickle.loads(str) self.assertEqual(msg, msg2)
def testMsgConstruction(self): msg = FIXMessage("AB") msg.setField("45", "dgd") msg.setField("32", "aaaa") msg.setField("323", "bbbb") 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) self.assertEqual( "45=dgd|32=aaaa|323=bbbb|444=2=>[611=aaa|612=bbb|613=ccc, 611=zzz|612=yyy|613=xxx]", str(msg)) msg.removeRepeatingGroupByIndex("444", 1) self.assertEqual( "45=dgd|32=aaaa|323=bbbb|444=1=>[611=aaa|612=bbb|613=ccc]", str(msg)) msg.addRepeatingGroup("444", rptgrp2, 1) rptgrp3 = FIXContext() rptgrp3.setField("611", "ggg") rptgrp3.setField("612", "hhh") rptgrp3.setField("613", "jjj") rptgrp2.addRepeatingGroup("445", rptgrp3, 0) self.assertEqual( "45=dgd|32=aaaa|323=bbbb|444=2=>[611=aaa|612=bbb|613=ccc, 611=zzz|612=yyy|613=xxx|445=1=>[611=ggg|612=hhh|613=jjj]]", str(msg)) grp = msg.getRepeatingGroupByTag("444", "612", "yyy") self.assertEqual( "611=zzz|612=yyy|613=xxx|445=1=>[611=ggg|612=hhh|613=jjj]", str(grp))
def resend_request(beginSeqNo, endSeqNo='0'): msg = FIXMessage(msgtype.RESENDREQUEST) msg.setField(fixtags.BeginSeqNo, str(beginSeqNo)) msg.setField(fixtags.EndSeqNo, str(endSeqNo)) return msg
def logon(): msg = FIXMessage(msgtype.LOGON) msg.setField(fixtags.EncryptMethod, 0) msg.setField(fixtags.HeartBtInt, 30) return msg
def resend_request(beginSeqNo, endSeqNo = '0'): msg = FIXMessage(msgtype.RESENDREQUEST) msg.setField(fixtags.BeginSeqNo, str(beginSeqNo)) msg.setField(fixtags.EndSeqNo, str(endSeqNo)) return msg
def sequence_reset(respondingTo, isGapFill): msg = FIXMessage(msgtype.SEQUENCERESET) msg.setField(fixtags.GapFillFlag, 'Y' if isGapFill else 'N') msg.setField(fixtags.MsgSeqNum, respondingTo[fixtags.BeginSeqNo]) return msg
def onNewOrder(self, connectionHandler, request): codec = connectionHandler.codec try: side = Side(int(request.getField(codec.protocol.fixtags.Side))) logging.debug( "<--- [%s] %s: %s %s %s@%s" % (codec.protocol.msgtype.msgTypeToName( request.getField(codec.protocol.fixtags.MsgType)), request.getField(codec.protocol.fixtags.ClOrdID), request.getField(codec.protocol.fixtags.Symbol), side.name, request.getField(codec.protocol.fixtags.OrderQty), request.getField(codec.protocol.fixtags.Price))) # respond with an ExecutionReport Ack msg = FIXMessage(codec.protocol.msgtype.EXECUTIONREPORT) msg.setField(codec.protocol.fixtags.Price, request.getField(codec.protocol.fixtags.Price)) msg.setField(codec.protocol.fixtags.OrderQty, request.getField(codec.protocol.fixtags.OrderQty)) msg.setField(codec.protocol.fixtags.Symbol, request.getField(codec.protocol.fixtags.OrderQty)) msg.setField(codec.protocol.fixtags.SecurityID, "GB00BH4HKS39") msg.setField(codec.protocol.fixtags.SecurityIDSource, "4") msg.setField(codec.protocol.fixtags.Symbol, request.getField(codec.protocol.fixtags.Symbol)) msg.setField(codec.protocol.fixtags.Account, request.getField(codec.protocol.fixtags.Account)) msg.setField(codec.protocol.fixtags.HandlInst, "1") msg.setField(codec.protocol.fixtags.OrdStatus, "0") msg.setField(codec.protocol.fixtags.ExecType, "0") msg.setField(codec.protocol.fixtags.LeavesQty, "0") msg.setField(codec.protocol.fixtags.Side, request.getField(codec.protocol.fixtags.Side)) msg.setField(codec.protocol.fixtags.ClOrdID, request.getField(codec.protocol.fixtags.ClOrdID)) msg.setField(codec.protocol.fixtags.Currency, request.getField(codec.protocol.fixtags.Currency)) connectionHandler.sendMsg(msg) logging.debug( "---> [%s] %s: %s %s %s@%s" % (codec.protocol.msgtype.msgTypeToName( msg.msgType), msg.getField(codec.protocol.fixtags.ClOrdID), request.getField(codec.protocol.fixtags.Symbol), side.name, request.getField(codec.protocol.fixtags.OrderQty), request.getField(codec.protocol.fixtags.Price))) except Exception as e: msg = FIXMessage(codec.protocol.msgtype.EXECUTIONREPORT) msg.setField(codec.protocol.fixtags.OrdStatus, "4") msg.setField(codec.protocol.fixtags.ExecType, "4") msg.setField(codec.protocol.fixtags.LeavesQty, "0") msg.setField(codec.protocol.fixtags.Text, str(e)) msg.setField(codec.protocol.fixtags.ClOrdID, request.getField(codec.protocol.fixtags.ClOrdID)) connectionHandler.sendMsg(msg)
def onNewOrder(self, connectionHandler, request): codec = connectionHandler.codec try: side = Side(int(request.getField(codec.protocol.fixtags.Side))) logging.debug("<--- [%s] %s: %s %s %s@%s" % (codec.protocol.msgtype.msgTypeToName(request.getField(codec.protocol.fixtags.MsgType)), request.getField(codec.protocol.fixtags.ClOrdID), request.getField(codec.protocol.fixtags.Symbol), side.name, request.getField(codec.protocol.fixtags.OrderQty), request.getField(codec.protocol.fixtags.Price))) # respond with an ExecutionReport Ack msg = FIXMessage(codec.protocol.msgtype.EXECUTIONREPORT) msg.setField(codec.protocol.fixtags.Price, request.getField(codec.protocol.fixtags.Price)) msg.setField(codec.protocol.fixtags.OrderQty, request.getField(codec.protocol.fixtags.OrderQty)) msg.setField(codec.protocol.fixtags.Symbol, request.getField(codec.protocol.fixtags.OrderQty)) msg.setField(codec.protocol.fixtags.SecurityID, "GB00BH4HKS39") msg.setField(codec.protocol.fixtags.SecurityIDSource, "4") msg.setField(codec.protocol.fixtags.Symbol, request.getField(codec.protocol.fixtags.Symbol)) msg.setField(codec.protocol.fixtags.Account, request.getField(codec.protocol.fixtags.Account)) msg.setField(codec.protocol.fixtags.HandlInst, "1") msg.setField(codec.protocol.fixtags.OrdStatus, "0") msg.setField(codec.protocol.fixtags.ExecType, "0") msg.setField(codec.protocol.fixtags.LeavesQty, "0") msg.setField(codec.protocol.fixtags.Side, request.getField(codec.protocol.fixtags.Side)) msg.setField(codec.protocol.fixtags.ClOrdID, request.getField(codec.protocol.fixtags.ClOrdID)) msg.setField(codec.protocol.fixtags.Currency, request.getField(codec.protocol.fixtags.Currency)) connectionHandler.sendMsg(msg) logging.debug("---> [%s] %s: %s %s %s@%s" % (codec.protocol.msgtype.msgTypeToName(msg.msgType), msg.getField(codec.protocol.fixtags.ClOrdID), request.getField(codec.protocol.fixtags.Symbol), side.name, request.getField(codec.protocol.fixtags.OrderQty), request.getField(codec.protocol.fixtags.Price))) except Exception as e: msg = FIXMessage(codec.protocol.msgtype.EXECUTIONREPORT) msg.setField(codec.protocol.fixtags.OrdStatus, "4") msg.setField(codec.protocol.fixtags.ExecType, "4") msg.setField(codec.protocol.fixtags.LeavesQty, "0") msg.setField(codec.protocol.fixtags.Text, str(e)) msg.setField(codec.protocol.fixtags.ClOrdID, request.getField(codec.protocol.fixtags.ClOrdID)) connectionHandler.sendMsg(msg)
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 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)
def sendOrder(self, connectionHandler): self.clOrdID = self.clOrdID + 1 codec = connectionHandler.codec msg = FIXMessage(codec.protocol.msgtype.NEWORDERSINGLE) msg.setField(codec.protocol.fixtags.Price, "%0.2f" % (random.random() * 2 + 10)) msg.setField(codec.protocol.fixtags.OrderQty, int(random.random() * 100)) 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.Account, "TEST") msg.setField(codec.protocol.fixtags.HandlInst, "1") msg.setField(codec.protocol.fixtags.ExDestination, "XLON") msg.setField(codec.protocol.fixtags.Side, int(random.random() * 2) + 1) msg.setField(codec.protocol.fixtags.ClOrdID, str(self.clOrdID)) msg.setField(codec.protocol.fixtags.Currency, "GBP") connectionHandler.sendMsg(msg) side = Side(int(msg.getField(codec.protocol.fixtags.Side))) logging.debug("---> [%s] %s: %s %s %s@%s" % (codec.protocol.msgtype.msgTypeToName(msg.msgType), msg.getField(codec.protocol.fixtags.ClOrdID), msg.getField(codec.protocol.fixtags.Symbol), side.name, msg.getField(codec.protocol.fixtags.OrderQty), msg.getField(codec.protocol.fixtags.Price)))
def decode(self, rawmsg): #msg = rawmsg.rstrip(os.linesep).split(SOH) try: rawmsg = rawmsg.decode('utf-8') msg = rawmsg.split(self.SOH) msg = msg[:-1] if len(msg) < 3: # at a minumum we require BeginString, BodyLength & Checksum return (None, 0) tag, value = msg[0].split('=', 1) if tag != self.protocol.fixtags.BeginString: logging.error("*** BeginString missing or not 1st field *** [" + tag + "]") elif value != self.protocol.beginstring: logging.error("FIX Version unexpected (Recv: %s Expected: %s)" % (value, self.protocol.beginstring)) tag, value = msg[1].split('=', 1) msgLength = len(msg[0]) + len(msg[1]) + len('10=000') + 3 if tag != self.protocol.fixtags.BodyLength: logging.error("*** BodyLength missing or not 2nd field *** [" + tag + "]") else: msgLength += int(value) # do we have a complete message on the sockt if msgLength > len(rawmsg): return (None, 0) else: remainingMsgFragment = msgLength # resplit our message msg = rawmsg[:msgLength].split(self.SOH) msg = msg[:-1] decodedMsg = FIXMessage("UNKNOWN") # logging.debug("\t-----------------------------------------") # logging.debug("\t" + "|".join(msg)) repeatingGroups = [] repeatingGroupTags = self.protocol.fixtags.repeatingGroupIdentifiers() currentContext = decodedMsg for m in msg: tag, value = m.split('=', 1) t = None try: t = self.protocol.fixtags.tagToName(tag) except KeyError: logging.info("\t%s(Unknown): %s" % (tag, value)) t = "{unknown}" if tag == self.protocol.fixtags.CheckSum: cksum = ((sum([ord(i) for i in list(self.SOH.join(msg[:-1]))]) + 1) % 256) if cksum != int(value): logging.warning("\tCheckSum: %s (INVALID) expecting %s" % (int(value), cksum)) elif tag == self.protocol.fixtags.MsgType: try: msgType = self.protocol.msgtype.msgTypeToName(value) decodedMsg.setMsgType(value) except KeyError: logging.error('*** MsgType "%s" not supported ***') if tag in repeatingGroupTags: # found the start of a repeating group if type(currentContext) is RepeatingGroupContext: # i.e. we are already in a repeating group while repeatingGroups and tag not in currentContext.repeatingGroupTags: currentContext.parent.addRepeatingGroup(currentContext.tag, currentContext) currentContext = currentContext.parent del repeatingGroups[-1] # pop the completed group off the stack ctx = RepeatingGroupContext(tag, repeatingGroupTags[tag], currentContext) repeatingGroups.append(ctx) currentContext = ctx elif repeatingGroups: # we have 1 or more repeating groups in progress & our tag isn't the start of a group while repeatingGroups and tag not in currentContext.repeatingGroupTags: currentContext.parent.addRepeatingGroup(currentContext.tag, currentContext) currentContext = currentContext.parent del repeatingGroups[-1] # pop the completed group off the stack if tag in currentContext.tags: # if the repeating group already contains this field, start the next currentContext.parent.addRepeatingGroup(currentContext.tag, currentContext) ctx = RepeatingGroupContext(currentContext.tag, currentContext.repeatingGroupTags, currentContext.parent) del repeatingGroups[-1] # pop the completed group off the stack repeatingGroups.append(ctx) currentContext = ctx # else add it to the current one currentContext.setField(tag, value) else: # this isn't a repeating group field, so just add it normally decodedMsg.setField(tag, value) return (decodedMsg, remainingMsgFragment) except UnicodeDecodeError as why: logging.error("Failed to parse message %s" % (why, )) return (None, 0)
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])