簡體   English   中英

如何以人類可讀的格式記錄 QuickFix 消息

[英]How to log QuickFix message in human-readable format

我想以某種解析模式記錄 QuickFix 消息,例如標記名、值

我找不到現有的功能。 我正在使用 QuickFix.Net。

我正在考慮提供某種方法來遍歷所有呈現的標簽並使用數據字典解析它們。

有一個 Java 示例http://www.quickfixj.org/confluence/display/qfj/Using+Message+Metadata可以轉換為 .NET 並且可能證明是有用的:

public class MetadataExample {
    public static void main(String[] args) throws Exception {
        DataDictionary dd = new DataDictionary("FIX44.xml");

        Message m = new Message("8=FIX.4.4\0019=247\00135=s\00134=5\001"
                + "49=sender\00152=20060319-09:08:20.881\001"
                + "56=target\00122=8\00140=2\00144=9\00148=ABC\00155=ABC\001"
                + "60=20060319-09:08:19\001548=184214\001549=2\001"
                + "550=0\001552=2\00154=1\001453=2\001448=8\001447=D\001"
                + "452=4\001448=AAA35777\001447=D\001452=3\00138=9\00154=2\001"
                + "453=2\001448=8\001447=D\001452=4\001448=aaa\001447=D\001"
                + "452=3\00138=9\00110=056\001", dd);

        MessagePrinter printer = new MessagePrinter();
        printer.print(System.out, dd, m);
    }
}

public class MessagePrinter {

    public void print(DataDictionary dd, Message message) throws FieldNotFound {
        String msgType = message.getHeader().getString(MsgType.FIELD);
        printFieldMap("", dd, msgType, message.getHeader());
        printFieldMap("", dd, msgType, message);
        printFieldMap("", dd, msgType, message.getTrailer());
    }

    private void printFieldMap(String prefix, DataDictionary dd, String msgType, FieldMap fieldMap)
            throws FieldNotFound {

        Iterator fieldIterator = fieldMap.iterator();
        while (fieldIterator.hasNext()) {
            Field field = (Field) fieldIterator.next();
            if (!isGroupCountField(dd, field)) {
                String value = fieldMap.getString(field.getTag());
                if (dd.hasFieldValue(field.getTag())) {
                    value = dd.getValueName(field.getTag(), fieldMap.getString(field.getTag())) + " (" + value + ")";
                }
                System.out.println(prefix + dd.getFieldName(field.getTag()) + ": " + value);
            }
        }

        Iterator groupsKeys = fieldMap.groupKeyIterator();
        while (groupsKeys.hasNext()) {
            int groupCountTag = ((Integer) groupsKeys.next()).intValue();
            System.out.println(prefix + dd.getFieldName(groupCountTag) + ": count = "
                    + fieldMap.getInt(groupCountTag));
            Group g = new Group(groupCountTag, 0);
            int i = 1;
            while (fieldMap.hasGroup(i, groupCountTag)) {
                if (i > 1) {
                    System.out.println(prefix + "  ----");
                }
                fieldMap.getGroup(i, g);
                printFieldMap(prefix + "  ", dd, msgType, g);
                i++;
            }
        }
    }

    private boolean isGroupCountField(DataDictionary dd, Field field) {
        return dd.getFieldTypeEnum(field.getTag()) == FieldType.NumInGroup;
    }

}

Output:

BeginString: FIX.4.4
BodyLength: 247
MsgSeqNum: 5
MsgType: NewOrderCross (s)
SenderCompID: sender
SendingTime: 20060319-09:08:20.881
TargetCompID: target
SecurityIDSource: EXCHANGE_SYMBOL (8)
OrdType: LIMIT (2)
Price: 9
SecurityID: ABC
Symbol: ABC
TransactTime: 20060319-09:08:19
CrossID: 184214
CrossType: CROSS_TRADE_WHICH_IS_EXECUTED_PARTIALLY_AND_THE_REST_IS_CANCELLED (2)
CrossPrioritization: NONE (0)
NoSides: count = 2
  OrderQty: 9
  Side: BUY (1)
  NoPartyIDs: count = 2
    PartyIDSource: PROPRIETARY_CUSTOM_CODE (D)
    PartyID: 8
    PartyRole: CLEARING_FIRM (4)
    ----
    PartyIDSource: PROPRIETARY_CUSTOM_CODE (D)
    PartyID: AAA35777
    PartyRole: CLIENT_ID (3)
  ----
  OrderQty: 9
  Side: SELL (2)
  NoPartyIDs: count = 2
    PartyIDSource: PROPRIETARY_CUSTOM_CODE (D)
    PartyID: 8
    PartyRole: CLEARING_FIRM (4)
    ----
    PartyIDSource: PROPRIETARY_CUSTOM_CODE (D)
    PartyID: aaa
    PartyRole: CLIENT_ID (3)
