/// <summary> /// Validates a FixMessage. Returns empty string if valid, otherwise a message indicating the validation errors. /// </summary> /// <param name="fixMessage"></param> /// <returns>string</returns> public static string ValidateFixMessage(FixMessage fixMessage) { if (fixMessage == null) { return("Fix Message Invalid."); } string validationMsg = string.Empty; try { if (!fixMessage.Contains(Tag.MsgType)) { validationMsg += "MsgType"; } if (!fixMessage.Contains(Tag.BeginString)) { validationMsg += ", BeginString"; } if (!fixMessage.Contains(Tag.SenderCompID)) { validationMsg += ", SenderCompID"; } if (!fixMessage.Contains(Tag.TargetCompID)) { validationMsg += ", TargetCompID"; } if (validationMsg != string.Empty) { validationMsg = string.Format("Missing fields: {0}.", validationMsg); } } catch (Exception ex) { validationMsg = string.Format("ValidateFixMessage: Error: {0}", ex.Message); } return(validationMsg); }
public void Enqueue(FixMessage fixMessage) { base.Enqueue(fixMessage); }
/// <summary> /// Adds an array of fields to the FixMessage. /// </summary> /// <param name="fields">An array of fields.</param> private void AddFieldArray(string[] fields) { // This local is used for repeating groups (see below.) StringCollection groupFields = new StringCollection(); // Add each field after parse the values into a "Tag=Value" pair. foreach (string field in fields) { // The 'Split' method has a bothersome habit of leaving a null entry when a token delimiter ends up a the end // of the string. This will quickly filter out those byproducts of the 'Split'. if (field == string.Empty) { continue; } // Break the field up into the 'Tag' and 'Value' fields, parse them and add them to the hash table. string[] values = field.Split('='); if (values.Length > 1) { try { //tagNumber Tag tag = MarkThree.TagConverter.ConvertFrom(values[0]); string stringValue = values[1]; // Handle repeating group fields here. // Per the FIX spec: // "Fields within repeating data groups must be specified in the order that the fields are // specified in the message definition within the FIX specification document. The NoXXX field, // where XXX is the field being counted, specifies the number of repeating group instances and // must immediately precede the repeating group contents." // Generally: // 1. record the number of repeating group instances for a group when the NoXXX field occurs. // 2. when each field in the group is read, save it in the groupFields array, unless it the last field. // 3. when the last field of the group occurs, add a group entry to the group object. // Order is important (See note from FIX spec above.) groupFields index 0 is the first field of the group, 1 is the second, etc. // The xxxxGroup object (derived from class RepeatingGroup) holds the all of the repeating groups relating to "xxxx". // Each repeating group in xxxxGroup is called an Entry. // The groupFields array is temp space to hold the group fields as they are read from the FIX string. switch (tag) { // IOIQualifiers. // There is only one field (IOIQualifier) in each group, so groupFields is not used. case Tag.NoIOIQualifiers: // This field indicates the start of a set of repeating groups. // But for FIX 4.0, only one IOIQualifier is allowed and this field is not used. // So don't create the group object here, create it when the first qualifier is encountered. // See IOIQualifier below. break; case Tag.IOIQualifier: if (!this.ContainsKey(Tag.IoiQualifierGroup)) { // if there is not yet an IoiQualifierGroup, create the group object to hold the repeating groups. this[Tag.IoiQualifierGroup] = new IoiQualifierGroup(); } // get the group object created previously. IoiQualifierGroup ioiQualifierGroup = (IoiQualifierGroup)this[Tag.IoiQualifierGroup]; // IOIQualifier is the only field in this group, so add the group to the IoiQualifierGroup object. // IOIQualifier is not a string in FixMessage, so it needs to be parsed into its correct type. ioiQualifierGroup.Add((IOIQualifier)FixMessage.Parse(tag, stringValue)); break; // RoutingIDs. (Valid in FIX 4.2 only.) // There are 2 fields in each group here, so save the first one in the groupFields array. // (It could just be saved in a string variable, but the array is more general. A group can have more than 2 fields.) // For example: // The following FIX string describes three repeating groups for Routing (215=3), with the first group having // two fields: RoutingType=3 (216=3), and RoutingID=RTEID1 (217=RTEID1). Similarly for groups 2 and 3. // 215=3|216=3|217=RTEID1|216=3|217=RTEID2|216=3|217=RTEID3| case Tag.NoRoutingIDs: // This field indicates the start of a set of repeating groups. // Create the group object to hold the repeating groups. this[Tag.RoutingGroup] = new RoutingGroup(); break; case Tag.RoutingType: // Save the RoutingType string in the groupFields collection. groupFields.Add(stringValue); break; case Tag.RoutingID: // RoutingID is the last field in this group, so add the group to the RoutingGroup object. if (this.Contains(Tag.RoutingGroup)) { // get the group object created above. RoutingGroup routingGroup = (RoutingGroup)this[Tag.RoutingGroup]; if (groupFields.Count > 0) { // Add the current group fields to the group object. // The first (and in this case only) item in the groupFields array is RoutingType. // RoutingType combined with the RoutingID is a complete group. // RoutingID is a string in FixMessage, so it doesn't need to be parsed. // RoutingType is not a string in FixMessage, so it needs to be parsed into its correct type. RoutingType routingType = (RoutingType)FixMessage.Parse(Tag.RoutingType, groupFields[0]); routingGroup.Add(routingType, stringValue); // once the group has been added, clear out the temp array for the next group. groupFields.Clear(); } } break; // Regular processing of (non-repeating) FIX fields. default: this[tag] = FixMessage.Parse(tag, stringValue); break; } } catch { string SenderComp = this.Contains(Tag.SenderCompID) ? this.SenderCompID : string.Empty; string TargetComp = this.Contains(Tag.TargetCompID) ? this.TargetCompID : string.Empty; MarkThree.EventLog.Error("MsgSeqNum={0}, SenderCompID={1}, TargetCompID={2}: Can't parse FIX field {3}={4}. Field ignored.", this.MsgSeqNum, SenderComp, TargetComp, values[0], values[1]); } } } }
/// <summary> /// Converts the tag number string to a Tag, uses /// the Parse method of the FixMessage class to convert /// the text value to the proper type, and adds the field. /// </summary> /// <param name="tagNumber"></param> /// <param name="stringValue"></param> public void AddField(string tagNumber, string stringValue) { Tag tag = MarkThree.TagConverter.ConvertFrom(tagNumber); this[tag] = FixMessage.Parse(tag, stringValue); }