I am having a complete mare with quickfix/Python. I'm not new to FIX, nor am I new to quickfix/J, but the Python version is not playing ball.
I have a custom spec which effectively redefines how a MassQuote, 35=i
, message looks.
A couple of SO posts suggest (1, 2) that I can create some custom groups that will let me work with custom messages, I'm unable to get this to work.
Is it because I have not loaded in my custom XML before I call fix.Message()
? My assumption is that I ought be able to do all this 'standalone', without being inside a session. Currently I'm testing this offline.
import quickfix as fix
class NoQuoteSets(fix.Group): # 296
def __init__(self):
order = fix.IntArray(3)
order[0] = 302 # QuoteSetID
order[1] = 295 # NoQuoteEntries
order[2] = 0
super().__init__(296, 302, order)
class NoQuoteEntries(fix.Group): # 295
def __init__(self):
order = fix.IntArray(7)
order[0] = 299 # QuoteEntryID
order[1] = 106 # Issuer
order[2] = 134 # BidSize
order[3] = 135 # OfferSize
order[4] = 188 # BidSpotRate
order[5] = 190 # OfferSpotRate
order[6] = 0
super().__init__(295, 299, order)
# example message taken from the spec, broken out for easier reading
MASS_QUOTE = "8=FIX.4.4|9=264|35=i|34=1113826|49=XCT|52=20171106-14:57:08.528|56=Q001|" + \
"296=5|" + \
"302=32|295=1|" + \
"299=0|106=1|134=1250000|188=1.80699|190=1.80709|" + \
"302=35|295=1|" + \
"299=0|106=1|190=148.051|" + \
"302=40|295=1|" + \
"299=0|106=1|190=1.30712|" + \
"302=37|295=1|" + \
"299=0|106=1|190=1.95713|" + \
"302=34|295=1|" + \
"299=0|135=500000|10=167|"
m = fix.Message(MASS_QUOTE.replace("|", "\x01"))
m.getField(fix.NoQuoteSets().getTag()) # tag is in the message
m.groupCount(fix.NoQuoteSets().getTag()) # no groups though...
m.getField(fix.NoQuoteEntries().getTag())
m.groupCount(fix.NoQuoteEntries().getTag())
m.hasGroup(NoQuoteSets())
m.hasGroup(NoQuoteEntries())
Result of the get/group functions:
>>> m.getField(fix.NoQuoteSets().getTag()) # tag is in the message
'5'
>>> m.groupCount(fix.NoQuoteSets().getTag()) # no groups though...
0
>>> m.getField(fix.NoQuoteEntries().getTag()) # I guess it just gets the first occurrence?
'1'
>>> m.groupCount(fix.NoQuoteEntries().getTag()) # no groups found here either...
0
>>> m.hasGroup(NoQuoteSets()) # can't find my custom class either
False
>>> m.hasGroup(NoQuoteEntries()) # sad times
False
Snippet of the xml where I (re)define what a MassQuote message is:
<message name='MassQuote' msgtype='i' msgcat='app'>
<field name='QuoteID' required='N' />
<group name='NoQuoteSets' required='Y'>
<field name='QuoteSetID' required='N' />
<group name='NoQuoteEntries' required='Y'>
<field name='QuoteEntryID' required='N' />
<field name='Issuer' required='N' />
<field name='BidSize' required='N' />
<field name='OfferSize' required='N' />
<field name='BidSpotRate' required='N' />
<field name='OfferSpotRate' required='N' />
</group>
</group>
</message>
If I try to validate message m
against my xml file, it throws an unhelpful exception:
>>> d = fix.DataDictionary()
>>> d.readFromURL("/path/to/foo.xml")
>>> d.validate(m)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/mark/.local/lib/python3.8/site-packages/quickfix.py", line 39970, in validate
return _quickfix.DataDictionary_validate(self, *args)
quickfix.FIXException: Tag not defined for this message type
I can't see any fields in the message that aren't in the xml definition, but maybe I need to sleep on it.
Other notes, I'm using Python 3.8 and installed QuickFIX (1.15.1) via pip.