Onix Solutions Logo

FIXForge .NET FIX Engine — Programmer’s Guide

Version 2.32.0.0

Introduction

Onix Solutions FIXForge .NET FIX Engine is a .NET class library (assembly) that will FIX-enable applications written in .NET supported languages (C#, Visual Basic (VB.NET), Managed C++, Delphi .NET, etc).

The Engine provides the following services:

High-level architecture of FIX Engine

High-level architecture of FIX Engine - Diagram

System Requirements

.NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0 or .NET Framework 3.5.

Recommended Development Environment

Microsoft Visual Studio .NET 2003, Microsoft Visual Studio 2005 or Microsoft Visual Studio 2008.

Getting Started

All Engine classes are located in the FIXForge.NET.FIX namespace.

The typical way of using the Engine is as follows:

  1. Initialize the Engine.
  2. Create the Session object.
  3. Establish the FIX session as Initiator or Acceptor.
  4. Send and receive application-level FIX messages.
  5. Disconnect the session.
  6. Shutdown the Engine.

Error Reporting

Exception handling is used as a fundamental error-reporting mechanism. In the event of any errors arising then the EngineException is thrown.

Engine Initialization

To initialize the FIX Engine class library the Engine.Init method is used. This method must be called before all other methods.

To shutdown the Engine the Engine.Shutdown method is used. No other Engine methods must be called after this method.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;

try{
	Engine fixEngine = Engine.Init();

	// Session-related logic..

  	fixEngine.Shutdown();
}catch(Exception ex)
	Console.WriteLine("Exception: " + ex);
}
Example in Visual Basic (VB.NET):
Imports  FIXForge.NET.FIX

Try
	Dim fixEngine As Engine = Engine.Init()

	' Session-related logic..

	fixEngine.Shutdown()
Catch ex As Exception
    Console.Out.WriteLine("EXCEPTION")
    Console.Out.WriteLine(ex)
End Try

FIX Version

As the FIX protocol evolves its new versions will be released to you to extend the current functionality.

Supported FIX versions are: FIX 4.0, 4.1, 4.2, 4.3, 4.4 and 5.0. The ProtocolVersion enum is used to identify them.

Example in C# (.NET 2.0):
ProtocolVersion fixVersion = ProtocolVersion.FIX42;
Example in Visual Basic (VB.NET):
Dim fixVersion As ProtocolVersion = ProtocolVersion.FIX42

Each FIX version has its own namespace that contains objects and definitions that are unique for the version, for example:

Example in C# (.NET 2.0):
using FIXForge.NET.FIX.FIX42;

Example in Visual Basic (VB.NET):
Imports FIXForge.NET.FIX.FIX42

FIX Message

The general format of a FIX message is a stream of <tag>=<value> fields with a field delimiter (<SOH>) between fields in the stream (so-called "tag-value FIX format").

Below is an example of a FIX message:

FIX Message example

It is represented with the Message class.

To create a FIX Message object the Message(String type, ProtocolVersion version) constructor is used.

To parse a message in the raw FIX format the Message(String rawMessage) constructor is used.

To validate a message the Message.Validate method is used. This method checks for the presence of required fields.

There are several overloaded methods Message.ToString() to simplify debugging and monitoring.

Example in C# (.NET 2.0):
// Creating a FIX Message object
Message order_1 = new Message("D", ProtocolVersion.FIX40);  // New Order - Single (MsgType = D)

// Parsing a FIX message in the raw FIX format
string rawFixMsg = "8=FIX.4.0\u00019=86\u000135=D\u000149=0\u000156=0\u000134=1\u000152=99990909-17:17:17\
u000111=90001008\u000121=1\u000155=IBM\u000154=1\u000138=10\u000140=1\u000159=0\u000110=191\u0001";

Message order_2 = new Message(rawFixMsg);

order_2.Validate();

Console.WriteLine(order_2.ToString());
Console.WriteLine(order_2.ToString(' '));
Console.WriteLine(order_2.ToString(Message.StringFormat.TAG_NAME | Message.StringFormat.TAG_NUMBER, ' '));
Example in Visual Basic (VB.NET):
' Creating a FIX Message object
Dim order_1 As New Message("D", FIXForge.NET.FIX.ProtocolVersion.FIX40) ' New Order - Single (MsgType = D)

' Parsing a FIX message in the raw FIX format
Dim rawFixMsg As String = "8=FIX.4.0" + ChrW(1) + "9=86" + ChrW(1) + "35=D" + ChrW(1) + "49=0" + ChrW(1) + "56=0" + ChrW(1) + "34=1" + ChrW(1)
 + "52=99990909-17:17:17" + ChrW(1) + "11=90001008" + ChrW(1) + "21=1" + ChrW(1) + "55=IBM" + ChrW(1) + "54=1" + ChrW(1) + "38=10" + ChrW(1) 
+ "40=1" + ChrW(1) + "59=0" + ChrW(1) + "10=191" + ChrW(1)

Dim order_2 As New Message(rawFixMsg)

order_2.Validate()

Console.WriteLine(order_2.ToString())
Console.WriteLine(order_2.ToString(" "))
Console.WriteLine(order_2.ToString(Message.StringFormat.TAG_NAME Or Message.StringFormat.TAG_NUMBER, " ")) 

Fields

To set a field value the Message.Set method is used.

To get a field value the Message.Get method is used.

It is also possible to get or set fields values using Message’s indexer.

Example in C# (.NET 2.0):
string ClOrdID = order[11];
execReport[17] = "Unique identifier of execution message";
Example in Visual Basic (VB.NET):
Dim ClOrdID As String = order.Get(11)

execReport.Set(17, "Unique identifier of execution message")

To remove a field the Message.Remove method is used.

The Tags class contains the constants for the tag values. This class is defined for each FIX version namespace. The use of these constants makes the source code more readable.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.FIX42;

Message order = new Message("D", ProtocolVersion.FIX42); // New Order – Single

order.Set(Tags.ClOrdID, "90001008"); // or order[Tags.ClOrdID]= "90001008"; 
order.Set(Tags.Side, "1");
order.Set(Tags.TimeInForce, "0");
Example in Visual Basic (VB.NET):
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.FIX42

Dim order As New Message("D", FIXForge.NET.FIX.ProtocolVersion.FIX42) ' New Order  Single

order.Set(Tags.ClOrdID, "90001008") ' or order[Tags.ClOrdID]= "90001008";                         
order.Set(Tags.Side, "1")
order.Set(Tags.TimeInForce, "0")

To iterate over all message fields the Message.Fields property is used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.FIX42;

Message msg = new Message("D", ProtocolVersion.FIX42); 

foreach(Field field in msg.Fields){
	Console.WriteLine("Tags=" + field.Tags +", value=" + field.Value);
}
Example in Visual Basic (VB.NET):
Imports  FIXForge.NET.FIX
Imports  FIXForge.NET.FIX.FIX42

Dim msg As New Message("D", ProtocolVersion.FIX42)

Dim field As Field
For Each field In msg.Fields
	Console.WriteLine("Tags=")
	Console.WriteLine(field.Tags)
	Console.WriteLine(", value=")
	Console.WriteLine(field.Value)
Next field

See also: FIX Repeating Group.

FIX Session

A FIX session is defined as a bi-directional stream of ordered messages between two parties within a continuous sequence number series. It is represented by the Session class.

To create a session the Session constructors are used.

To terminate the session the Session.Dispose method is used.

A session has one of two possible roles: Acceptor or Initiator.

Acceptor is the receiving party of the FIX session. It listens for the incoming connection on the pre-defined port. The acceptor has responsibility to perform first level authentication and formally declare the connection request "accepted" through transmission of an acknowledgment Logon message.

Initiator establishes the telecommunications link and initiates the session via transmission of the initial Logon message.

To obtain the current role the Session.Role property is used.

Connection Establishment

To establish the FIX connection as Acceptor the Session.LogonAsAcceptor method is used.

To establish the FIX connection as Initiator the Session.LogonAsInitiator method is used.