CheckSum: 056

quickfix 中沒有方法以人類可讀的格式解析消息。 另一種選擇是當您在 onMessage 中處理傳入的 FIX 消息時,您無論如何都會解析它以讀取消息。 您可以在此處列出文件或數據庫的標記名和值。 但是這樣做的任何操作都可能會減慢您的 Quickfix 引擎,因為寫入文件或數據庫總是很慢。 所以當心!

另一種選擇是將您的消息記錄到您的數據庫而不是文件,然后在數據庫中執行所有操作,但這意味着兩次解析消息,即在您的引擎和數據庫中。 但是你會更靈活地決定你想讀什么,不讀什么。

可以通過QuickFix.Message.InitializeXML方法獲取某個字典的QuickFix.Message.ToXML()到output標簽。

例如。

QuickFix.Message msg = new QuickFix.Message();
// Create your message
QuickFix.Message.InitializeXML(@"c:\quickfix\spec\FIX44.xml");
Console.WriteLine(msg.ToXML());

它會給你每個字段的標簽,但如果它是一個枚舉值,則不會給出字段內容的含義。

這是我在 output window 中看到的示例:

<message>
<header>
    <field name="BeginString" number="8"><![CDATA[FIX.4.4]]></field>
    <field name="MsgType" number="35" enum="Heartbeat"><![CDATA[0]]></field>
    <field name="MsgSeqNum" number="34"><![CDATA[10]]></field>
    <field name="SenderCompID" number="49"><![CDATA[VCMVCON]]></field>
    <field name="SendingTime" number="52"><![CDATA[20110815-09:35:33.782]]></field>
    <field name="TargetCompID" number="56"><![CDATA[BLPVCON]]></field>
  </header>
  <body>
    <field name="TestReqID" number="112"><![CDATA[R.0001.0010.000A.093519]]></field>
  </body>
  <trailer>
  </trailer>
</message>

我采用了 Martin Vseticka 的 Java 答案並在 C# 中制作了我自己的版本,主要區別在於我選擇使用StringBuilder而不是打印出每一行,並且我添加了一個擴展方法。 我選擇了一種類似於 JSON 的格式,它根本不需要太多工作就可以生成實際有效的 JSON。

public static class MessageDecoder
{
    public static string Decode(this Message message, DataDictionary dataDictionary)
    {
        return DecodeMessage(message, dataDictionary);
    }

    public static string DecodeMessage(Message message, DataDictionary dataDictionary)
    {
        var messageStr = new StringBuilder("FIX {\n");

        var msgType = message.Header.GetString(Tags.MsgType);
        DecodeFieldMap("  ", dataDictionary, messageStr, msgType, message.Header);
        DecodeFieldMap("  ", dataDictionary, messageStr, msgType, message);
        DecodeFieldMap("  ", dataDictionary, messageStr, msgType, message.Trailer);

        messageStr.Append("}");
        return messageStr.ToString();
    }

