QuickFIX/Python读取包含重复组的自定义消息

2024-10-02 12:28:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在和quickfix/Python玩一个完整的游戏。我对FIX并不陌生,对quickfix/J也不陌生,但Python版本并不是什么新鲜事

我有一个自定义规范,它可以有效地重新定义MassQuote,35=i消息的外观

一些帖子建议(12)我可以创建一些自定义组,让我可以处理自定义消息,但我无法实现这一点

是不是因为我在调用fix.Message()之前没有加载自定义XML?我的假设是,我应该能够独立完成所有这些工作,而不必在会话中。目前我正在离线测试

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())

get/group函数的结果:

>>> 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

我(重新)定义MassQuote消息的xml片段:

<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>

如果我尝试根据xml文件验证消息m,它会抛出一个无用的异常:

>>> 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

我在消息中看不到任何字段不是xml定义中的,但可能我需要考虑一下

另外,我使用的是Python 3.8,并通过pip安装了QuickFIX(1.15.1)


Tags: thename消息fieldmessageinitgrouprequired
1条回答
网友
1楼 · 发布于 2024-10-02 12:28:02

我明白了

首先,定义一个扩展quickfix.Message的新类

import quickfix as fix

class MassQuote(fix.Message):
    """Custom flavour of a MassQuote"""
    def __init__(self, *args):
        super().__init__(*args)
        self.getHeader().setField(fix.MsgType('i'))
    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)

然后创建一个quickfix.DataDictionary并读入XML规范:

data_dictionary = fix.DataDictionary()
data_dictionary.readFromURL("/path/to/foo.xml")

现在,您可以通过构造函数Message(fix_string, data_dictionary)实例化自定义修复消息:

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|"

mass_quote = MassQuote(MASS_QUOTE.replace("|", "\x01"), data_dictionary)

然后,您可以进行健全性检查:

data_dictionary.validate(mass_quote)

为了提取组,您需要创建一个“组”对象并使用它:

mass_quote.getField(fix.NoQuoteSets().getTag())    # '5' => sanity check
mass_quote.groupCount(fix.NoQuoteSets().getTag())  # 5   => nice!

# define the object to hold the group
quote_set = MassQuote.NoQuoteSets()
# copy 1st group into object
mass_quote.getGroup(1, quote_set)                  # Swig Object of type 'Group *' at 0x7f747f9652a0>
# now we can access fields of this group
quote_set_id = quote_set.getField(302)             # '32'

如果要访问嵌套组,则调用:

# define object to hold nested entry
entry = MassQuote.NoQuoteSets.NoQuoteEntries() 
# copy 1st group into object
quote_set.getGroup(1, entry)
# now we can access fields of this group
entry_id = int(entry.getField(299))

相关问题 更多 >

    热门问题