To disconnect the session the Session.Logout method is used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX; 
using FIXForge.NET.FIX.FIX42;

const string senderCompID = "SenderCompID"; const string targetCompID = "TargetCompID"; const ProtocolVersion version = ProtocolVersion.FIX42; const string TARGET_HOST = "localhost"; const int TARGET_PORT = Engine.Instance.Settings.ListenPort; // Target port is equal to acceptor's port to create a loopback FIX session.
Session acceptor = new Session(senderCompID, targetCompID, version); Session initiator = new Session(targetCompID, senderCompID, version);
acceptor.LogonAsAcceptor();
initiator.LogonAsInitiator(TARGET_HOST, TARGET_PORT); // Sends the Logon message and waits for the acknowledgment Logon
// Message exchange and processing..
acceptor.Logout(); // Sends the Logout message and waits for the confirming Logout initiator.Logout();
acceptor.Dispose(); // Free resources initiator.Dispose(); // Free resources
Example in Visual Basic (VB.NET):
Imports  FIXForge.NET.FIX
Imports  FIXForge.NET.FIX.FIX42

Dim senderCompID As String = "SenderCompID"
Dim targetCompID As String = "TargetCompID"

Dim fixVersion As FIXForge.NET.FIX.ProtocolVersion = FIXForge.NET.FIX.ProtocolVersion.FIX42
Dim TARGET_HOSTAs String = "localhost"
Dim TARGET_PORT As Integer = Engine.Instance.Settings.ListenPort  ' Target port is equal to acceptor's port to create a loopback FIX session.

Dim acceptor As New Session(senderCompID, targetCompID, fixVersion)
Dim initiator As New Session(targetCompID, senderCompID, fixVersion)

acceptor.LogonAsAcceptor()
initiator.LogonAsInitiator(TARGET_HOST, TARGET_PORT) ' Sends the Logon message and waits for the acknowledgment Logon

' Message exchange and processing.. 

acceptor.Logout() ' Sends the Logout message and waits for the confirming Logout
initiator.Logout()

acceptor.Dispose() ' Free resources
initiator.Dispose() ' Free resources

See also:  Session state, Custom Logon Message, Sequence Numbers.

Message Exchange

To send a message to counterparty the Session.Send method is used. This method is asynchronous. As soon as a session is created it is possible to start sending messages via the session. If the session is not established, the messages will be sent when the connection is established with the counterparty.

To receive incoming application-level messages it is necessary to register for the Session.InboundApplicationMsgEvent event.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.FIX42;

class SessionListener
{
 	public void OnInboundApplicationMsg(Object sender, Session.InboundApplicationMsgEventArgs e)
	{
		Console.WriteLine("Incoming application-level message: " + e.Msg);
		// processing of the application-level incoming message..
	}
}

const string senderCompID = "Acceptor";
const string targetCompID = "Initiator";
const ProtocolVersion version = ProtocolVersion.FIX42;
const string host = "localhost";
Engine engine = Engine.Init();

Session acceptor = new Session(senderCompID, targetCompID, version);
acceptor.LogonAsAcceptor();

Session initiator = new Session(targetCompID, senderCompID, version);
initiator.LogonAsInitiator(host, Engine.Instance.Settings.ListenPort);

SessionListener listener = new SessionListener();
initiator.InboundApplicationMsgEvent += new Session.InboundApplicationMsgEventHandler(listener.OnInboundApplicationMsg);

Message order = new Message(MsgType.Order_Single, version); 

order.Set(Tags.ClOrdID, "Unique identifier for Order as assigned by the buy-side");
order.Set(Tags.HandlInst, "1");
order.Set(Tags.Symbol, "Ticker symbol");
order.Set(Tags.Side, "1");
order.Set(Tags.TransactTime, DateTime.UtcNow.ToString("yyyyMMdd-HH:mm:ss"));
order.Set(Tags.OrdType, "1");

order.Validate();

acceptor.Send(order);

// continue the message exchange..

acceptor.Logout();

acceptor.Dispose();
initiator.Dispose();

engine.Shutdown();
Example in Visual Basic (VB.NET):
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.FIX42

Class SessionListener
Public Sub OnInboundApplicationMsg(ByVal sender As Object, ByVal args As Session.InboundApplicationMsgEventArgs)
Console.WriteLine("Incoming application-level message: ")
Console.WriteLine(args.Msg)
' processing of the application-level incoming message..
End Sub
End Class Dim senderCompID As String = "Acceptor" Dim targetCompID As String = "Initiator" Dim fixVersion As FIXForge.NET.FIX.ProtocolVersion = FIXForge.NET.FIX.ProtocolVersion.FIX42 Dim host As String = "localhost" Dim fixEngine As Engine = Engine.Init() Dim acceptor As Session = New Session(senderCompID, targetCompID, fixVersion) acceptor.LogonAsAcceptor() Dim initiator As Session = New Session(targetCompID, senderCompID, fixVersion) initiator.LogonAsInitiator(host, Engine.Instance.Settings.ListenPort) Dim listener As SessionListener = New SessionListener() AddHandler session.InboundApplicationMsgEvent, AddressOf listener.OnInboundApplicationMsg Dim order As Message = New Message("D", fixVersion) order.Set(Tags.ClOrdID, "Unique identifier for Order as assigned by the buy-side") order.Set(Tags.HandlInst, "1") order.Set(Tags.Symbol, "Ticker symbol") order.Set(Tags.Side, "1") order.Set(Tags.TransactTime, DateTime.UtcNow.ToString("yyyyMMdd-HH:mm:ss")) order.Set(Tags.OrdType, "1") order.Validate() acceptor.Send(order) 'continue the message exchange.. acceptor.Logout() acceptor.Dispose() initiator.Dispose() fixEngine.Shutdown()

Sequence Numbers

All FIX messages are identified by a unique sequence number (the MsgSeqNum field).

Sequence numbers are initialized at the start of each FIX session starting at 1 (one) and increment throughout the session.  Each session establishes an independent incoming and outgoing sequence series.

A single FIX session can exist across multiple sequential (not concurrent) physical connections.  Parties can connect and disconnect multiple times while maintaining a single FIX session.  In other words, FIX Session is comprised of one or more FIX Connections.

Resetting the inbound and outbound sequence numbers back to 1, for whatever reason, constitutes the beginning of a new FIX session.

Method Session.ResetSequenceNumbers could be used to backup the previous log files and reset the sequence numbers to 1.

Monitoring sequence numbers enables parties to gracefully synchronize applications when reconnecting during a FIX session. 

To get or set the expected sequence number of the next incoming message the Session.InSeqNum property is used.

To get or set the sequence number of the next outgoing message the Session.OutSeqNum property is used.

Note: It is NOT recommended to use Session.InSeqNum and Session.OutSeqNum properties to reset session sequence numbers to 1. Method Session.ResetSequenceNumbers should be used instead.

To disconnect the FIX Connection while maintaining a single FIX Session the Session.Logout method is used. It is possible to continue the session later using the Session.LogonAsAcceptor or Session.LogonAsInitiator methods again.

To terminate a FIX Session the Session.Dispose() method is used.

The FIX Engine automatically synchronizes sequence numbers when reconnecting during a FIX session on the base of the information previously stored in log files.

To synchronize sequence numbers manually Session.InSeqNum and Session.OutSeqNum properties are used (before Session.LogonAsAcceptor() or Session.LogonAsInitiator() method calls).

Sequence numbers diagram

Some implementations of FIX protocol (FIX Dialects) expect that the FIX Session coincides with FIX Connection, in other words that the sequence numbers are reset back to 1 after the Logout messages exchange.

To interact with such FIX dialects, the keepSequenceNumbersAfterLogout parameter of Session constructor should be set to false. In this case after Session.Dispose() method sequence numbers are set back to 1. Next time when the Session object is created incoming and outgoing sequence numbers will start from 1 (in other words, a new FIX Session will be created).

See also: Sequence Number Reset, Sequence Number Reset via ResetSeqNumFlag field.

Administration

License File

By default the license file (FIXForge.NET.FIX.Engine.lic) must be placed in the same directory as the FIX Engine assembly (FIXForge.NET.FIX.Engine-net-1.1.dll or FIXForge.NET.FIX.Engine-net-2.0.dll).

It is possible to specify the path to the license file using either LicenseFile configuration setting or EngineSettings.LicenseFile property.

License Expiration Date

The license expiration date is available via Engine.LicenseExpirationDate property.

Persistent Message Storage and FIX Log Files

The MsgStorage folder is created for storing log data. Incoming and outgoing messages, session’s state data and the FIX Engine log file (FixEngineLog.txt) are stored in this folder.

Unless the storageType parameter of Session’s constructor is set to SessionStorageType.MemoryBasedStorage a file-based session storage is used.

For each FIX session with a file-based session storage the following files are created:

SESSION_NAME is formed on the base of SenderCompID, TargetCompID, session's FIX version and a timestamp. During the run-time is it available via Session.StorageID property.

When the Session object with a file-based session storage is created anew after Engine's restart, FIX Session's state (the sequence numbers of last received and sent messages, previously sent messages, etc) is restored from these files.

To start a FIX session as a new one (so called "clean start"), it is necessary to remove the session files from the previous runs.

Connecting parties must bi-laterally agree as to when sessions are to be started/stopped and log files are backed up based upon individual system and time zone requirements.

When the FIX session is finished, the session files are not needed anymore. They can be backed up and later a new FIX session with the same SenderCompID and TargetCompID will start sequence numbers from 1. The usual practice is to backup the log files at the end of each business day (so called "End Of Day procedure") to start the sequence numbers from 1 at the beginning of the next day.

To reset the sequence numbers to 1 and backup the log files the Session.ResetSequenceNumbers method can be used. This method can be called only when the session is disconnected.

See also: Memory Based Session Storage, Log.Directory, Log.FlushFileAfterEachMessage, Sequence Numbers, FIX Analyser.

Settings

The default values of FIX Engine settings can be changed using the <FixEngine> configuration section of the standard .NET Framework application-level configuration file (App.config at design time or YourApplicationName.exe.config at run-time) or using the EngineSettings parameter of the Engine.Init method.

Example:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

	<configSections>
		<section name="FixEngine" type="System.Configuration.NameValueSectionHandler"/>
	</configSections>

	<FixEngine>
		<add key="Dialect" value="LavaDialect.xml"/> 
		<add key="ListenPort" value="4500"/>

		<add key="Reconnect.Attempts" value="3"/>
		<add key="Reconnect.Interval" value="30"/>

		<add key="Validate.NumberOfRepeatingGroupInstances" value="false"/> 
		<add key="Validate.RequiredFields" value="true"/>
		<add key="Validate.UnknownFields" value="true"/>
		<add key="Validate.UnknownMessages" value="true"/>
	</FixEngine> 

</configuration>

Example in C# (.NET 2.0):
  EngineSettings settings = new EngineSettings();
  
  settings.LogDirectory = "LogDirectoryValue";

  Engine.Init(settings);
  
Example in Visual Basic (VB.NET):
Dim settings As EngineSettings = New EngineSettings()

settings.LogDirectory = "LogDirectoryValue"

Engine.Init(settings)
FIX Engine configuration settings
Setting Description Default value
Connection.ReceiveBufferSize The size of the buffer allocated to FIX connection for receiving data. 65535
Connection.SendBufferSize The size of the buffer allocated to FIX connection for sending data. 65535
Connection.TcpNoDelayOption.SetForAcceptors

Option to improve latency at the expense of message throughput.

true
Connection.TcpNoDelayOption.SetForInitiators

Option to improve latency at the expense of message throughput.

true
Reconnect.Attempts Number of attempts to restore the telecommunication link. 3
Reconnect.Interval The time interval between the attempts to restore the telecommunication link (in seconds). 180
Dialect Specify the description of the FIX dialect. Empty
LicenseFile Path to the license file.

See also: EngineSettings.LicenseFile.
FIXForge.NET.FIX.Engine.lic
ListenPort

FIX Engine listens on this port for incoming connections.

If it is set to '0' then only session-initiators can be created.
If '-1' then the telecommunication level is disabled and only message parsing/assembling can be used.

Use comma delimited list if more than one listen port is used.

0
Log.Directory Inbound and outbound messages session's state data and the FIX Engine log file (FixEngine.log) are stored in this directory. MsgStorage
Log.InboundMessages Option to log inbound messages. See also: Session.LogInboundMessages. True
ProcessDeliverToCompID Option to automatically process the DeliverToCompID (128) field. False
Resending.QueueSize Number of sent messages that are available for resending on counterparty's Resend Request <2> message. 1000
SSL.CertificateFile The path to the SSL certificate file in (Privacy Enhanced Mail) Base64 encoded (.pem) format.
See also: SSL Encryption
Empty
SSL.ListenPort FIX Engine listens on this port for incoming SSL connections.
 If it is set to '0' then only SSL-based session-initiators can be created.
 If '-1' then the SSL encryption is disabled.
See also: SSL Encryption
0
SSL.PrivateKeyFile The path to the SSL private key file in (Privacy Enhanced Mail) Base64 encoded (.pem) format.
See also: SSL Encryption
Empty
SSL.PrivateKeyPassword The password to load private keys that are protected by a password. Empty
SSL.VerifyPeer Option to request client certificates and perform the certificate verification. False
Validate.NumberOfRepeatingGroupInstances Option to validate that the declared number of repeating group instances is equal to the actual one. True
Validate.RequiredFields Option to validate the presence of required fields in inbound and outbound messages. False
Validate.UnknownFields Option to validate the presence of unknown fields (fields that do not belong to the message in accordance with the FIX protocol or its dialect). False
Validate.UnknownMessages Option to validate the presence of unknown FIX messages (messages that do not belong to the message in accordance with the FIX protocol or its dialect). False

Advanced

FIX Repeating Group

It is permissible for fields to be repeated in the same message within a repeating group (e.g. "215=2<SOH>216=2<SOH>217=Dest_1<SOH>216=4<SOH>217=Dest_2<SOH>" represents a repeating group with two repeating instances "delimited" by tag 216 (first field in the repeating group.).

The NoRoutingIDs<215> field specifies the number of repeating group instances (2 in this case). This is so called "NumberOfInstances field". The NumberOfInstances field must immediately precede the repeating group contents (repeating group instances).

Repeating Group

The FIX repeating group is represented with the Group class.

To get the Group object that represents the existing repeating group of the message the Message.GetGroup(int numberOfInstancesTag) method is used.

To create a new repeating group or modify the number of instances in the existing one the Message.SetGroup(int numberOfInstancesTag, int numberOfInstances) method is used.

To remove a repeating group method Message.Remove(int numberOfInstancesTag) is used.

The Group class works with fields and embedded repeating groups in the same manner as the Message class, but each method has an additional parameter that defines the index of the repeating group instance (starting from 0).

Example in C# (.NET 2.0):
Message request = new Message("V", ProtocolVersion.FIX42); // Market Data Request

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

// create a repeating group NoMDEntryTypes with two instances
Group groupMDEntryTypes = request.SetGroup(Tags.NoMDEntryTypes, 2);
groupMDEntryTypes.Set(Tags.MDEntryType, 0, "EntryType_0"); // first instance
groupMDEntryTypes.Set(Tags.MDEntryType, 1, "EntryType_1"); // second instance

// create a repeating group NoRelatedSym with two instances
Group groupRelatedSym = request.SetGroup(Tags.NoRelatedSym, 2);
groupRelatedSym.Set(Tags.Symbol, 0, "EURUSD_0"); // first instance
groupRelatedSym.Set(Tags.Symbol, 1, "EURUSD_1"); // second instance 

request.Validate();

Console.WriteLine(request.ToString());
Example in Visual Basic (VB.NET):
Dim request As Message = New Message("V", FIXForge.NET.FIX.ProtocolVersion.FIX42) ' Market Data Request

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

' create a repeating group NoMDEntryTypes with two instances
Dim groupMDEntryTypes As Group = request.SetGroup(Tags.NoMDEntryTypes, 2)
groupMDEntryTypes.Set(Tags.MDEntryType, 0, "EntryType_0") ' first instance
groupMDEntryTypes.Set(Tags.MDEntryType, 1, "EntryType_1") ' second instance

' create a repeating group NoRelatedSym with two instances
Dim groupRelatedSym As Group = request.SetGroup(Tags.NoRelatedSym, 2)
groupRelatedSym.Set(Tags.Symbol, 0, "EURUSD_0") ' first instance
groupRelatedSym.Set(Tags.Symbol, 1, "EURUSD_1") ' second instance 

request.Validate()

Console.WriteLine(request.ToString())

See also: FIX Dialects.

Session States

To obtain the current session state the Session.State property is used.

The states of the FIX session are listed below.

FIX Session states
State Description
Role == Acceptor Role == Initiator
DISCONNECTED The session is disconnected.
LOGON_IN_PROGRESS The session is waiting for the initial Logon message. The initial Logon message was sent and the session is waiting for the acknowledgment Logon message.
ACTIVE The session is fully established (after the successful Logon exchange).
RECONNECTING N/A (only session-initiator can be in this state). Session-initiator is trying to restore the telecommunication link.
LOGOUT_IN_PROGRESS The initial Logout message was sent and the session is waiting for the acknowledgment Logout message.

To be notified about the changes in the session state register for the Session.StateChangeEvent event.

Example in C# (.NET 2.0):
void OnStateChange(Object sender, Session.StateChangeEventArgs e)
{
	Console.WriteLine("New session state: " + e.NewState);
} 
void run()
{
	Engine.Init();
	Session session = new Session("SenderCompID", "TargetCompID", ProtocolVersion.FIX42);
	session.StateChangeEvent += new Session.StateChangeEventHandler(OnStateChange);
	// ...
}
Example in Visual Basic (VB.NET):
Sub OnStateChange(ByVal sender As Object, ByVal e As Session.StateChangeEventArgs)
	Console.WriteLine("New session state: ")
	Console.WriteLine(e.NewState)
End Sub

Sub Run()
	Engine.Init()
	Dim session As New Session("SenderCompID", "TargetCompID", FIXForge.NET.FIX.ProtocolVersion.FIX42)
	AddHandler session.StateChangeEvent, AddressOf OnStateChange
End Sub

Session Events

The events of the Session class are listed below.

Session events
Event Description
StateChangeEvent Session state is changed.
ErrorEvent Error condition is detected.
InboundApplicationMsgEvent Application-level message is received from the counterparty.
InboundSessionMsgEvent Session-level message is received from the counterparty.
OutboundApplicationMsgEvent Application-level message will be sent to the counterparty.
OutboundSessionMsgEvent Session-level message will be sent to the counterparty.
MessageResending Sent application-level message is about to be resent to the counterparty.
WarningEvent Warning condition is detected.

Note: It is important not perform time-consuming tasks inside event handlers.

Example in C# (.NET 2.0):
void OnStateChange(object sender, Session.StateChangeEventArgs e) 
{ 
 	Console.WriteLine("New session state: " + e.NewState); 
}

void OnInboundApplicationMsg(object sender, Session.InboundApplicationMsgEventArgs e) 
{ 
	Console.WriteLine("Incoming application-level message: " + e.Msg); 
} 

void OnInboundSessionMsg(object sender, Session.InboundSessionMsgEventArgs e) 
{ 
	Console.WriteLine("Incoming session-level message: " + e.Msg); 
} 

void OnOutboundApplicationMsg(object sender, Session.OutboundApplicationMsgEventArgs e) 
{ 
	Console.WriteLine("Outgoing application-level message: " + e.Msg); 
} 

void OnOutboundSessionMsg(object sender, Session.OutboundSessionMsgEventArgs e) 
{ 
	Console.WriteLine("Outbound session-level message: " + e.Msg); 
} 

void OnMessageResending(object sender, Session.MessageResendingEventArgs e)
{				
	Console.WriteLine("OnMessageResending: " + e.Msg);				
	e.AllowResending = false;
}

void OnSessionWarning(object sender, Session.WarningEventArgs e) 
{ 
	Console.WriteLine("Session warning: " + e.Reason); 
} 

void OnSessionError(object sender, Session.ErrorEventArgs e) 
{ 
	Console.WriteLine("Session error: " + e.Reason); 
} 

void run()
{ 
	Session session = new Session("SenderCompID", "TargetCompID", ProtocolVersion.FIX44);  

	session.StateChangeEvent += new Session.StateChangeEventHandler(OnStateChange); 
	session.InboundSessionMsgEvent += new Session.InboundSessionMsgEventHandler(OnInboundSessionMsg); 
	session.InboundApplicationMsgEvent += new Session.InboundApplicationMsgEventHandler(OnInboundApplicationMsg); 
	session.OutboundSessionMsgEvent += new Session.OutboundSessionMsgEventHandler(OnOutboundSessionMsg); 
	session.OutboundApplicationMsgEvent += new Session.OutboundApplicationMsgEventHandler(OnOutboundApplicationMsg); 
	session.MessageResending += new Session.MessageResendingEventHandler(OnResendRequest); 
	session.WarningEvent += new Session.WarningEventHandler(OnSessionWarning); 
	session.ErrorEvent += new Session.ErrorEventHandler(OnSessionError); 
    
	// ... 
}
Example in Visual Basic (VB.NET):
Sub OnStateChange(ByVal sender As Object, ByVal e As Session.StateChangeEventArgs)
	Console.WriteLine("New session state: " + e.NewState.ToString())            
End Sub
    
Sub OnInboundApplicationMsg(ByVal sender As Object, ByVal e As Session.InboundApplicationMsgEventArgs)
	Console.WriteLine("Incoming application-level message: " + e.Msg.ToString())
End Sub

Sub OnInboundSessionMsg(ByVal sender As Object, ByVal e As Session.InboundSessionMsgEventArgs)
	Console.WriteLine("Incoming session-level message: " + e.Msg.ToString())
End Sub

Sub OnOutboundApplicationMsg(ByVal sender As Object, ByVal e As Session.OutboundApplicationMsgEventArgs)
	Console.WriteLine("Outgoing application-level message: " + e.Msg.ToString())
End Sub

Sub OnOutboundSessionMsg(ByVal sender As Object, ByVal e As Session.OutboundSessionMsgEventArgs)
	Console.WriteLine("Outbound session-level message: " + e.Msg.ToString())
End Sub

Sub OnMessageResending(ByVal sender As Object, ByVal e As Session.ResendRequestEventArgs, ByRef allowResend As System.ValueType)
	Console.WriteLine("OnMessageResending: " + e.Msg.ToString())
	e.AllowResending = False
End Sub

Sub OnSessionWarning(ByVal sender As Object, ByVal e As Session.WarningEventArgs)
	Console.WriteLine("Session warning: " + e.Reason.ToString())
End Sub

Sub OnSessionError(ByVal sender As [Object], ByVal e As Session.ErrorEventArgs)
	Console.WriteLine("Session error: " + e.Reason.ToString())             
End Sub

Sub MainRun()
	Engine.Init()

	Dim session As New Session("SenderCompID", "TargetCompID", FIXForge.NET.FIX.ProtocolVersion.FIX42)

	AddHandler session.StateChangeEvent, AddressOf OnStateChange
	AddHandler session.InboundSessionMsgEvent, AddressOf OnInboundSessionMsg
	AddHandler session.InboundApplicationMsgEvent, AddressOf OnInboundApplicationMsg
	AddHandler session.OutboundSessionMsgEvent, AddressOf OnOutboundSessionMsg
	AddHandler session.OutboundApplicationMsgEvent, AddressOf OnOutboundApplicationMsg
	AddHandler session.MessageResending, AddressOf OnMessageResending
	AddHandler session.WarningEvent, AddressOf OnSessionWarning
	AddHandler session.ErrorEvent, AddressOf OnSessionError
End Sub

Accepting FIX Session without the prior creation of the Session object

Sometimes it is required to accept an incoming FIX session 'on the fly', without the prior creation of the Session object and connecting it as TargetCompID of the incoming session is not known in advance). To perform this task, subscribe to Engine.UnknownIncomingConnection event.

An automatically created Session object that corresponds to the incoming FIX connection is available via the CreatedSession property of the UnknownIncomingConnectionEventArgs object passed to your event handler.

To accept the incoming connection, set the Accept property of the UnknownIncomingConnectionEventArgs object to true. Otherwise the incoming connection will be rejected and the created Session object will be disposed by the FIX Engine.

Example in C# (.NET 1.1, .NET 2.0, .NET 3.0, .NET 3.5):
void run()
{ 
 Engine.Init();
 Engine.Instance.UnknownIncomingConnection += new Engine.UnknownIncomingConnectionEventHandler(OnUnknownIncomingConnection); 
 // ...
}

void OnUnknownIncomingConnection(Object sender, Engine.UnknownIncomingConnectionEventArgs e)
{ 
 Console.WriteLine("Unknown incoming session: " + e.Session); 
 e.Accept = true; // Otherwise the connection will be rejected!
}

Updating GUI Controls on Session event

Session events are fired from the FIX Engine thread of execution. In order to safely update GUI Controls it is necessary to use Control.BeginInvoke, otherwise the application could hang.

Example in C# (.NET 2.0):
delegate void UpdateSessionStateDelegate(string state); 

void UpdateSessionState(string state)
{ 
	statusBar.Panels[0].Text = state; 
} 
void OnStateChange(Object sender, Session.StateChangeEventArgs e) 
{ 
	statusBar.BeginInvoke(new UpdateSessionStateDelegate(UpdateSessionState), new object[] {e.NewState.ToString()}); 
} 
Example in Visual Basic (VB.NET):
Dim formStatusBar As StatusBar = New StatusBar

Delegate Sub UpdateSessionStateDelegate(ByVal state As String)

Sub UpdateSessionState(ByVal state As String)            
	formStatusBar.Panels.Item(0).Text = state
End Sub


Sub OnStateChange(ByVal sender As Object, ByVal e As Session.StateChangeEventArgs)
	formStatusBar.BeginInvoke(New UpdateSessionStateDelegate(AddressOf Me.UpdateSessionState), New Object() {e.NewState.ToString()})
End Sub

Custom Logon Message

Sometime there is need to set additional fields (e.g. Username <553>, Password <554>) in the initiation Logon message. In this case the Session.LogonAsInitiator(string host, int port, int heartBtInt, Message customLogonMsg) method must be used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.FIX43;

const string senderCompID = "CustomLogonMessage_SND";
const string targetCompID = "CustomLogonMessage_TRG";
const ProtocolVersion version = ProtocolVersion.FIX43;
const int HBI = 30;
const string USERNAME = "USER_NAME";
const string PASSWORD = "PASSWORD";

Session acceptor = new Session(senderCompID, targetCompID, version);
acceptor.LogonAsAcceptor();

Session initiator = new Session(targetCompID, senderCompID, version);

Message customLogonMsg = new Message("A", FIXForge.NET.FIX.ProtocolVersion.FIX43);
customLogonMsg[Tags.Username] = USERNAME;
customLogonMsg[Tags.Password] = PASSWORD;

initiator.LogonAsInitiator("localhost", Engine.Instance.Settings.ListenPort, HBI, customLogonMsg);

// message exchange and processing..

acceptor.Logout();
initiator.Logout();

acceptor.Dispose();
initiator.Dispose();
Example in Visual Basic (VB.NET):
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.FIX43

Dim senderCompID As String = "CustomLogonMessage_SND"
Dim targetCompID As String = "CustomLogonMessage_TRG"
Dim fixVersion As FIXForge.NET.FIX.ProtocolVersion = FIXForge.NET.FIX.ProtocolVersion.FIX43
Dim HBI = 30
Dim USERNAME As String = "USER_NAME"
Dim PASSWORD As String = "PASSWORD"

Dim acceptor As New Session(senderCompID, targetCompID, fixVersion)
acceptor.LogonAsAcceptor()

Dim initiator As New Session(targetCompID, senderCompID, fixVersion)

Dim customLogonMsg As New Message("A", FIXForge.NET.FIX.ProtocolVersion.FIX43)
customLogonMsg.Set(Tags.Username, USERNAME)
customLogonMsg.Set(Tags.Password, PASSWORD)

initiator.LogonAsInitiator("localhost", Engine.Instance.Settings.ListenPort, HBI, customLogonMsg)

' message exchange and processing..

acceptor.Logout()
initiator.Logout()

acceptor.Dispose()
initiator.Dispose()

Sequence Number Reset

Method Session.ResetSequenceNumbers is used to reset the sequence numbers to 1 and backup the previous log files. This method can be called only when the session is disconnected.

See also: Sequence Numbers.

Sequence Number Reset via ResetSeqNumFlag field

ResetSeqNumFlag (141) field in the Logon (A) message indicates that the both sides of the FIX session should reset sequence numbers.

To send a Logon message with this field during FIX Connection establishment, use the setResetSeqNumFlag parameter of the Session.LogonAsInitiator(string host, int port, bool setResetSeqNumFlag) method.

It is also possible to send a Logon message with the ResetSeqNumFlag set when the FIX Session is established (e.g. to maintain 24 hour connectivity) using Session.ResetSeqNumViaLogonExchange method.

FIX Dialects

It is not uncommon for firms to implement slightly different interpretations of the FIX protocol (FIX dialects).

Due to the design of the FIX protocol such deviations from the FIX specification should be described to the FIX Engine, otherwise it will not be able to parse or create the corresponding FIX messages correctly.

The Dialect configuration setting specifies the path to the description of FIX dialects in XML file. This description must confirm to the Dialect.xsd XML Schema.

Ready to use FIX dialect description files as well as exchange-specific trading and market data client samples are available for many FIX destinations (Hotspot, Currenex, CME, EFX, etc) upon request.

To add a new user-defined field to a FIX Message add the corresponding <Field> entity to the FIX Dialect description file.

For example:

<?xml version="1.0" encoding="utf-8"?>
<Dialect xmlns="http://tempuri.org/Dialect.xsd" name="DialectID">

<FIX version="4.0">
	<Message type="D">
		<Field tag="526" name="SecondaryClOrdID"/> <!-- Does not belong to Standard FIX 4.0 --> 
	</Message> 
</FIX>

</Dialect>

To add a new user-defined repeating group to a FIX Message add the corresponding <Group> entity to the FIX Dialect description file.

For example:

<?xml version="1.0" encoding="utf-8"?>
<Dialect xmlns="http://tempuri.org/Dialect.xsd" name="DialectID">

<FIX version="4.0">
	<Message type="D">
		<Group numberOfInstancesTag="78" name="NoAllocs"> <!-- Number of repeating groups for pre-trade allocation, does not belong to Standard FIX 4.0 -->
			<Field tag="79" name="AllocAccount"/> <!--  Does not belong to Standard FIX 4.0 --> 
			<Field tag="661" name="AllocAcctIDSource"/> <!--  Does not belong to Standard FIX 4.0 --> 
			<Field tag="736" name="AllocSettlCurrency"/> <!--  Does not belong to Standard FIX 4.0 --> 
			<!-- Other group fields -->
		</Group>
	</Message> 
</FIX>
  
</Dialect>

To make a field, which is required according to the FIX Protocol specification, optional, and visa-versa, add the corresponding <Field> entity to the FIX Dialect description and set the isRequired attribute accordingly.

For example:

<?xml version="1.0" encoding="utf-8"?>
<Dialect xmlns="http://tempuri.org/Dialect.xsd" name="DialectID">


<FIX version="4.0">
	<Message type="D">
		<Field tag="21" isRequired="false" name="HandlInst"/> <!-- Required in Standard FIX 4.0, but optional in this FIX dialect --> 
		<Field tag="109" isRequired="true" name="ClientID"/> <!-- Optional in Standard FIX 4.0, but required in this FIX dialect --> 
	</Message> 
</FIX>

</Dialect>

To define a User Defined Message add the corresponding <Message> entity to the FIX Dialect description.

For example:

<?xml version="1.0" encoding="utf-8"?>
<Dialect xmlns="http://tempuri.org/Dialect.xsd" name="DialectID">


<FIX version="4.0">
	<Message type="UserDefinedMessage_1">
		<Field tag="100"/> 
		<Field tag="101"/> 
	</Message> 
</FIX>

</Dialect>

Such a user-defined message can be used exactly the same way as the standard FIX Message:

Example in C# (.NET 2.0):
Message userDefinedMsg = new Message("UserDefinedMessage_1", ProtocolVersion.FIX40);

userDefinedMsg.Set(100, "Field 100");
userDefinedMsg.Set(101, "Field 101");
userDefinedMsg.Validate();

Console.WriteLine("UDM: " + userDefinedMsg);
Example in Visual Basic (VB.NET):
Dim userDefinedMsg As New Message("UserDefinedMessage_1", FIXForge.NET.FIX.ProtocolVersion.FIX42)

userDefinedMsg.Set(100, "Field 100")
userDefinedMsg.Set(101, "Field 101")

userDefinedMsg.Validate()
Console.WriteLine("UDM: " + userDefinedMsg.ToString())

Example of a FIX Dialect description file:

<?xml version="1.0" encoding="utf-8"?>
<Dialect xmlns="http://tempuri.org/Dialect.xsd" name="Lava">

<FIX version="4.2"> 
	<Message type="N">		
		<Group numberOfInstancesTag="73" name="RefAllocID">
			<!-- An additional field in the existing repeating group -->
			<Field tag="37" name="OrderID"/>			
		</Group>
	</Message>
</FIX>
    
<FIX version="4.3">
	<Message type="y">
		<Group numberOfInstancesTag="146" name="NoRelatedSym">
			<!-- An additional field in the existing repeating group -->
			<Field tag="64" isRequired="true" name="FutSettDate"/>
		</Group>
	</Message>
        
	<Message type="W">
		<Group numberOfInstancesTag="268" name="NoMDEntries">
			<!-- An additional field in the existing repeating group -->
			<Field tag="278" name="MDEntryID"/>
		</Group>
		<Field tag="64" name="FutSettDate"/>
	</Message>
  
	<Message type="X">
		<!-- An additional field -->
		<Field tag="55" name="Symbol"/>

		<!-- An additional field -->
		<Field tag="64" name="FutSettDate"/>
	</Message>
</FIX>
</Dialect>

See also: the Dialect configuration setting.

Dictionary namespace

The Dictionary namespace contains information about the structure of FIX versions (dialects), messages and fields.

To get the field name by the given tag number the Dialect.TagNameByNumber method is used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.Dictionary;

Dialect dialect = new Dialect(ProtocolVersion.FIX42);
string name = dialect.TagNameByNumber(34);
Example in Visual Basic (VB.NET):
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.Dictionary

Dim dialectInstance As New Dialect(FIXForge.NET.FIX.ProtocolVersion.FIX42)
Dim name As String = dialectInstance.TagNameByNumber(34)

To get the collection of valid field values the Dialect.GetValidFieldValues method is used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.Dictionary;

Dialect dialect = new Dialect(ProtocolVersion.FIX42);

ValidFieldValue[] values = dialect.GetValidFieldValues(54);

foreach(ValidFieldValue vfv in values){
	Console.WriteLine(vfv.Value + " = " + vfv.Description);
}
Example in Visual Basic (VB.NET):
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.Dictionary

Dim dialectInstance As New Dialect(FIXForge.NET.FIX.ProtocolVersion.FIX42)
Dim values As ValidFieldValue() = dialectInstance.GetValidFieldValues(54)
    
Dim vfv As ValidFieldValue
For Each vfv In values
	Console.WriteLine(vfv.Value + " = " + vfv.Description)
Next vfv

To traverse the message structure the Dialect.GetMessageFields method is used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.Dictionary;

Dialect dialect = new Dialect(ProtocolVersion.FIX42);

void TraverseChildFields(FieldInfo[] childFields, int shift)
{
	if(0 == childFields.Length){
		return;
	}
	String spaces = new String(' ', shift);
	foreach(FieldInfo fInfo in childFields){
		Console.WriteLine(spaces + fInfo.Tags + ", " + fInfo.IsRequired);
		TraverseChildFields(fInfo.ChildFields, shift*2);
	}
}

public void GetMessageFields()
{
	FieldInfo[] fields = dialect.GetMessageFields("i");

	foreach (FieldInfo fInfo in fields)
	{
		Console.WriteLine(fInfo.Tags + ", " + fInfo.IsRequired);
		TraverseChildFields(fInfo.ChildFields, 3);
	}
}		
Example in Visual Basic (VB.NET):
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.Dictionary

Dim dialectInstance As New Dialect(FIXForge.NET.FIX.ProtocolVersion.FIX42)

Sub TraverseChildFields(ByVal childFields() As FieldInfo, ByVal shift As Integer)
            If 0 = childFields.Length Then
                Return
            End If
            Dim spaces As New String(" "c, shift)
            Dim fInfo As FieldInfo
            For Each fInfo In childFields
                Console.WriteLine(spaces + fInfo.Tags + ", " + fInfo.IsRequired)

                TraverseChildFields(fInfo.ChildFields, shift * 2)
            Next fInfo
End Sub

Public Sub GetMessageFields()
            Dim fields As FieldInfo() = dialectInstance.GetMessageFields("i")


            Dim fInfo As FieldInfo
            For Each fInfo In fields
                Console.WriteLine(fInfo.Tags + ", " + fInfo.IsRequired)
                TraverseChildFields(fInfo.ChildFields, 3)
            Next fInfo
End Sub

Message Resending

When the Resend Request (2) message is received from the counterparty (e.g due to the sequence numbers mismatch) and the application has subscribed to the SequenceReset-GapFill (MsgType 4) message will be sent instead of the requested message.

If the sent application-level message should be resent to the counterparty then the AllowResending property of Session.MessageResendingEventArgs parameter should be set to True in the corresponding Sequence Reset-GapFill (4) message will be sent instead (e.g. in case of an aged order).

The message that is about to be resent is available via MessageResendingEventArgs.Msg property of Session.MessageResendingEventArgs parameter.

Example in C# (.NET 2.0):
public void OnMessageResending(object sender, Session.MessageResendingEventArgs e)
{
	Console.WriteLine("Message " + e.Msg + " is about to be resent to the counterpart");

	e.AllowResending = true; // false - to skip (GapFill) this message
}

public void Run()
{
	Session session = new Session("SenderCompID", "TargetCompID", ProtocolVersion.FIX50);

	session.MessageResending += new Session.MessageResendingEventHandler(OnMessageResending);
	// ... 
}

Memory Based Session Storage

Memory based session storage could be used to maintain a high-performance FIX session when persisting of session’s state and messages in the file system is not required.

To create such a session storageType parameter of Session’s constructor should be set to SessionStorageType.MemoryBasedStorage.

Example in C# (.NET 2.0):

Boolean keepSequenceNumbersAfterLogout = false;

Session session = new Session("SenderCompID", "TargetCompID", ProtocolVersion.FIX42, keepSequenceNumbersAfterLogout, Session.SessionStorageType.MemoryBasedStorage);

Mutliple Listen Ports

To accept (listen for) incoming connections on multiple ports simultaneously these ports should be specified during FIX Engine initialization using either the ListenPort FIX Engine configuration setting or EngineSettings.ListenPorts property.

If a session-acceptor should be bound to a specific listen port then this port is explicitly defined via the Session.ListenPort property.

If there is an incoming FIX connection on one of the configured listen ports and the corresponding FIX session-acceptor is found without the specified listen port or with the same specified listen ports as the 'active' listen port the incoming FIX connection is accepted.

If the corresponding FIX session-acceptor is found, but the specified session listen port is not the same as the 'active' listen port then the incoming FIX connection is terminated.

Example in C# (.NET 2.0):

EngineSettings settings = new EngineSettings();
settings.ListenPorts = new int[] { 9001, 9002 };

Engine.Init(settings);

Session firstAcceptor = new Session("Acceptor_1", "Initiator_1", ProtocolVersion.FIX42);
firstAcceptor.LogonAsAcceptor();

Session secondAcceptor = new Session("Acceptor_2", "Initiator_2", ProtocolVersion.FIX42);
secondAcceptor.LogonAsAcceptor();

Session firstInitiator = new Session( "Initiator_1", "Acceptor_1", ProtocolVersion.FIX42);
firstInitiator.LogonAsInitiator("localhost", 9001);

Session secondInitiator = new Session( "Initiator_2", "Acceptor_2", ProtocolVersion.FIX42);
secondInitiator.LogonAsInitiator("localhost", 9002);

// Message exchange ...

firstInitiator.Logout();

secondInitiator.Logout();

SSL encryption

To use the Ssl (Secure Sockets Layer) connectivity the following steps should be taken:

  1. If the counterparty requires client-side SSL certificate set both SSL.CertificateFile and SSL.PrivateKeyFile FIX Engine configuration settings. They can refer to the same file if it contains both the SSL certificate and the private key.
  2. Set Session.Encryption property to Session.EncryptionMethod.SSL right after the creation of the Session object.
  3. Establish the FIX Connection as usual.
Example in C# (.NET 2.0):

EngineSettings settings = new EngineSettings();

// the next two assignments are only needed if the counterparty requires client-side SSL certificate:
settings.SslCertificateFile = "SSL_Certificate_File.pem";
settings.SslPrivateKeyFile = "SSL_PrivateKey_File.pem"; // could be the same file as above

Engine.Init(settings);

Session session = new Session("SenderCompID", "TargetCompID", ProtocolVersion.FIX42);

session.Encryption = Session.EncryptionMethod.SSL;

session.LogonAsInitiator("localhost", 443, true);

// Message exchange ...

session.Logout("SSL connection is finished.");

Example in Visual Basic (VB.NET):

Dim settings As New EngineSettings()

' the next two assignments are only needed if the counterparty requires client-side SSL certificate:
settings.SslCertificateFile = "SSL_Certificate_File.pem"
settings.SslPrivateKeyFile = "SSL_PrivateKey_File.pem" ' could be the same file as above

Engine.Init(settings)

Dim session As New Session("SenderCompID", "TargetCompID", ProtocolVersion.FIX42)

session.Encryption = Session.EncryptionMethod.SSL

session.LogonAsInitiator("localhost", 443, True)

' Message exchange ...

session.Logout("SSL connection is finished.")

See also: Settings.SSL.CertificateFile, Settings.SSL.ListenPort, Settings.SSL.PrivateKeyFile, Settings.SSL.PrivateKeyPassword, and Settings.SSL.VerifyPeer configuration settings.

Format of SSL certificates

The (Privacy Enhanced Mail) Base 64 Encoded (.pem) SSL certificates are supported.