    private static void DecodeFieldMap(string prefix, DataDictionary dd, StringBuilder str, string msgType, FieldMap fieldMap)
    {
        foreach (var kvp in fieldMap)
        {
            if (dd.IsGroup(msgType, kvp.Key)) continue;

            var field = dd.FieldsByTag[kvp.Key];

            var value = fieldMap.GetString(field.Tag);
            if (dd.FieldHasValue(field.Tag, value))
            {
                value = $"{field.EnumDict[value]} ({value})";
            }

            str.AppendFormat("{0}{1} = {2};\n", prefix, field.Name, value);
        }

        foreach (var groupTag in fieldMap.GetGroupTags())
        {
            var groupField = dd.FieldsByTag[groupTag];
            str.AppendFormat("{0}{1} (count {2}) {{\n", prefix, groupField.Name, fieldMap.GetInt(groupTag));

            for (var i = 1; i <= fieldMap.GetInt(groupTag); i++)
            {
                var group = fieldMap.GetGroup(i, groupTag);
                var groupPrefix = prefix + "  ";
                str.AppendFormat("{0}{{\n", groupPrefix);
                DecodeFieldMap(groupPrefix + "  ", dd, str, msgType, group);
                str.AppendFormat("{0}}},\n", groupPrefix);
            }

            str.Remove(str.Length - 2, 1); // Remove last ","
            str.AppendFormat("{0}}};\n", prefix);
        }
    }
}

Output 看起來像這樣(我修剪了一堆字段):

FIX {
  BeginString = FIX.4.4;
  BodyLength = 821;
  MsgSeqNum = 123;
  MsgType = EXECUTION_REPORT (8);
  PossDupFlag = YES (Y);
  SendingTime = 20200125-02:26:17.405;
  ExecID = 76615:3975388;
  ExecInst = WORK (2);
  LastMkt = XCEC;
  OrdStatus = EXPIRED (C);
  OrdType = LIMIT (2);
  OpenClose = OPEN (O);
  SecurityDesc = Copper;
  MaturityDate = 20200129;
  CustOrderCapacity = ALL_OTHER (4);
  ManualOrderIndicator = MANUAL (Y);
  NoPartyIDs (count 2) {
    {
      PartyIDSource = PROPRIETARY (D);
      PartyID = 0;
      PartyRole = ACCOUNT_TYPE (205);
    },
    {
      PartyIDSource = PROPRIETARY (D);
      PartyID = FIX_UAT;
      PartyRole = CLEARING_ACCOUNT (83);
    }
  };
  NoSecurityAltID (count 2) {
    {
      SecurityAltID = 1HGF0;
      SecurityAltIDSource = RIC_CODE (5);
    },
    {
      SecurityAltID = 170831;
      SecurityAltIDSource = EXCHANGE_SECURITY_ID (8);
    }
  };
  CheckSum = 077;
}

這是 Python 中的答案。根據用戶的需要,這里提供了三種解決方案。

  1. 標記為 XML
  2. 字段列表(嵌入組)。
  3. 類似 JSON 的 output。

在 quickfix Python 庫中,未公開 FieldMap 字段和組鍵迭代器。 所以方法是首先生成 XML 並遍歷樹。 也無法訪問 DataDictionary 的 getFieldType 方法,因此必須對字典進行預處理以存儲用於轉換和處理組的字段類型。

import quickfix as fix

import xml.etree.ElementTree as ET
from collections import OrderedDict
import json

string = "8=FIX.4.4\0019=247\00135=s\00134=5\00149=sender\00152=20060319-09:08:20.881\00156=target\00122=8\00140=2\00144=9\00148=ABC\00155=ABC\00160=20060319-09:08:19\001548=184214\001549=2\001550=0\001552=2\00154=1\001453=2\001448=8\001447=D\001452=4\001448=AAA35777\001447=D\001452=3\00138=9\00154=2\001453=2\001448=8\001447=D\001452=4\001448=aaa\001447=D\001452=3\00138=9\00110=056\001"

# Load data dictionary
data_dictionary_xml = "FIX44.xml"
data_dictionary = fix.DataDictionary(data_dictionary_xml)
fix.Message().InitializeXML(data_dictionary_xml)

# String as fix message according to dictionary
message = fix.Message(string, data_dictionary, True)

# Marked-up XML
xml = message.toXML()
print(xml)

def get_field_type_map(data_dictionary_xml):
  """Preprocess DataDictionary to get field types."""
  field_type_map = {}
  with open(data_dictionary_xml, "r") as f:
    xml = f.read()
    tree = ET.fromstring(xml)
    fields = tree.find("fields")
    for field in fields.iter("field"):
      field_type_map[field.attrib["number"]] = field.attrib["type"]
  return field_type_map

field_type_map = get_field_type_map(data_dictionary_xml)

INT_TYPES = ["INT", "LENGTH", "NUMINGROUP", "QTY", "SEQNUM"]
FLOAT_TYPES = ["FLOAT", "PERCENTAGE", "PRICE", "PRICEOFFSET"]
BOOL_TYPES = ["BOOLEAN"]
DATETIME_TYPES = ["LOCALMKTDATE", "MONTHYEAR", "UTCDATEONLY", "UTCTIMEONLY", "UTCTIMESTAMP"]
STRING_TYPES = ["AMT", "CHAR", "COUNTRY", "CURRENCY", "DATA", "EXCHANGE", "MULTIPLEVALUESTRING", "STRING"]

def field_map_to_list(field_map, field_type_map):
  fields = []
  field_iter = iter([el for el in field_map if el.tag == "field"])
  group_iter = iter([el for el in field_map if el.tag == "group"])
  for field in field_iter:
    # Extract raw value
    raw = field.text
    # Type the raw value
    field_type = field_type_map.get(field.attrib["number"])
    if field_type in INT_TYPES:
      value = int(raw)
    elif field_type in FLOAT_TYPES:
      value = float(raw)
    elif field_type in BOOL_TYPES:
      value = bool(int(raw))
    elif field_type in DATETIME_TYPES:
      value = str(raw)
    elif field_type in STRING_TYPES:
      value = str(raw)
    else:
      value = str(raw)
    # field.attrib should contain "name", "number", "enum"
    _field = {
      **field.attrib,
      "type": field_type,
      "raw": raw,
      "value": value,
    }
    # If NUMINGROUP type then iterate groups the number indicated
    # This assumes groups are in the same order as their field keys
    if field_type == "NUMINGROUP":
      groups = []
      for _ in range(value):
        group = next(group_iter)
        # Parse group as field map
        group_fields = field_map_to_list(group, field_type_map)
        groups.append(group_fields)
      _field["groups"] = groups
    fields.append(_field)
  return fields

def field_map_to_dict(field_map, field_type_map):
  fields = OrderedDict()
  field_iter = iter([el for el in field_map if el.tag == "field"])
  group_iter = iter([el for el in field_map if el.tag == "group"])
  for field in field_iter:
    # Define key
    # field.attrib should contain "name", "number", "enum"
    key = field.attrib.get("name") or field.attrib.get("number")
    # Extract raw value
    raw = field.text
    # Type the raw value
    field_type = field_type_map.get(field.attrib["number"])
    if field_type in INT_TYPES:
      value = int(raw)
    elif field_type in FLOAT_TYPES:
      value = float(raw)
    elif field_type in BOOL_TYPES:
      value = bool(int(raw))
    elif field_type in DATETIME_TYPES:
      value = str(raw)
    elif field_type in STRING_TYPES:
      value = str(raw)
    else:
      value = str(raw)
    # If NUMINGROUP type then iterate groups the number indicated
    # This assumes groups are in the same order as their field keys
    if field_type == "NUMINGROUP":
      groups = []
      for _ in range(value):
        group = next(group_iter)
        # Parse group as field map
        group_fields = field_map_to_dict(group, field_type_map)
        groups.append(group_fields)
      fields[key] = groups
    else:
      # Preference enum above value
      fields[key] = field.attrib.get("enum") or value
  return fields

def parse_message_xml(xml, field_type_map, as_dict=False):
  parsed = OrderedDict()
  tree = ET.fromstring(xml)
  for field_map in tree:
    if not as_dict:
      parsed[field_map.tag] = field_map_to_list(field_map, field_type_map)
    else:
      parsed[field_map.tag] = field_map_to_dict(field_map, field_type_map)
  return parsed

# List of fields (groups embedded)
parsed = parse_message_xml(xml, field_type_map, as_dict=False)
print(json.dumps(parsed, indent=True))

# JSON-like output
parsed = parse_message_xml(xml, field_type_map, as_dict=True)
print(json.dumps(parsed, indent=True))

輸出:

<message>
  <header>
    <field name="BeginString" number="8"><![CDATA[FIX.4.4]]></field>
    <field name="BodyLength" number="9"><![CDATA[247]]></field>
    <field name="MsgType" number="35" enum="NewOrderCross"><![CDATA[s]]></field>
    <field name="MsgSeqNum" number="34"><![CDATA[5]]></field>
    <field name="SenderCompID" number="49"><![CDATA[sender]]></field>
    <field name="SendingTime" number="52"><![CDATA[20060319-09:08:20.881]]></field>
    <field name="TargetCompID" number="56"><![CDATA[target]]></field>
  </header>
  <body>
    <field name="SecurityIDSource" number="22" enum="EXCHANGE_SYMBOL"><![CDATA[8]]></field>
    <field name="OrdType" number="40" enum="LIMIT"><![CDATA[2]]></field>
    <field name="Price" number="44"><![CDATA[9]]></field>
    <field name="SecurityID" number="48"><![CDATA[ABC]]></field>
    <field name="Symbol" number="55"><![CDATA[ABC]]></field>
    <field name="TransactTime" number="60"><![CDATA[20060319-09:08:19]]></field>
    <field name="CrossID" number="548"><![CDATA[184214]]></field>
    <field name="CrossType" number="549" enum="CROSS_TRADE_WHICH_IS_EXECUTED_PARTIALLY_AND_THE_REST_IS_CANCELLED_ONE_SIDE_IS_FULLY_EXECUTED_THE_OTHER_SIDE_IS_PARTIALLY_EXECUTED_WITH_THE_REMAINDER_BEING_CANCELLED_THIS_IS_EQUIVALENT_TO_AN_IMMEDIATE_OR_CANCEL_ON_THE_OTHER_SIDE_NOTE_THE_CROSSPRIORITZATION"><![CDATA[2]]></field>
    <field name="CrossPrioritization" number="550" enum="NONE"><![CDATA[0]]></field>
    <field name="NoSides" number="552" enum="BOTH_SIDES"><![CDATA[2]]></field>
    <group>
      <field name="Side" number="54" enum="BUY"><![CDATA[1]]></field>
      <field name="NoPartyIDs" number="453"><![CDATA[2]]></field>
      <field name="OrderQty" number="38"><![CDATA[9]]></field>
      <group>
        <field name="PartyID" number="448"><![CDATA[8]]></field>
        <field name="PartyIDSource" number="447" enum="PROPRIETARY_CUSTOM_CODE"><![CDATA[D]]></field>
        <field name="PartyRole" number="452" enum="CLEARING_FIRM"><![CDATA[4]]></field>
      </group>
      <group>
        <field name="PartyID" number="448"><![CDATA[AAA35777]]></field>
        <field name="PartyIDSource" number="447" enum="PROPRIETARY_CUSTOM_CODE"><![CDATA[D]]></field>
        <field name="PartyRole" number="452" enum="CLIENT_ID"><![CDATA[3]]></field>
      </group>
    </group>
    <group>
      <field name="Side" number="54" enum="SELL"><![CDATA[2]]></field>
      <field name="NoPartyIDs" number="453"><![CDATA[2]]></field>
      <field name="OrderQty" number="38"><![CDATA[9]]></field>
      <group>
        <field name="PartyID" number="448"><![CDATA[8]]></field>
        <field name="PartyIDSource" number="447" enum="PROPRIETARY_CUSTOM_CODE"><![CDATA[D]]></field>
        <field name="PartyRole" number="452" enum="CLEARING_FIRM"><![CDATA[4]]></field>
      </group>
      <group>
        <field name="PartyID" number="448"><![CDATA[aaa]]></field>
        <field name="PartyIDSource" number="447" enum="PROPRIETARY_CUSTOM_CODE"><![CDATA[D]]></field>
        <field name="PartyRole" number="452" enum="CLIENT_ID"><![CDATA[3]]></field>
      </group>
    </group>
  </body>
  <trailer>
    <field name="CheckSum" number="10"><![CDATA[056]]></field>
  </trailer>
</message>
{
 "header": [
  {
   "number": "8",
   "name": "BeginString",
   "value": "FIX.4.4",
   "raw": "FIX.4.4",
   "type": "STRING"
  },
  {
   "number": "9",
   "name": "BodyLength",
   "value": 247,
   "raw": "247",
   "type": "LENGTH"
  },
  {
   "number": "35",
   "name": "MsgType",
   "enum": "NewOrderCross",
   "value": "s",
   "raw": "s",
   "type": "STRING"
  },
  {
   "number": "34",
   "name": "MsgSeqNum",
   "value": 5,
   "raw": "5",
   "type": "SEQNUM"
  },
  {
   "number": "49",
   "name": "SenderCompID",
   "value": "sender",
   "raw": "sender",
   "type": "STRING"
  },
  {
   "number": "52",
   "name": "SendingTime",
   "value": "20060319-09:08:20.881",
   "raw": "20060319-09:08:20.881",
   "type": "UTCTIMESTAMP"
  },
  {
   "number": "56",
   "name": "TargetCompID",
   "value": "target",
   "raw": "target",
   "type": "STRING"
  }
 ],
 "body": [
  {
   "number": "22",
   "name": "SecurityIDSource",
   "enum": "EXCHANGE_SYMBOL",
   "value": "8",
   "raw": "8",
   "type": "STRING"
  },
  {
   "number": "40",
   "name": "OrdType",
   "enum": "LIMIT",
   "value": "2",
   "raw": "2",
   "type": "CHAR"
  },
  {
   "number": "44",
   "name": "Price",
   "value": 9.0,
   "raw": "9",
   "type": "PRICE"
  },
  {
   "number": "48",
   "name": "SecurityID",
   "value": "ABC",
   "raw": "ABC",
   "type": "STRING"
  },
  {
   "number": "55",
   "name": "Symbol",
   "value": "ABC",
   "raw": "ABC",
   "type": "STRING"
  },
  {
   "number": "60",
   "name": "TransactTime",
   "value": "20060319-09:08:19",
   "raw": "20060319-09:08:19",
   "type": "UTCTIMESTAMP"
  },
  {
   "number": "548",
   "name": "CrossID",
   "value": "184214",
   "raw": "184214",
   "type": "STRING"
  },
  {
   "number": "549",
   "name": "CrossType",
   "enum": "CROSS_TRADE_WHICH_IS_EXECUTED_PARTIALLY_AND_THE_REST_IS_CANCELLED_ONE_SIDE_IS_FULLY_EXECUTED_THE_OTHER_SIDE_IS_PARTIALLY_EXECUTED_WITH_THE_REMAINDER_BEING_CANCELLED_THIS_IS_EQUIVALENT_TO_AN_IMMEDIATE_OR_CANCEL_ON_THE_OTHER_SIDE_NOTE_THE_CROSSPRIORITZATION",
   "value": 2,
   "raw": "2",
   "type": "INT"
  },
  {
   "number": "550",
   "name": "CrossPrioritization",
   "enum": "NONE",
   "value": 0,
   "raw": "0",
   "type": "INT"
  },
  {
   "number": "552",
   "name": "NoSides",
   "enum": "BOTH_SIDES",
   "value": 2,
   "raw": "2",
   "type": "NUMINGROUP",
   "groups": [
    [
     {
      "number": "54",
      "name": "Side",
      "enum": "BUY",
      "value": "1",
      "raw": "1",
      "type": "CHAR"
     },
     {
      "number": "453",
      "name": "NoPartyIDs",
      "groups": [
       [
        {
         "number": "448",
         "name": "PartyID",
         "value": "8",
         "raw": "8",
         "type": "STRING"
        },
        {
         "number": "447",
         "name": "PartyIDSource",
         "enum": "PROPRIETARY_CUSTOM_CODE",
         "value": "D",
         "raw": "D",
         "type": "CHAR"
        },
        {
         "number": "452",
         "name": "PartyRole",
         "enum": "CLEARING_FIRM",
         "value": 4,
         "raw": "4",
         "type": "INT"
        }
       ],
       [
        {
         "number": "448",
         "name": "PartyID",
         "value": "AAA35777",
         "raw": "AAA35777",
         "type": "STRING"
        },
        {
         "number": "447",
         "name": "PartyIDSource",
         "enum": "PROPRIETARY_CUSTOM_CODE",
         "value": "D",
         "raw": "D",
         "type": "CHAR"
        },
        {
         "number": "452",
         "name": "PartyRole",
         "enum": "CLIENT_ID",
         "value": 3,
         "raw": "3",
         "type": "INT"
        }
       ]
      ],
      "value": 2,
      "raw": "2",
      "type": "NUMINGROUP"
     },
     {
      "number": "38",
      "name": "OrderQty",
      "value": 9,
      "raw": "9",
      "type": "QTY"
     }
    ],
    [
     {
      "number": "54",
      "name": "Side",
      "enum": "SELL",
      "value": "2",
      "raw": "2",
      "type": "CHAR"
     },
     {
      "number": "453",
      "name": "NoPartyIDs",
      "groups": [
       [
        {
         "number": "448",
         "name": "PartyID",
         "value": "8",
         "raw": "8",
         "type": "STRING"
        },
        {
         "number": "447",
         "name": "PartyIDSource",
         "enum": "PROPRIETARY_CUSTOM_CODE",
         "value": "D",
         "raw": "D",
         "type": "CHAR"
        },
        {
         "number": "452",
         "name": "PartyRole",
         "enum": "CLEARING_FIRM",
         "value": 4,
         "raw": "4",
         "type": "INT"
        }
       ],
       [
        {
         "number": "448",
         "name": "PartyID",
         "value": "aaa",
         "raw": "aaa",
         "type": "STRING"
        },
        {
         "number": "447",
         "name": "PartyIDSource",
         "enum": "PROPRIETARY_CUSTOM_CODE",
         "value": "D",
         "raw": "D",
         "type": "CHAR"
        },
        {
         "number": "452",
         "name": "PartyRole",
         "enum": "CLIENT_ID",
         "value": 3,
         "raw": "3",
         "type": "INT"
        }
       ]
      ],
      "value": 2,
      "raw": "2",
      "type": "NUMINGROUP"
     },
     {
      "number": "38",
      "name": "OrderQty",
      "value": 9,
      "raw": "9",
      "type": "QTY"
     }
    ]
   ]
  }
 ],
 "trailer": [
  {
   "number": "10",
   "name": "CheckSum",
   "value": "056",
   "raw": "056",
   "type": "STRING"
  }
 ]
}
{
 "header": {
  "BeginString": "FIX.4.4",
  "BodyLength": 247,
  "MsgType": "NewOrderCross",
  "MsgSeqNum": 5,
  "SenderCompID": "sender",
  "SendingTime": "20060319-09:08:20.881",
  "TargetCompID": "target"
 },
 "body": {
  "SecurityIDSource": "EXCHANGE_SYMBOL",
  "OrdType": "LIMIT",
  "Price": 9.0,
  "SecurityID": "ABC",
  "Symbol": "ABC",
  "TransactTime": "20060319-09:08:19",
  "CrossID": "184214",
  "CrossType": "CROSS_TRADE_WHICH_IS_EXECUTED_PARTIALLY_AND_THE_REST_IS_CANCELLED_ONE_SIDE_IS_FULLY_EXECUTED_THE_OTHER_SIDE_IS_PARTIALLY_EXECUTED_WITH_THE_REMAINDER_BEING_CANCELLED_THIS_IS_EQUIVALENT_TO_AN_IMMEDIATE_OR_CANCEL_ON_THE_OTHER_SIDE_NOTE_THE_CROSSPRIORITZATION",
  "CrossPrioritization": "NONE",
  "NoSides": [
   {
    "Side": "BUY",
    "NoPartyIDs": [
     {
      "PartyID": "8",
      "PartyIDSource": "PROPRIETARY_CUSTOM_CODE",
      "PartyRole": "CLEARING_FIRM"
     },
     {
      "PartyID": "AAA35777",
      "PartyIDSource": "PROPRIETARY_CUSTOM_CODE",
      "PartyRole": "CLIENT_ID"
     }
    ],
    "OrderQty": 9
   },
   {
    "Side": "SELL",
    "NoPartyIDs": [
     {
      "PartyID": "8",
      "PartyIDSource": "PROPRIETARY_CUSTOM_CODE",
      "PartyRole": "CLEARING_FIRM"
     },
     {
      "PartyID": "aaa",
      "PartyIDSource": "PROPRIETARY_CUSTOM_CODE",
      "PartyRole": "CLIENT_ID"
     }
    ],
    "OrderQty": 9
   }
  ]
 },
 "trailer": {
  "CheckSum": "056"
 }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM