Flat Group Reader Sample
Source code
using System;
using System.Diagnostics;
using System.IO;
using NLog.Extensions.Logging;
using OnixS.Fix;
using OnixS.Fix.Fix44;
namespace RepeatingGroupFlatMessage
{
static class RepeatingGroupFlatMessage
{
static int Main()
{
try
{
var settings = new EngineSettings()
{
LicenseStore = GetLicenseStoreFolder(),
LoggerProvider = new NLogLoggerProvider()
};
Engine.Init(settings);
FlatMessage marketDataRequest = CreateMarketDataRequestMessage();
Log("Created FIX message in the native (tag=value) format:\n\n" + marketDataRequest);
ProcessMarketDataRequestMessage(marketDataRequest);
FlatMessage order = CreateMessageWithNestedRepeatingGroups();
ProcessMessageWithNestedRepeatingGroups(order);
Engine.Instance.Shutdown();
}
catch (Exception ex)
{
Log("Exception: " + ex);
return 1;
}
finally
{
// From https://github.com/NLog/NLog/wiki/Tutorial:
// NET Application running on Mono / Linux are required to stop threads / timers before entering application shutdown phase.
// Failing to do this will cause unhandled exceptions and segmentation faults, and other unpredictable behavior.
NLog.LogManager.Shutdown(); // Flush and close down internal threads and timers
}
return 0;
}
/// <summary>
/// Creates a Market Data Request (MsgType=V) message.
/// </summary>
static FlatMessage CreateMarketDataRequestMessage()
{
var request = new FlatMessage(ProtocolVersion.Fix44);
// See https://www.onixs.biz/fix-dictionary/4.4/msgType_V_86.html
request.Set(Tag.MsgType, MsgType.MarketDataRequest);
request.Add(Tag.MDReqID, "1")
.Add(Tag.SubscriptionRequestType, SubscriptionRequestType.SnapshotUpdate)
.Add(Tag.MarketDepth, "0")
.Add(Tag.MDUpdateType, MDUpdateType.Full)
// Repeating group
.Add(Tag.NoMDEntryTypes, 3)
.Add(Tag.MDEntryType, MDEntryType.Bid)
.Add(Tag.MDEntryType, MDEntryType.Offer)
.Add(Tag.MDEntryType, MDEntryType.Trade)
// Repeating group
.Add(Tag.NoRelatedSym, 2)
.Add(Tag.Symbol, "EUR/USD")
.Add(Tag.Symbol, "GPS/USD");
return request;
}
static void ProcessMarketDataRequestMessage(FlatMessage request)
{
Debug.Assert(MsgType.MarketDataRequest == request.Type);
Console.WriteLine("\nProcessing:\n" + request.ToString(' ') + "\n");
FlatGroupReader marketDataEntryTypes = new FlatGroupReader(Tag.NoMDEntryTypes);
marketDataEntryTypes.Wrap(request);
int index = 0;
while (marketDataEntryTypes.MoveNext())
{
Log("Market Data Entry # " + index + " : MDEntryType = " + marketDataEntryTypes.Get(Tag.MDEntryType));
index++;
}
}
static FlatMessage CreateMessageWithNestedRepeatingGroups()
{
var order = new FlatMessage(ProtocolVersion.Fix44);
// See https://www.onixs.biz/fix-dictionary/4.4/msgType_D_68.html
order.Set(Tag.MsgType, MsgType.NewOrderSingle);
order.Add(Tag.ClOrdID, "ClOrdID value")
// Repeating group
.Add(Tag.NoPartyIDs, 1)
.Add(Tag.PartyID, "Party ID value")
// Nested repeating group:
.Add(Tag.NoPartySubIDs, 3)
.Add(Tag.PartySubID, "PartySubID value0")
.Add(Tag.PartySubID, "PartySubID value1")
.Add(Tag.PartySubID, "PartySubID value2");
Log("\n\nMessage with a nested repeating group:\n" + order);
return order;
}
static void ProcessMessageWithNestedRepeatingGroups(FlatMessage order)
{
Debug.Assert(MsgType.NewOrderSingle == order.Type);
Log("\nProcessing:\n" + order.ToString(' ') + "\n");
FlatGroupReader partiesGroup = new FlatGroupReader(Tag.NoPartyIDs);
FlatGroupReader partiesSubGroup = new FlatGroupReader(Tag.NoPartySubIDs);
partiesGroup.Wrap(order);
while (partiesGroup.MoveNext())
{
partiesSubGroup.Wrap(partiesGroup);
int nestedIndex = 0;
while (partiesSubGroup.MoveNext())
{
Log("Parties SubGroup # " + nestedIndex + " : PartySubID = " + partiesSubGroup.Get(Tag.PartySubID));
nestedIndex++;
}
}
}
private static string GetLicenseStoreFolder()
{
string path = Path.Join(AppContext.BaseDirectory, "../../../../../license");
if (Directory.Exists(path))
return path;
// expecting it run after dotnet publish using default paths
return Path.Join(AppContext.BaseDirectory, "../../../../../../license");
}
private static void Log(string msg)
{
Console.Out.WriteLine(msg);
}
}
}