To convert into this format from other format types, the openssl command-line tool could be used (http://www.openssl.org).

For example, to convert from "Personal Information Exchange - PKCS#12 (.pfx)" to "Base64 Encoded (.pem)", the following command is run on the PFX file:

openssl pkcs12 -in <file_name>.pfx -out <file_name>.pem -nodes

Per-session SSL settings

Per-session SSL settings ara available via Session.Ssl property.

Example in C# :

Engine.Init();

string targetCompID = "CNX";
string host = "TargetHost";

{ // Stream FIX Session

string streamSenderCompID = "str";

Session streamSession = new Session(streamSenderCompID, targetCompID, ProtocolVersion.FIX42);
streamSession.Encryption = Session.EncryptionMethod.SSL;

string streamSslCertificateAndPrivateKeyFile = "str.pem"; // If your counterpart performs the verification of your SSL certificate you need to set both SSL Certificate File and SSL Private Key File.
streamSession.Ssl.CertificateFile = streamSslCertificateAndPrivateKeyFile;
streamSession.Ssl.PrivateKeyFile = streamSslCertificateAndPrivateKeyFile;

int streamPort = 442;
streamSession.LogonAsInitiator(host, streamPort, 30, true);

Console.WriteLine("Stream session is established");

streamSession.Logout();
}

{ // Trading FIX Session

string tradingSenderCompID = "tr";

Session tradingSession = new Session(tradingSenderCompID, targetCompID, ProtocolVersion.FIX42);
tradingSession.Encryption = Session.EncryptionMethod.SSL;

string tradingSslCertificateAndPrivateKeyFile = "tr.pem";

// If your counterpart performs the verification of your SSL certificate you need to set both SSL Certificate File and SSL Private Key File.
tradingSession.Ssl.CertificateFile = tradingSslCertificateAndPrivateKeyFile;
tradingSession.Ssl.PrivateKeyFile = tradingSslCertificateAndPrivateKeyFile;

int tradingPort = 443;
tradingSession.LogonAsInitiator(host, tradingPort, 30, true);

Console.WriteLine("Trading session is established");

tradingSession.Logout();
}

FAST Encoding and Decoding

FAST (FIX Adapted for Streaming) is a binary encoding method for message oriented data streams.

FAST-related classes can be found in the FIXForge.NET.FIX.FAST namespace.

To encode a FIX message into a FAST stream the Encoder class is used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;

using FIXForge.NET.FIX.FAST;

const bool encodeEachMessageIndependently = true;
Encoder encoder = new Encoder(fastTemplates, FastVersion.FAST11, ProtocolVersion.FIX44, encodeEachMessageIndependently);

int templateIdentifier = 88;

byte[] fastStreamChunk = encoder.Encode(fixMessage, templateIdentifier);
Example in VB.NET:
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.FAST

Dim fastEncoder As Encoder = New Encoder(fastTemplates, FastVersion.FAST11, ProtocolVersion.FIX44, true)
Dim templateIdentifier As Integer = 88

Dim fastStreamChunk() As Byte = fastEncoder.Encode(fixMessage, templateIdentifier)

To decode a part of a FAST stream back into a FIX message the Decoder class is used.

Example in C# (.NET 2.0):
using FIXForge.NET.FIX;

using FIXForge.NET.FIX.FAST;

const bool decodeEachMessageIndependently = true;
Decoder decoder = new Decoder(fastTemplates, FastVersion.FAST11, ProtocolVersion.FIX44, decodeEachMessageIndependently);

Message fixMessage = decoder.Decode(fastStreamChunk);
Example in VB.NET:
Imports FIXForge.NET.FIX
Imports FIXForge.NET.FIX.FAST

Dim fastDecoder As Decoder = New Decoder(fastTemplates, FastVersion.FAST11, ProtocolVersion.FIX44, true)

Dim fixMessage As Message = fastDecoder.Decode(fastStreamChunk)

FAST Template

Both Encoder and Decoder constructors require the string that contains XML-based FAST templates.

A FAST Template specifies the encoding and decoding rules in accordance with the FAST specification.

For example:
<?xml version="1.0" encoding="utf-8"?>
<templates>

<template name="Market Data - Incremental Refresh (X)" id="88">
    <uInt32 name="BodyLength" id="9"/>
    <string name="MessageType" id="35">
      <constant value="X" />
    </string>
    <string name="SenderCompID" id="49">
      <copy/>
    </string>
    <string name="TargetCompID" id="56">
      <copy/>
    </string>
    <uInt64 name="MsgSeqNum" id="34">
      <increment value="1"/>
    </uInt64>
    <string name="SendingTime" id="52">
      <tail/>
    </string>
    <string name="PosDupFlag" id="43" presence="optional">
      <default/>
    </string>
    <sequence name="MDEntries">
      <length name="NoMDEntries" id="268"/>
      <string name="MDUpdateAction" id="279"/>
      <string name="Symbol" id="55"/>
    </sequence>
    <string name="CheckSum" id="10"/>
  </template>
<templates>

Field Types

The following field types are supported:

Field Example Notes
Signed 32-bit Integer <int32 name="MDEntrySize" id="271" presence="optional"> Min value: -2147483648
Max value: 2147483647
Unsigned 32-bit Integer <uInt32 name="BodyLength" id="9"/> Min value: 0
Max value: 4294967295
Signed 64-bit Integer <int64 name="MinQty" id="110"/> Min value: -9223372036854775808
Max value: 9223372036854775807
Unsigned 64-bit Integer <uInt64 name="MsgSeqNum" id="34"/> Min value: 0
Max value: 18446744073709551615
String <string name="SenderCompID" id="49"/> An optional charset attribute can be used to indicate the character set used in the string ("ascii" or "unicode").
Decimal <decimal name="MDEntryPx" id="270">
<exponent/>
<mantissa/>
</decimal>
Indicates that the field is represented by two parts: an exponent and a mantissa.
Byte Vector <byteVector name="RawData" id ="96" presence="optional"/> Sequence of bytes.
Sequence <sequence name="NoSecurityAltID" id="454" presence="optional">
<string name="SecurityAltID" id="455"/>
</sequence>

Specifies that the contained group of instructions should be used repeatedly to encode each element (e.g. to encode/decode a FIX Repeating Group).

A sequence can have an associated length field containing an unsigned integer indicating the number of encoded elements.

The optional presence attribute indicates whether the field is mandatory or optional. If the attribute is not specified, the field is mandatory.

The required name attribute identifies the corresponding field in the current FIX message type by the field name.

The optional id attribute identifies the corresponding field in the current FIX message type by the tag number.

Field Operators

A field that is not a Sequence can have a field operator. The Field Operator specifies an optimization operation for the field.

The following field operators are supported:

Field Operator Example Notes

Constant

<string name="MessageType" id="35">
<constant value="X" />
</string>

Specifies that the value of a field will always be the same initial value.

Is applicable to all field types.

Default

<string name="PosDupFlag" id="43" presence="optional">
<default = "N" />
</string>

Specifies that the value of a field is either present in the FAST stream or it will be the initial value.

Is applicable to all field types.

Copy

<uInt32 name="MDUpdateAction" id="279">
<copy value="1" />
</uInt32>

If the value is present in the stream it becomes the new previous value, otherwise the value of the field is the previous value.

Is applicable to all field types.

Increment

<uInt32 name="RptSeq" id="83">
<increment />
</uInt32>

If the value is present in the stream it becomes the new previous value, otherwise the value of the field is the previous value incremented by one.

Is applicable to Integer field types only.

Delta

<int32 name="MDEntrySize" id="271">
<delta />
</int32>

Specifies that a delta value is present in the stream.  The field is obtained by combining the delta value with the previous value.

Is applicable to Integer, Decimal, String and Byte Vector field types.

Tail

<string name="SendingTime" id="52">
<tail/>
</string>

Specifies that a tail value is present in the stream.  The value of the field is obtained by combining the tail value with the previous value. 

Is applicable to String and Byte Vector fields with constant or increasing value length.

Template Identifier (Template ID)

Each FAST Template is assigned a Template Identifier which uniquely describes the encoding/decoding rules.
More than one FAST template can be used to encode the same FIX message type, so the Template ID is supplied as an argument of the Encoder.Encode method.

Dictionaries

Some Field Operators rely on a previous value. Previous values are maintained in named dictionaries.
To reset the state of dictionaries (set the state of the previous values to undefined) the Encoder.Reset and Decoder.Reset methods are used.

Frequently Asked Questions (FAQ)

  1. Q. I need to continue the FIX Session starting from the specific message sequence number, but I have deleted the log files from the previous runs. How can I do this?
    A. You can use Session.InSeqNum and Session.OutSeqNum properties to set the start sequence numbers before establishing the session. See also: Sequence Numbers.
  2. Q. Why does my GUI application hang when I try to handle the Engine events?
    A. The most probable reason is that you are trying to update GUI controls directly from the event handler. It is necessary to use Control.Invoke instead. See also: Updating GUI Controls on Session event.
  3. Q. How can I customize the FIX Engine to work with non-standard FIX counterparties that employ user-defined fields and messages (use modifications of the FIX Protocol)?
    A. You need to define and use the corresponding XML-based FIX Dialect description. See: FIX Dialects.
  4. Q. What is the default behavior of the FIX Engine in case a Test Request <1> message was sent to the counterparty and the counterparty does not respond?
    A. When the response on the Test Request <1> message is not received during HeartBeatInt, the FIX Connection is considered lost. FIX Session-Acceptor changes its state to LOGON_IN_PROGRESS. FIX Session-Initiator changes its state to RECONNECTING and tries to restore the FIX Connection pre-configured number of times in pre-configured interval (using the binary exponential back off algorithm). Please note that FIX Engine automatically handles sending of Test Request messages (when needed). See also: Reconnect.Attempts and Reconnect.Interval.
  5. Q. How can I set SenderSubID and OnBehalfOfSubID fields in the Logon message?
    A. Please use Custom Logon Message.

    For example:
    Example in C# (.NET 2.0):
    Message customLogonMsg = new Message("A", FIXForge.NET.FIX.ProtocolVersion.FIX42);
    
    customLogonMsg[Tags.SenderSubID] = "SenderSubID_Value";
    customLogonMsg[Tags.OnBehalfOfSubID] = "OnBehalfOfSubID_Value";
    
    Example in Visual Basic (VB.NET):
    Dim customLogonMsg As New Message("A", FIXForge.NET.FIX.ProtocolVersion.FIX42)
    
    customLogonMsg.Set(Tags.SenderSubID, "SenderSubID_Value")
    customLogonMsg.Set(Tags.OnBehalfOfSubID, "OnBehalfOfSubID_Value")
    
  6. Q. Why do I receive the "Invalid FIX Engine settings: Cannot open the persistent storage folder ('MsgStorage')" error (exception) when I try to run my FIX application as a Windows service? When I run my application as a standalone one, all work perfectly OK.
    A. The reason of this error is the different default current folder for Windows Service and Windows application. By default, the current directory for your Windows service is the System32 folder. To solve this issue specify the full path to the persistent storage folder using the Log.Directory setting. See also: Settings.
  7. Q. How can I set SenderSubID, TargetSubID, SenderLocationID, TargetLocationID in all outgoing messages (including session-level ones)?
    A. You can use SenderSubID, TargetSubID, SenderLocationID, Session object.
  8. Q. How will I know if I do not have the valid license file - i.e. what is failure mode/message for the FIX Engine?
    A. When the license expires EngineException is thrown during the call of the Error Reporting.

Glossary

Acceptor
Session-acceptor is the receiving party of the FIX session. It listens for the incoming connection on the pre-defined port. The acceptor has responsibility to perform first level authentication and formally declare the connection request "accepted" through transmission of an acknowledgment Logon message.
Conditionally required fields
Fields which are required based on the presence or value of other fields.
Delimiter character
The non-printing, ASCII "SOH" (\u0001, hex:  0x01, referred to in this document as <SOH>), is used for field termination.
MsgSeqNum field
Integer message sequence number, the tag number is 34.
FIX
The Financial Information Exchange (FIX) Protocol is a message standard developed to facilitate the electronic exchange of information related to securities transactions.   It is intended for use between trading partners wishing to automate communications. 
FIX Connection
It is comprised of three parts: logon, message exchange, and logout.
FIX Dialect
This is a custom, slightly different interpretation of FIX protocol.