This post will demonstrate how to connect with FIX5.0 server and FIXT1.1 specification and uses of QuickFix/n (native .NET FIX engine).
Introduction
With this release of FIX protocol version 5.0, a new Transport Independence framework (TI) introduced which separates the FIX Session Protocol from the FIX Application Protocol. This gives freedom to send message across different messaging technologies like MSMQ, message bus etc.
Because of different versions of transport and application protocol, we will have to explicitly defines settings in config file.
TransportDataDictionary is used for defining transport protocol version eg. FIXT.1.1.xml
AppDataDictionary is used for defining data dictionary for FIX application protocol version eg. FIX50.xml
You can read more about FIXT1.1 and FIX 5.0 Sp2 specification on fixprotocol.org.
http://fixprotocol.org/specifications/FIXT.1.1
http://fixprotocol.org/specifications/FIX.5.0
QuickFix/N
To demonstrate implementation of FIX 5.0 sp2, I’ll use open source FIX engine for .net (QuickFix/N) which is one of best open source engine in native .NET code. Code for quickfix.net is available on github and primarily contributed by Connamara System’s developers. These guys are doing commendable job.
Implementation
FixInitiator
This is client application which will connect with FIX server to send and receive FIX messages. I am demonstrating implementation of MarketDataRequest and its responses (MarketDataSnapshot & MarketDataIncrementalRefresh).
Start with Configuration
First we create configuration file for initiator.
[default]
PersistMessages=Y
ConnectionType=initiator
UseDataDictionary=Y
[SESSION]
ConnectionType=initiator
FileStorePath=store
FileLogPath=fixlog
BeginString=FIXT.1.1
DefaultApplVerID=FIX.5.0
TransportDataDictionary=FIXT.1.1.xml
AppDataDictionary=FIX50.xml
SenderCompID=ABC
TargetCompID=FIXSERVER
SocketConnectHost=127.0.0.1
SocketConnectPort=3500
HeartBtInt=20
ReconnectInterval=30
ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y
*Note- AppDataDictionary is for application protocol eg. FIX 5.0 and TransportDataDictionary is for transport protocol.
You can read more about configuration here.
Create Application Class
Before starting with implementation you would need to have quickFix.dll which is available of github at https://github.com/connamara/quickfixn
To connect with FIX session, you will have to implement QuickFix.Application
interface.
public interface Application
{
void FromAdmin(Message message, SessionID sessionID);
void FromApp(Message message, SessionID sessionID);
void OnCreate(SessionID sessionID);
void OnLogon(SessionID sessionID);
void OnLogout(SessionID sessionID);
void ToAdmin(Message message, SessionID sessionID);
void ToApp(Message message, SessionID sessionId);
}
I create one class named FixClient50Sp2
which implements interface and inherit base class for message cracking and getting message events.
FIX Application Setup
Setting up Initiator
var settings = new SessionSettings("C:\\initiator.cfg");
MessageStoreFactory storeFactory = new FileStoreFactory(settings);
LogFactory logFactory = new FileLogFactory(settings);
_client = new FixClient50Sp2(settings);
IInitiator initiator = new SocketInitiator(_client, storeFactory, settings, logFactory);
_client.Initiator = initiator;
* _client
is an instance of the class FixClient50Sp2
.
Starting Initiator
_client.Start();
Implementation of QuickFix.Application Interface methods
public void FromAdmin(Message message, SessionID sessionId)
{
Log(message.ToString());
}
public void FromApp(Message message, SessionID sessionID)
{
Trace.WriteLine("## FromApp: " + message);
Crack(message, sessionID);
}
public void OnCreate(SessionID sessionID)
{
if (OnProgress != null)
Log(string.Format("Session {0} created", sessionID));
}
public void OnLogon(SessionID sessionID)
{
ActiveSessionId = sessionID;
Trace.WriteLine(String.Format("==OnLogon: {0}==", ActiveSessionId));
if (LogonEvent != null)
LogonEvent();
}
public void OnLogout(SessionID sessionID)
{
string a = (ActiveSessionId == null) ? "null" : ActiveSessionId.ToString();
Trace.WriteLine(String.Format("==OnLogout: {0}==", a));
if (LogoutEvent != null)
LogoutEvent();
}
public void ToAdmin(Message message, SessionID sessionID)
{
Log("To Admin : " + message);
}
public void ToApp(Message message, SessionID sessionId)
{
Log("To App : " + message);
}
Callback to Subscription
public void OnMessage(MarketDataIncrementalRefresh message, SessionID session)
{
var noMdEntries = message.NoMDEntries;
var listOfMdEntries = noMdEntries.getValue();
var group = new MarketDataIncrementalRefresh.NoMDEntriesGroup();
Group gr = message.GetGroup(1, group);
string sym = message.MDReqID.getValue();
var price = new MarketPrice();
for (int i = 1; i <= listOfMdEntries; i++)
{
group = (MarketDataIncrementalRefresh.NoMDEntriesGroup)message.GetGroup(i, group);
price.Symbol = group.Symbol.getValue();
MDEntryType mdentrytype = group.MDEntryType;
if (mdentrytype.getValue() == ’0′) {
decimal px = group.MDEntryPx.getValue();
price.Bid = px;
}
else if (mdentrytype.getValue() == ’1′) {
decimal px = group.MDEntryPx.getValue();
price.Offer = px;
}
price.Date = Constants.AdjustedCurrentUTCDate.ToString("yyyyMMdd");
price.Time = group.MDEntryTime.ToString();
}
if (OnMarketDataIncrementalRefresh != null)
{
OnMarketDataIncrementalRefresh(price);
}
}
Code can be found at github.