0

I am newbie to fix protocol and quick fix programming. I am seeking a help on getting Trade Capture report from ICE. I have googled for the sample/ tutorial to use quick fix/n to get the trade report but I am not being able to get sufficient output of it. My problem is to get Trade Capture report or deal information for this I tried using TradeCaptureReportRequest, TradeCaptureReportRequestAck, TradeCaptureReport classes but somehow its now working. A simple how to extract information would be a great help. thanking everyone out there in advance.

ze-corps
  • 65
  • 1
  • 9
  • So you are getting a response, and having trouble parsing the data? Just making sure I understand clearly. – Aaron Nov 14 '16 at 18:48
  • If you need to simply get a field, use msg.GetField(int) where the int is the enum value in your definition file (FIX50SP2.xml, eg). If it is a header field, msg.Header.GetField(int). Is that what you need? – Aaron Nov 14 '16 at 18:55
  • @aaron I m not getting any response. Actually it doesn't do anything at all. Can you please elaborate the overall process of this integration? – ze-corps Nov 14 '16 at 19:25
  • I'll be at my desk in a few. I'll see if I can help out. Do you have the skeleton built already? (Do you have your FIX[ver].XML, initiator.cfg, and a main form creating a message all in your project? – Aaron Nov 14 '16 at 19:28
  • @aaron, I do have few but i do not think its correct. if you could provide a sample and steps would be a great help. – ze-corps Nov 14 '16 at 20:07
  • @aaron Thanks for the answer. Will try it out and will let you know – ze-corps Nov 14 '16 at 21:17

1 Answers1

2

Ok I am posting as an answer because it's going to be way too long for a comment. Please keep in mind that I have written custom constants, message types, etc (I wrote my acceptor server as well, so I'm not restricted by ICE constants/enums). You will need to determine what fields are required by ICE and make changes - this will not be easy to copy/paste...

First, you need to make sure you have all required files in and referenced. I create a folder called "fix" in my project, and copy all fix files into it. These need to be (at least 1) FixXXX.xml file, if you're using FIX50SP1 or 2, you need to also have FIXT11.xml. Along with the .xml files, you need to have an initiator.cfg file (assuming you're making an initiator, no a server, otherwise this will need to be "acceptor.cfg" but again, it sounds like you're trying to connect to ICE, so initiator is the correct usage. Finally, you will need to have a QuickFix.dll. My tree looks as below: enter image description here

I am not going to go through the XML files - you will need to just learn that - it is very confusing and takes time.. especially if using FIXT11.XML along with SP1 or 2.

Your initiator.cfg should be similar to below:

# default settings for sessions
[DEFAULT]
FileStorePath=store
FileLogPath=log
ConnectionType=initiator
ReconnectInterval=60
SenderCompID=[Enter yours]

ResetOnLogon=Y 
ResetOnLogout=Y 
ResetOnDisconnect=Y 


[SESSION]
BeginString=FIXT.1.1
TargetCompID=[Enter ICE Acceptor]
DefaultApplVerID=FIX.5.0
StartTime=12:30:00
EndTime=21:30:00
# overide default setting for RecconnectInterval
ReconnectInterval=30
HeartBtInt=30
SocketConnectPort=[From ICE]
# (optional) only listen for incoming connections on a specific host
#SocketConnectHost=127.0.0.1
SocketConnectHost=[ICE Ip Address- from your documentation/registration]
DataDictionary=..\..\fix\FIX50.xml
TransportDataDictionary=..\..\fix\FIXT11.xml

Ok, assuming that you have QuickFix.dll imported and referenced, and your initiator.cfg properly connected, it's actually fairly simple:

Create a Class that handles everything. Ignore AddToLB, that is a testing function.

public class TCT_Fix : Control, IApplication
{
    private readonly string username = [removed]
    private readonly string password = [removed]
    public string InitiatorID;                           
    SessionID sessionID;                                 
    public bool running;                                 
    SessionSettings settings;
    IMessageStoreFactory storeFactory;
    ILogFactory logFactory;
    SocketInitiator initiator;
    public event EventHandler AddToLB;
    public event EventHandler AddToAdmin;
    public void StopIt()
    {
        if (sessionID == null) return;
        try
        {
            Session.LookupSession(sessionID).Disconnect("Stopping");
            settings.Remove(sessionID);
            settings = null;
            initiator.Dispose();
            settings = new SessionSettings(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fix", "initiator.cfg"));
            storeFactory = new FileStoreFactory(settings);
            logFactory = new FileLogFactory(settings);
            initiator = new SocketInitiator(
                this,
                storeFactory,
                settings,
                logFactory);
        }
        catch { }   
    }
    public void FromApp(QuickFix.Message msg, SessionID sessionID)
    {
        var sMsg = "FROM APP: " + msg.ToString();
        AddToLB(sMsg, null);
        if (msg.Header.GetField(35) == "TC") //Cash
        {
            DateTime dtTdate;
            float fPrice;
            int Qty;
            int OrdType;
            bool BPisBuyer;

            DateTime.TryParse(msg.GetField(CustomConstants.TDATE),out dtTdate);
            string BPSide = msg.GetField(CustomConstants.BP_SIDE);                
            float.TryParse(msg.GetField(CustomConstants.F_PRICE), out fPrice);
            int.TryParse(msg.GetField(CustomConstants.QTY), out Qty);
            string TCTReference = msg.GetField(CustomConstants.TCT_REF);
            string BPAcct = msg.GetField(CustomConstants.BP_COMPANY);
            int.TryParse(msg.GetField(CustomConstants.ORDER_TYPE), out OrdType);
            string ExecBkr = msg.GetField(CustomConstants.EXEC_BKR);
            string CounterParty = msg.GetField(CustomConstants.COUNTER_PARTY);
            BPisBuyer = msg.GetField(CustomConstants.IS_BUYER) == "Y";
            string BPTrader = msg.GetField(CustomConstants.BP_TRADER);
            string CounterTrader = msg.GetField(CustomConstants.COUNTER_TRADER);
            string Grade = msg.GetField(CustomConstants.GRADE);
            string Location = msg.GetField(CustomConstants.LOCATION);
            string CycDt = msg.GetField(CustomConstants.CYCLE_DATE);
            string DelMo = msg.GetField(CustomConstants.DELIVER_MONTH);
            string Terms = msg.GetField(CustomConstants.TERMS);
            string Payment = msg.GetField(CustomConstants.PAYMENT);
            string Origin = msg.GetField(CustomConstants.ORIGIN);
            string NumOfCyc = msg.GetField(CustomConstants.NUM_OF_CYCLES);
            string Via = msg.GetField(CustomConstants.VIA);
            string MoveMo = msg.GetField(CustomConstants.MOVE_MONTH);
            string Comment = msg.GetField(CustomConstants.COMMENT);
        }
        else if (msg.Header.GetField(35) == "TE") //EFP
        {
            DateTime dtTdate;
            float fPrice;
            int Qty;
            int OrdType;
            bool BPisBuyer;
            bool IsWater;

            DateTime.TryParse(msg.GetField(CustomConstants.TDATE), out dtTdate);
            string BPSide = msg.GetField(CustomConstants.BP_SIDE);
            float.TryParse(msg.GetField(CustomConstants.F_PRICE), out fPrice);
            int.TryParse(msg.GetField(CustomConstants.QTY), out Qty);
            string TCTReference = msg.GetField(CustomConstants.TCT_REF);
            string BPAcct = msg.GetField(CustomConstants.BP_COMPANY);
            int.TryParse(msg.GetField(CustomConstants.ORDER_TYPE), out OrdType);
            string ExecBkr = msg.GetField(CustomConstants.EXEC_BKR);
            string CounterParty = msg.GetField(CustomConstants.COUNTER_PARTY);
            BPisBuyer = msg.GetField(CustomConstants.IS_BUYER) == "Y";
            string BPTrader = msg.GetField(CustomConstants.BP_TRADER);
            string CounterTrader = msg.GetField(CustomConstants.COUNTER_TRADER);
            string Grade = msg.GetField(CustomConstants.GRADE);
            string Location = msg.GetField(CustomConstants.LOCATION);
            string CycDt = msg.GetField(CustomConstants.CYCLE_DATE);
            string DelMo = msg.GetField(CustomConstants.DELIVER_MONTH);
            string Terms = msg.GetField(CustomConstants.TERMS);
            string Payment = msg.GetField(CustomConstants.PAYMENT);
            string Origin = msg.GetField(CustomConstants.ORIGIN);
            string NumOfCyc = msg.GetField(CustomConstants.NUM_OF_CYCLES);
            string Via = msg.GetField(CustomConstants.VIA);
            string MoveMo = msg.GetField(CustomConstants.MOVE_MONTH);
            string Comment = msg.GetField(CustomConstants.COMMENT);
            IsWater = msg.GetField(CustomConstants.ISWATER) == "Y";
            string BPFloorBkr = msg.GetField(CustomConstants.BP_FLOOR_BKR);
            string CounterFloorBkr = msg.GetField(CustomConstants.COUNTER_FLOOR_BKR);
            string Diff = msg.GetField(CustomConstants.DIFFERENCE);
            string MercMo = msg.GetField(CustomConstants.MERC_MO);
            string MercPr = msg.GetField(CustomConstants.MERC_PRICE);
        }
        else if (msg.Header.GetField(35) == "TI") //Index
        {
            DateTime dtTdate;
            float fPrice;
            int Qty;
            int OrdType;
            bool BPisBuyer;
            bool IsWater;

            DateTime.TryParse(msg.GetField(CustomConstants.TDATE), out dtTdate);
            string BPSide = msg.GetField(CustomConstants.BP_SIDE);
            float.TryParse(msg.GetField(CustomConstants.F_PRICE), out fPrice);
            int.TryParse(msg.GetField(CustomConstants.QTY), out Qty);
            string TCTReference = msg.GetField(CustomConstants.TCT_REF);
            string BPAcct = msg.GetField(CustomConstants.BP_COMPANY);
            int.TryParse(msg.GetField(CustomConstants.ORDER_TYPE), out OrdType);
            string ExecBkr = msg.GetField(CustomConstants.EXEC_BKR);
            string CounterParty = msg.GetField(CustomConstants.COUNTER_PARTY);
            BPisBuyer = msg.GetField(CustomConstants.IS_BUYER) == "Y";
            string BPTrader = msg.GetField(CustomConstants.BP_TRADER);
            string CounterTrader = msg.GetField(CustomConstants.COUNTER_TRADER);
            string Grade = msg.GetField(CustomConstants.GRADE);
            string Location = msg.GetField(CustomConstants.LOCATION);
            string CycDt = msg.GetField(CustomConstants.CYCLE_DATE);
            string DelMo = msg.GetField(CustomConstants.DELIVER_MONTH);
            string Terms = msg.GetField(CustomConstants.TERMS);
            string Payment = msg.GetField(CustomConstants.PAYMENT);
            string Origin = msg.GetField(CustomConstants.ORIGIN);
            string NumOfCyc = msg.GetField(CustomConstants.NUM_OF_CYCLES);
            string Via = msg.GetField(CustomConstants.VIA);
            string MoveMo = msg.GetField(CustomConstants.MOVE_MONTH);
            string Comment = msg.GetField(CustomConstants.COMMENT);
            IsWater = msg.GetField(CustomConstants.ISWATER) == "Y";
            string BPFloorBkr = msg.GetField(CustomConstants.BP_FLOOR_BKR);
            string CounterFloorBkr = msg.GetField(CustomConstants.COUNTER_FLOOR_BKR);
            string Diff = msg.GetField(CustomConstants.DIFFERENCE);
            string MercMo = msg.GetField(CustomConstants.MERC_MO);
            string MercPr = msg.GetField(CustomConstants.MERC_PRICE);


        }
    }
    public void OnCreate(SessionID sessionID)
    {
        AddToAdmin("SESSION CREATED: " + sessionID.ToString(), null);
    }
    public void OnLogout(SessionID sessionID)
    {
        AddToAdmin("LOGOUT: " + this.sessionID.ToString(), null);       
    }
    public void OnLogon(SessionID sessionID)
    {
        this.sessionID = sessionID;
        AddToAdmin("LOG ON: " + this.sessionID.ToString(),null);
    }
    public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
    {
        AddToAdmin("FROM ADMIN: " + msg.ToString(), null);
    }
    public void ToAdmin(QuickFix.Message msg, SessionID sessionID)
    {
        if (msg.Header.GetField(35).ToString() == "A")
        {
            msg.SetField(new QuickFix.Fields.Username(username));
            msg.SetField(new QuickFix.Fields.Password(password));
        }

        AddToAdmin("TO ADMIN: " + msg.ToString(), null);
    }
    public void ToApp(QuickFix.Message msg, SessionID sessionID)
    {
        AddToLB("TO APP: " + msg.ToString(), null);       
    }        
    public void GetTestMessage(string msgType)
    {
        if (sessionID == null) return;
        QuickFix.FIX50.TestMessage msg = new QuickFix.FIX50.TestMessage();
        msg.TestType = msgType;
        msg.Header.SetField(new QuickFix.Fields.MsgType("TEST"));
        msg.SetField(new QuickFix.Fields.StringField(CustomConstants.TEST_TYPE, msgType));
        Session.SendToTarget(msg, sessionID);
    }
    public TCT_Fix()
    {
        settings = new SessionSettings(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fix", "initiator.cfg"));
        storeFactory = new FileStoreFactory(settings);
        logFactory = new FileLogFactory(settings);
        initiator = new SocketInitiator(
            this,
            storeFactory,
            settings,
            logFactory);
    }
    public TCT_Fix(ref string initID)
    {
        InitiatorID = initID;
        settings = new SessionSettings(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fix", "initiator.cfg"));
        storeFactory = new FileStoreFactory(settings);
        logFactory = new FileLogFactory(settings);
        initiator = new SocketInitiator(
            this,
            storeFactory,
            settings,
            logFactory);
    }
    public void RunIt()
    {
        if (running) return;
        if(initiator.IsStopped)
        {
            try
            {   
                initiator.Start(); //This can throw an error due to current set up.  I would recommend making the connection,
                                   //pulling data, and then closing the connection (polling) to ensure the initiator clears the
                                   //log files
                                   //reference http://lists.quickfixn.com/pipermail/quickfixn-quickfixn.com/2013q1/000747.html
                                   //2013 issue, still unresolved...  Restart app
            }
            catch(Exception ex)
            {
                if (MessageBox.Show("Error restarting initiator.  Program will close due to file access.  This is a Quickfix bug, not an issue with this program.  Please restart." + Environment.NewLine + Environment.NewLine +
                    "Reference: http://lists.quickfixn.com/pipermail/quickfixn-quickfixn.com/2013q1/000747.html for more information.  Click ok to copy link to clipboard.  Click \"X\" to ignore.") == DialogResult.OK)
                {
                    Clipboard.SetText("http://lists.quickfixn.com/pipermail/quickfixn-quickfixn.com/2013q1/000747.html");
                }
                throw new Exception(ex.ToString());
            }
        }          
        running = true;           
    }
}

Finally, to make it stand out (this is actually in the block above as well), you construct a message similar to below, keeping in mind that your ICE Message will have certain required fields that my "TestMessage" does not. I cannot give code from production though - sorry.

public void GetTestMessage(string msgType)
    {
        if (sessionID == null) return;
        QuickFix.FIX50.TestMessage msg = new QuickFix.FIX50.TestMessage();
        msg.TestType = msgType;
        msg.Header.SetField(new QuickFix.Fields.MsgType("TEST"));
        msg.SetField(new QuickFix.Fields.StringField(CustomConstants.TEST_TYPE, msgType));
        Session.SendToTarget(msg, sessionID);
    }

The learning curve is substantial. You will just need to keep playing around until you get it. Once you get it down though, it makes sense. Stick with it. Let me know if you need anything else.

Aaron
  • 1,313
  • 16
  • 26
  • Thanks @Aaron for this. I tried to implement your suggestion and got to somewhere like Currently I am getting: MsgType = AQ and TraderRequestID = requested value but when ever I try to Get other field like Symbol or price then I am getting error **bold** 'Cracker Exception message: Field not found for tag 55.' Can you suggest me what I am missing here? also how can we use GetField to get different field from trade. Currently I am using Fix44 and QuickFix/N-v1.7.0.Thank you again and I hope you will understand the newbie. – ze-corps Nov 22 '16 at 17:44
  • Do the fields actually come in? You will get that error if the field is not sent. It is possible that the message type you are requesting doesn't include those fields. Put this before anything else in each of your "To/From" methods (FromApp, ToAdmin, etc): Console.WriteLine(msg.ToString()); You should get something like (separate comment) (continued)::: – Aaron Nov 22 '16 at 17:54
  • 8=FIXT.1.19=46035=TE34=849=TCTAcceptor5052=20161122-17:52:53.37756=BPConfInitiator501140=CompanyB1141=N1142=BPTraderGuy1143=OtherTraderGuy1144=USGC1145=DEC161146=JAN1147=FOB1148=2 Business Days1149=TEST Option1150=11151=Test Barge1152=NOV161154=BUY1155=1.331156=1609E00021157=11/22/2016 5:52:53 PM1158=11159=751160=BPAccountNum21161=TestLoc21162=JJA1163=Test Comment1164=Y1165=BP Floor Broker1166=Counter Floor Broker1167=251168=JAN1169=1.5810=204 – Aaron Nov 22 '16 at 17:54
  • Each number (look for the equal signs) represents a "Get" field. So for example, 8 means "What type of FIX", 35 is message type (TE in my case), etc. If you look in your fix dictionary, you should be able to search for "35" and cycle through until you get to the right message type, and it'll tell you what it is... First things first, find tag 55 in the 44 dictionary, and see what it is, then see if you're getting a tag 55 in your received message... It might not be there. – Aaron Nov 22 '16 at 17:57
  • 55 is Symbol, so your error message seems legitimate. Make sure you are actually receiving a 55 tag... – Aaron Nov 22 '16 at 17:58
  • I still think I am missing a big piece somewhere. to be honest, I don't know how i can get TradeCaptureReport. Can u suggest? – ze-corps Nov 22 '16 at 18:28
  • To submit trades? You need to create the message and set all of the fields that they require...They will have the necessary fields for each trade type in their documentation. QuickFix.FIX50.CustomCash customOrder = new QuickFix.FIX50.CustomCash(); customOrder.SetField(new StringField(CustomConstants.TDATE, DateTime.Now.ToString())); customOrder.Header.SetField(new MsgType("TC")); Session.SendToTarget(customOrder, sessionID); Once you send the message, you will get a response Ack – Aaron Nov 22 '16 at 18:31
  • @Arron, here is what i understood on the flow of code: I created an Initiator, Connected to WebICE, QuickFix.FIX44.TradeCaptureReportRequest and following is what i am receiving back from the application: Trade Capture Report request Ack[35 =AQ] and Trade Capture report response[35=AE]. I am able to catch the Ack message using **OnMessage(QuickFix.FIX44.TradeCaptureReportRequestAck msg, SessionID s)** but i am not able to capture Trade Capture report response. How can i get the information from Trade Capture report response i.e. something like u Posted continue:: – ze-corps Nov 22 '16 at 22:34
  • What you posted above from your console output *is* a trade response. I guarantee if you look at tag 568, that is your execution ID... That looks like an accepted trade to me... What are you missing? – Aaron Nov 22 '16 at 23:08
  • Ok, I'm going through it item by item. Double check me, length 89,TRADECAPTUREREPORTREQUESTACK,preopen,Sender is ICE, time sent is that, Target comp is 406(?), Target Sub ID is 2541,Request ID is 65001170, request type all trades, Result is success, request status is completed, and a checksum... It looks ok to me. – Aaron Nov 22 '16 at 23:24
  • Thanks @aaron, i figured my FixXML44 was faulty. – ze-corps Nov 23 '16 at 22:02