forwardFIX Engine Thread Safety   Table of ContentFIX Sessionsforward
FIX Repeating Groups
Structure of FIX Repeating Groups

Sometimes fields of the same tag number can appear multiple times in the same message within a so-called repeating group.

The following diagram depicts the general structure of a repeating group in a FIX message:

Repeating Group Structure

Each repeating group starts from the field which identifies the number of repeating entries within repeating group. Such a leading field must immediately precede the repeating group entries. In the referenced example, the leading field is defined by the NoRoutingIDs tag.

Each entry of a repeating group has a selected field which in turn identifies the beginning of a group new entry. This field must occur in a raw message before any other tag from a single repeating group entry. In other words, these fields separate repeating group entries from each other. RoutingType field is an example of such a separator.

Important aspects of FIX repeating groups structure:

  • Well-defined FIX messages assume all fields of a repeating group that follow one another. The appearance of an arbitrary field, which doesn't belong to repeating group (according to the FIX specification), automatically indicates the end of the repeating group. Therefore, the further appearance of fields from the repeating group is disallowed by the FIX Standard.
  • It is possible for repeating groups to appear inside of another repeating group. In such case, all entries of the inner repeating group belong to the single entry of the outer repeating group.
  • The number of entries or instances, which are defined by the value of the leading field (tag), must correspond to the number of instances/entries, which actually appear in the message. In particular, number of tags-separators must equal to value of the leading field.

Group class

OnixS .NET FIX Engine exposes Group class to encapsulate all aspects related with handling FIX repeating groups.

Since a repeating group is identified by the leading field, which defines the number of repeating instances, OnixS .NET FIX Engine follows this approach in handling repeating groups. In particular, the Group object is accessed using its leading (number of instances) field. Changing the value of this field affects the length of a repeating group. Removing this field from a message or other repeating group removes all entries of the repeating group.

Adding Group into Message

To create a new repeating group or modify the number of instances, the SetGroup(Int32, Int32) method is available.

Note Note
Setting non-zero integer value for a field, which defines a number of instances of a repeating group, implicitly creates and/or changes the length of the repeating group object.
Accessing Repeating Group Entries

To obtain a reference to the Group object that represents an existing repeating group of the message, the GetGroup(Int32) method is available.

The Group class works with fields, as well as with embedded repeating groups in the same manner as the Message class. The only difference in accessing field values is the availability of an additional parameter, which defines the index of the repeating group entry whose field is being accessed. Entries indexing starts from zero. Additionally, the Group class supports the IEnumerable interface, therefore you can use a Group object in the foreach operator to enumerate group entries of a repeating group.

Removing Repeating Group from Message

To remove an entire repeating group together with its leading tag, the Remove(Int32) method is exposed by the FieldSet class.

Ill-Formed Repeating Group

Declared number of instances is the number of repeating group instances, that are defined by the FIX field which identifies a repeating group size ("No<Field>"). Actual number of instances is the number of repeating group instances which actually exist in FIX message, and can be calculated by counting presence of FIX fields (which make up repeating group) in the fields sequence.

By default, FIX Engine strictly follows requirements of the FIX Standard. Thus it requires the actual number of repeating group instances to match declared number of instances. FIX message parsing services report an error by throwing exception, if FIX message doesn't meet the requirements.

FIX Engine exposes configuration parameter Validate.RepeatingGroupEntryCount, which allows to change default behavior. By changing parameter value as shown below, it's possible to have ill-formed FIX messages parsed successfully.

<FixEngine>
  <add key="Validate.RepeatingGroupEntryCount" value="False"/>
</FixEngine>

As soon as parameter is changed, the following behavior will be achieved:

  • FIX messages with ill-formed repeating groups will be parsed successfully.
  • NumberOfInstances will return actual number of repeating group instances if it exceeds declared one.

By default, FIX Engine does not check that each entry of a repeating group starts from a selected field which identifies the beginning of a group new entry.

FIX Engine exposes the configuration parameter Validate.RepeatingGroupLeadingTag, which allows to change default behavior. By changing parameter value as shown below, it's possible to enable more strict FIX message validation.

<FixEngine>
  <add key="Validate.RepeatingGroupLeadingTag" value="True"/>
</FixEngine>

As soon as parameter is changed, the following behavior will be achieved:

  • FIX messages that have repeating group entries, which don't start from a selected field, will not be parsed.
  • EngineException will be thrown for such messages.

We highly do not recommend to set both properties ValidateRepeatingGroupEntryCount and ValidateRepeatingGroupLeadingTag to false. This can lead to data loss during the ill-formed message parsing without any notification about an error.

If you set ValidateRepeatingGroupEntryCount to false, an actual number of group instances may differ from the required number of instances that are represented by a corresponding NumberOfInstances tag. In this case, you can access to this field, as if it was an integer value. This acton gives you a required number of instances of the corresponding group.

Example
C#
// Forms 'Market Data Request' message.

Message request = new Message(
  MsgType.MarketDataRequest, ProtocolVersion.FIX44);

// Sets up regular fields.
request.Set(Tags.MDReqID, "ABSD");
request.Set(Tags.SubscriptionRequestType, 1);
request.Set(Tags.MarketDepth, 1);
request.Set(Tags.MDUpdateType, 1);
request.Set(Tags.AggregatedBook, "N");

// Creates a repeating group NoMDEntryTypes with two instances.
Group groupMDEntryTypes = request.SetGroup(Tags.NoMDEntryTypes, 2);

// Defines fields in the first instance/entry of repeating group.
groupMDEntryTypes.Set(Tags.MDEntryType, 0, "EntryType_0");

// . and the same but for the second instance.
groupMDEntryTypes.Set(Tags.MDEntryType, 1, "EntryType_1");

// Create a repeating group NoRelatedSym with two instances.
// (another way of creating and accessing repeating group).

request.Set(Tags.NoRelatedSym, 2);
Group groupRelatedSym = request.GetGroup(Tags.NoRelatedSym);

groupRelatedSym.Set(Tags.Symbol, 0, "EURUSD_0");
groupRelatedSym.Set(Tags.Symbol, 1, "EURUSD_1");

// Create embedded repeating group which belongs to first entry of 
// groupRelatedSym repeating group
Group groupSecAltID = groupRelatedSym.SetGroup(Tags.NoSecurityAltID, 0, 1);
groupSecAltID.Set(Tags.SecurityAltID, 0, "EURUSD_Alt_0");

request.Validate();

// Get data from group
string symbol1 = groupRelatedSym.Get(Tags.Symbol, 0);
string symbol2 = groupRelatedSym.Get(Tags.Symbol, 1);
string altID = groupSecAltID.Get(Tags.SecurityAltID, 0);

Console.WriteLine(request.ToString());
VB
' Forms Market Data Request message.

Dim request As Message = New Message( _
  MsgType.MarketDataRequest, FIXForge.NET.FIX.ProtocolVersion.FIX44)

' Sets up regular fields.
request.Set(Tags.MDReqID, "ABSD")
request.Set(Tags.SubscriptionRequestType, 1)
request.Set(Tags.MarketDepth, 1)
request.Set(Tags.MDUpdateType, 1)
request.Set(Tags.AggregatedBook, "N")

' Creates a repeating group NoMDEntryTypes with two instances.
Dim groupMDEntryTypes As Group = request.SetGroup(Tags.NoMDEntryTypes, 2)

' Defines fields in the first instance/entry of repeating group.
groupMDEntryTypes.Set(Tags.MDEntryType, 0, "EntryType_0")

' . and the same but for the second instance.
groupMDEntryTypes.Set(Tags.MDEntryType, 1, "EntryType_1")

' Creates a repeating group NoRelatedSym with two instances.
' (another way of creating and accessing repeating group).
request.Set(Tags.NoRelatedSym, 2)
Dim groupRelatedSym As Group = request.GetGroup(Tags.NoRelatedSym)

groupRelatedSym.Set(Tags.Symbol, 0, "EURUSD_0")
groupRelatedSym.Set(Tags.Symbol, 1, "EURUSD_1")

' Creates embedded repeating group which belongs to first entry of 
' groupRelatedSym repeating group
Dim groupSecAltID as Group = groupRelatedSym.SetGroup(Tags.NoSecurityAltID, 0, 1)
groupSecAltID.Set(Tags.SecurityAltID, 0, "EURUSD_Alt_0")

request.Validate()

' Gets data from group
Dim symbol1 As String = groupRelatedSym.Get(Tags.Symbol, 0);
Dim symbol2 As String = groupRelatedSym.Get(Tags.Symbol, 1);
Dim altID As String = groupSecAltID.Get(Tags.SecurityAltID, 0);

Console.WriteLine(request.ToString())
See Also

Other Resources