Click here to Skip to main content
12,746,535 members (31,503 online)
Click here to Skip to main content
Add your own
alternative version


28 bookmarked
Posted 14 Apr 2009

Fix Protocol C# Fix Engine Source Code

, 16 Apr 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Fix Protocol C# Fix Engine Source Code


I needed some C# fix protocol engine code and was disappointed that there is almost nothing on the internet, so here is a small project in VS 2005. It actually connects to EBS AI v4 fix which is a major foreign exchange trading platform. Fix servers are usually huge projects but there is a simple way to cut them down to nothing - do not support message retransmission. In fact EBS, along with many others, does not support message retransmission either because it is pointless for today's 100% reliable socket communication. Using this technique, you can avoid paying for a fix engine or fighting with QuickFix and it will be much faster as well. This code is for connecting to a big reliable platform, not for connecting to customers who might send you junk.

Points of Interest

Some people process fix messages by splitting the received bytes into a vector of string pairs or even a vector of maps - but this is pointlessly slow! Instead I pass simply the start and end location of the fix message in the buffer and provide a few functions such as ReadKey(), ReadStringValue(), ReadIntegerValue(), SkipValue(), etc. The ProcessMessage code can then more quickly process the fields as desired. Usually the order of the data is constant, but if it is not use a loop and case. Repeating blocks will always have some field marking the start of a new block. When I am reading the integer key, I use a loop that subtracts 48 from the char value and multiples by 10 etc. rather than just calling convert to string and Convert.Int32(..). In other words, I have taken care to keep it all mostly as fast as possible.

Normally a class like this would have an interface with various events but again this is just sample code so I am not including this stuff. I am using a synchronous or blocking socket read instead of asynchronous events. This is slightly faster for a single connection example like this which only consumes one thread. With debug on, I log to a simple StreamWriter. Of course any logging should actually take place in a proper logging class with a queue and intermittent writing thread (always to the local drive, keep network traffic to a minimum), but I have not bothered including code for that in here. Note you don't need to waste time logging fix except in debug mode - in the event of a problem you can always get the monster log file from your vendor anyway.

Processing the fix messages in this code takes just a few microseconds but how fast are sockets in .NET? I wrote some test code that sends messages between a server and a client server running on the same machine in C#, C++ and Linux C++. I used RTDSC to time the server send to client receive interval. For messages up to about 1.5k bytes in size, I got a pretty steady time of 70 microseconds in C#. In Windows C++, this came down to 45 microseconds. Rewriting all this in Linux C++ gave 25 microseconds. This performance hit compared to Linux C++ is probably OK for most people.

Some Code Examples

private byte[] _buffer_data = new byte[655360]; // buffer
private int _buffer_end=0; // this is the number of bytes of data in the buffer 
private int _buffer_start=0; // this is posn of current message

private void ReadData()
        while (true)
            // we are using a blocking read.. so at this point 
	   // we will always be exactly at the start of a new fix message
            // read at least enough data to get the message length
            // Stre the location of the start of the fix message in 
	   // fix_message_buffer_start
            int fix_message_buffer_start = _buffer_start; 
            // message starts "8=FIXT.1.1/9=" which has length 13
            if (_buffer_data[_buffer_start] != '8' || 
			_buffer_data[_buffer_start+1] != '=') 
                ErrorHandler("message did not start with 8=", 
			fix_message_buffer_start, 25);
            // read the message length
            int length = ReadIntValue(ref _buffer_start);
            // Store the total length of the message in fix_message_buffer_length
            int fix_message_buffer_length = _buffer_start - 
				fix_message_buffer_start + length + 7;
            // we are only sure we have read the first 25 bytes of the message - 
	   // now read the rest
            // now parse the message
            int end = _buffer_start + length - 1; // _buffer_data[end] is the 01 
			// end field terminator just before the checksum starts
            // Message must start with 35=
            if (_buffer_data[_buffer_start] != 51 || 
		_buffer_data[++_buffer_start] != 53 || 
		_buffer_data[++_buffer_start] != 61)
                ErrorHandler("35= Was not at the start of the message", 
		fix_message_buffer_start, fix_message_buffer_length);
            string fix_message_id = ReadStringValue(ref _buffer_start);
            // Now skip the next four fields which are SenderCompId 
	   // and MsgSeqNum and TargetCompId and SendingTime
            SkipValue(ref _buffer_start);
            SkipValue(ref _buffer_start);
            SkipValue(ref _buffer_start);
            SkipValue(ref _buffer_start);
            // Process the fix message
            ProcessFixMessage(fix_message_id, fix_message_buffer_start, 
			fix_message_buffer_length, _buffer_start, end);
            // Move to end of message
            _buffer_start = fix_message_buffer_start + fix_message_buffer_length;
            // Clean the buffer out if there are no more messages inside it 
	   // (normally the case)
            if (_buffer_start == _buffer_end) _buffer_start = _buffer_end = 0;

    private int ReadKey(ref int posn)
        int val=_buffer_data[posn] - 48;
        while (_buffer_data[++posn] != 61) val = val * 10 + _buffer_data[posn] - 48;
        return val;

    private string ReadStringValue(ref int posn)
    { // we assume the value is at least one character long
        string val;
        int posn_temp=posn;
        while (_buffer_data[++posn] != 1) {  }
        val = Encoding.ASCII.GetString(_buffer_data, posn_temp, posn - posn_temp );
        return val;

    private void ReadSocket(int numbytes) 	// Block until we have at least 
				     	// numbytes of data in the buffer
        int bytes_available = _buffer_end - _buffer_start;
        while (bytes_available < numbytes)
                int size = _socket_networkstream.Read
			(_buffer_data, _buffer_end, 655360 - _buffer_end);
                if (size==0) ErrorHandler("Socket Dead",0,0);
                _buffer_end += size;
                // record the time now - this is the time before message processing -
                //  if the message arrived in parts this is the 
	       // first time all the data we need is in the buffer            
                ErrorHandler("Socket Dead",0,0);
            bytes_available = _buffer_end - _buffer_start;

    private void ProcessFixMessage(string message_id, 
	int message_buffer_start, int message_buffer_length, int start, int end)
        if (message_id == "AE") // Trade Report or Deal mesage
        { // this message does not come in a reliable order - 
	 // use a case to extract the values we need
            Console.WriteLine("Trade Report");
            string sOrderId = null; // 37 This is our order id
            string sMatchStatus = null; 	// 573 - "Z" for Pending, "2" 
					// for Confirmed, "0" for Done
            string sSymbol = null; // 55
            int iLastQty = 0; // 32
            string sLastPx = null; // 31
            string sSide = null; // 54

            while (start < end)
                int key = ReadKey(ref start);
                switch (key)
                    case 573:
                        sMatchStatus = ReadStringValue(ref start);
                    case 55:
                        sSymbol = ReadStringValue(ref start);
                    case 32:
                        iLastQty = ReadIntValue(ref start)/1000000;
                    case 31:
                        sLastPx = ReadStringValue(ref start);
                    case 54:
                        sSide = ReadStringValue(ref start);
                    case 37:
                        sOrderId = ReadStringValue(ref start);
                        SkipValue(ref start);

            _fixlog.WriteLine("TRADE_MESSAGE: MatchStatus=" + sMatchStatus + "," + 
                              "Order ID="+sOrderId + "," +
                              "Side=" + sSide + "," +
                                sSymbol + "," + sLastPx + "," + iLastQty );

        if (message_id == "X") // MarketUpdateEventMsg
           etc etc...

    private void FixSendMessage(string type, string body)
        StringBuilder sb = new StringBuilder();
        string t = sb.ToString();
        sb.Length = 0;
        t = sb.ToString();
        int sum = 0;
        int len = t.Length;
        for (int i = 0; i < len; i++) sum += Convert.ToChar(t.Substring(i, 1));
        sum = sum % 256;
        byte[] buffer = Encoding.ASCII.GetBytes(sb.ToString());
        _socket_networkstream.Write(buffer, 0, buffer.Length);

    private void SendLogon1()
        // 8=FIXT.1.1/9=84/35=A/49=ME/56=ICAP_AI_Server/34=1/
        // 52=20090402-12:57:29/98=0/108=1/1137=7/10=153/
        FixSendMessage("A", "98=0/108=1/1137=7/");


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

You may also be interested in...


Comments and Discussions

QuestionRating Limitations Pin
Tomaž Štih3-Nov-15 5:18
memberTomaž Štih3-Nov-15 5:18 
AnswerRe: Rating Limitations Pin
AcrobatX23-Nov-15 10:19
memberAcrobatX23-Nov-15 10:19 
GeneralGreat job Pin
David Jiboye31-Jul-13 5:46
memberDavid Jiboye31-Jul-13 5:46 
QuestionWhat Fix version is it done for? FIXT.1.1? Pin
darch229-Jun-13 10:58
memberdarch229-Jun-13 10:58 
QuestionVery very awesome! Pin
Member 199004718-Apr-13 17:59
memberMember 199004718-Apr-13 17:59 
GeneralMy vote of 5 Pin
qtonchr17-Apr-11 23:32
memberqtonchr17-Apr-11 23:32 
GeneralMy vote of 3 Pin
matthias Weiser22-Sep-10 2:20
membermatthias Weiser22-Sep-10 2:20 
General[My vote of 1] this is very slowly looking codes. Pin
vishram sharma15-Aug-10 5:14
membervishram sharma15-Aug-10 5:14 
GeneralMessage Automatically Removed Pin
15-Aug-10 19:37
memberw.hooper15-Aug-10 19:37 
GeneralRe: [My vote of 1] this is very slowly looking codes. Pin
vishram sharma15-Aug-10 22:19
membervishram sharma15-Aug-10 22:19 
GeneralMessage Automatically Removed Pin
16-Aug-10 23:53
memberw.hooper16-Aug-10 23:53 
GeneralRe: [My vote of 1] this is very slowly looking codes. Pin
vishram sharma19-Aug-10 3:49
membervishram sharma19-Aug-10 3:49 
GeneralMessage Automatically Removed Pin
12-Jul-12 6:53
memberDevAlgoTrade12-Jul-12 6:53 
GeneralMy vote of 5 Pin
FXMC10-Aug-10 9:23
memberFXMC10-Aug-10 9:23 
GeneralGreat stuff. Pin
FXMC10-Aug-10 9:23
memberFXMC10-Aug-10 9:23 
GeneralMy vote of 1 Pin
Member 1841428-Jul-10 6:34
memberMember 1841428-Jul-10 6:34 
GeneralGood starting point Pin
Member 41797953-Jun-10 5:11
memberMember 41797953-Jun-10 5:11 
Generalfix server Pin
bachebahal_13638-Dec-09 1:43
memberbachebahal_13638-Dec-09 1:43 
GeneralWas helpful Pin
ritzy pal29-Sep-09 22:17
memberritzy pal29-Sep-09 22:17 
GeneralTCPIP Reconstruction Pin
prgtrdr20-Jul-09 2:29
memberprgtrdr20-Jul-09 2:29 
GeneralGood Job Pin
black198130-May-09 4:06
memberblack198130-May-09 4:06 
GeneralMy vote of 2 Pin
ZTransform16-Apr-09 3:42
memberZTransform16-Apr-09 3:42 
GeneralRe: My vote of 2 Pin
w.hooper20-Apr-09 1:43
memberw.hooper20-Apr-09 1:43 
Generalunsafe code Pin
xliqz14-Apr-09 8:42
memberxliqz14-Apr-09 8:42 
GeneralRe: unsafe code Pin
williammorrishooper14-Apr-09 8:58
memberwilliammorrishooper14-Apr-09 8:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170215.1 | Last Updated 16 Apr 2009
Article Copyright 2009 by w.hooper
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid