Monitor Order Execution Using Events Handling (O2GO, CS)

From FxCodeBaseWiki
Jump to: navigation, search

This is a sample of order execution processing using events handling. The structure of the sample is as follows:

  1. An order is created (in this sample it is an Open Market order created using the OpenTrade method).
  2. In events handlers, information about the received order execution events is printed and saved into the helper OrderExecutionState structure.
  3. In the main thread, wait until the order is completely executed and show the result of the order execution.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using FXCore;

namespace OrderExecution
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Init

            if (args.Length < 2)
            {
                Console.WriteLine("usage: sample.OrderExecution.exe user password [URL Connection]");
                return;
            }
            string url = args.Length > 2 ? args[2] : "http://www.fxcorporate.com";
            string connection = args.Length > 3 ? args[3] : "Demo";

            //create an o2go object and log in                
            mCore = new FXCore.CoreAut();
            mDesk = (FXCore.TradeDeskAut)mCore.CreateTradeDesk("trader");
            mDesk.Login(args[0], args[1], url, connection);
      
            //subscribe to events
            TradeDeskEventsSinkClass sink = new FXCore.TradeDeskEventsSinkClass();
            ITradeDeskEvents_OnRowAddedExEventHandler funcRowAddedEx = new FXCore.ITradeDeskEvents_OnRowAddedExEventHandler(OnAddRowEx);
            sink.ITradeDeskEvents_Event_OnRowAddedEx += funcRowAddedEx;
            ITradeDeskEvents_OnRowChangedExEventHandler funcRowChangedEx = new FXCore.ITradeDeskEvents_OnRowChangedExEventHandler(OnChangeRowEx);
            sink.ITradeDeskEvents_Event_OnRowChangedEx += funcRowChangedEx;
            ITradeDeskEvents_OnRowBeforeRemoveExEventHandler funcRowBeforeRemoveEx = new FXCore.ITradeDeskEvents_OnRowBeforeRemoveExEventHandler(OnRemoveRowEx);
            sink.ITradeDeskEvents_Event_OnRowBeforeRemoveEx += funcRowBeforeRemoveEx;
            int SubscriptionToken = mDesk.Subscribe(sink);

            //collect all required information
            FXCore.TableAut acct = (FXCore.TableAut)mDesk.FindMainTable("accounts");
            FXCore.TableAut offer = (FXCore.TableAut)mDesk.FindMainTable("offers");
            string instrument = (string)offer.CellValue(1, "Instrument");
            string account_id = (string)acct.CellValue(1, "AccountID");
            FXCore.TradingSettingsProviderAut tradingSettings = (FXCore.TradingSettingsProviderAut)mDesk.TradingSettingsProvider;
            int amount = tradingSettings.GetMinQuantity(instrument, account_id);

            #endregion
          
            //open a trade
            object order_id, di;
            mDesk.OpenTrade(account_id, instrument, true, amount, 0, null, 0, 0, 0, 0, out order_id, out di);
            //wait until the order is executed or cancelled
            WaitOrderExecute((string)order_id);
            ShowExecutionResult((string)order_id);

            #region Finalize

            //finalize
            sink.ITradeDeskEvents_Event_OnRowAddedEx -= funcRowAddedEx;
            sink.ITradeDeskEvents_Event_OnRowChangedEx -= funcRowChangedEx;
            sink.ITradeDeskEvents_Event_OnRowBeforeRemoveEx -= funcRowBeforeRemoveEx;            
            mDesk.Unsubscribe(SubscriptionToken);
            mDesk.Logout();

            #endregion
        }

        #region events handlers

        /// The handler of the row change.
        static public void OnChangeRowEx(object tableDisp, string rowID, string extInfo)
        {
            FXCore.ITableAut table = tableDisp as FXCore.ITableAut;
            if (table.Type == "orders")
            {
                //log the event
                Console.WriteLine("Change order: {0}.", DescribeOrder(extInfo));

                //retrieve the order info
                ParserAut parser = (ParserAut)mDesk.GetParser();
                parser.ParseEventRow(extInfo, "orders");
                string status = (string)parser.GetValue("FixStatus");
                int orig_qty = (int)parser.GetValue("OriginQTY");
                int filled_qty = (int)parser.GetValue("FilledQTY");
                int remain_qty = (int)parser.GetValue("Lot");
                string order_id = rowID;

                //check whether the order is executed or rejected/cancelled
                OrderExecutionState state = GetOrderState(order_id);
                bool finish = false;
                if (status == "F")
                {
                    finish = true;
                    Console.WriteLine("The order is executed.");
                }
                else if (status == "R")
                {
                    finish = true;
                    //check whether the order is rejected completely or partially
                    if (orig_qty == remain_qty)
                        Console.WriteLine("The order is rejected completely.");
                    else
                        Console.WriteLine("The order is rejected partially({0} of {1}).", remain_qty, orig_qty);

                    //Save information about the order execution                    
                    OrderExecutionPart exec = new OrderExecutionPart();
                    exec.Type = OrderExecutionType.Reject;
                    exec.Amount = remain_qty;
                    state.Parts.Add(exec);
                }
                else if (status == "C")
                {
                    finish = true;
                    //check whether the order is cancelled completely or partially
                    if (orig_qty == remain_qty)
                        Console.WriteLine("The order is cancelled completely.");
                    else
                        Console.WriteLine("The order is cancelled partially({0} of {1}).", remain_qty, orig_qty);

                    //Save information about the order execution                    
                    OrderExecutionPart exec = new OrderExecutionPart();
                    exec.Type = OrderExecutionType.Cancel;
                    exec.Amount = remain_qty;
                    state.Parts.Add(exec);
                }

                if (finish)
                    state.Complete = true;
            }
        }

        /// The handler of the row adding.
        static public void OnAddRowEx(object tableDisp, string rowID, string extInfo)
        {
            FXCore.ITableAut table = tableDisp as FXCore.ITableAut;
            if (table.Type == "orders")
                Console.WriteLine("New order: {0}.", DescribeOrder(extInfo));
            else if (table.Type == "trades")
            {
                Console.WriteLine("New open position: {0}.", DescribeTrade(extInfo));

                //Save information about the order execution
                ParserAut parser = (ParserAut)mDesk.GetParser();
                parser.ParseEventRow(extInfo, "trades");
                OrderExecutionState state = GetOrderState((string)parser.GetValue("OpenOrderID"));
                OrderExecutionPart exec = new OrderExecutionPart();
                exec.Type = OrderExecutionType.OpenTrade;
                exec.TradeID = rowID;
                exec.Amount = (int)parser.GetValue("Lot");
                state.Parts.Add(exec);
            }
            else if (table.Type == "closed trades")
            {
                //Save information about the order execution
                ParserAut parser = (ParserAut)mDesk.GetParser();
                parser.ParseEventRow(extInfo, "closed trades");
                OrderExecutionState state = GetOrderState((string)parser.GetValue("CloseOrderID"));
                OrderExecutionPart exec = new OrderExecutionPart();
                exec.Type = OrderExecutionType.CloseTrade;
                exec.TradeID = rowID;
                exec.Amount = (int)parser.GetValue("Lot");
                state.Parts.Add(exec);
            }
        }

        /// The handler of the row removing.
        static public void OnRemoveRowEx(object tableDisp, string rowID, string extInfo)
        {
            FXCore.ITableAut table = tableDisp as FXCore.ITableAut;
            if (table.Type == "orders")
                Console.WriteLine("Remove order: {0}.", DescribeOrder(extInfo));
            else if (table.Type == "trades")            
                Console.WriteLine("Remove open position: {0}.", DescribeTrade(extInfo));                            
        }

        //A helper method: format the sting with the event description
        static string DescribeOrder(string extInfo)
        {
            ParserAut parser = (ParserAut)mDesk.GetParser();
            parser.ParseEventRow(extInfo, "orders");
            return string.Format("OrderID = {0}, FixStatus = {1}, Lot = {2}, OriginQTY = {3}, FilledQTY = {4}, TradeID= {5}",
                    parser.GetValue("OrderID"), parser.GetValue("FixStatus"), parser.GetValue("Lot"),
                    parser.GetValue("OriginQTY"), parser.GetValue("FilledQTY"), parser.GetValue("TradeID"));
        }

        //A helper method: format the string with the event description
        static string DescribeTrade(string extInfo)
        {
            ParserAut parser = (ParserAut)mDesk.GetParser();
            parser.ParseEventRow(extInfo, "trades");
            return string.Format("TradeID = {0}, OpenOrderID = {1}, Lot= {2}",
                parser.GetValue("TradeID"), parser.GetValue("OpenOrderID"), parser.GetValue("Lot"));
        }

        #endregion

        #region Helper structures and methods to work with order execution info

        static void ShowExecutionResult(string order_id)
        {
            Console.WriteLine("===================================================");
            Console.WriteLine("Result information about order {0} execution", order_id);
            Console.WriteLine("===================================================");

            OrderExecutionState state = GetOrderState(order_id);
            Console.WriteLine("The order is executed in {0} parts:", state.Parts.Count);
            for (int i = 0; i < state.Parts.Count; i++)
            {
                OrderExecutionPart part = state.Parts[i];
                switch (part.Type)
                {
                    case OrderExecutionType.OpenTrade:
                        Console.WriteLine("{0}. Trade {1} with amount {2} is opened.", i + 1, part.TradeID, part.Amount);
                        break;
                    case OrderExecutionType.CloseTrade:
                        Console.WriteLine("{0}. Trade {1} with amount {2} is closed.", i + 1, part.TradeID, part.Amount);
                        break;
                    case OrderExecutionType.Reject:
                        Console.WriteLine("{0}. Amount {1} is rejected.", i + 1, part.Amount);
                        break;
                    case OrderExecutionType.Cancel:
                        Console.WriteLine("{0}. Amount {1} is cancelled.", i + 1, part.Amount);
                        break;
                }
            }            
        }

        /// Wait until the order is executed or removed (cancelled).                
        static bool WaitOrderExecute(string order_id)
        {
            long start_time = DateTime.Now.Ticks;
            FXCore.TableAut orders = (FXCore.TableAut)mDesk.FindMainTable("orders");
            while ((DateTime.Now.Ticks - start_time) < 6000000000)
            {
                try
                {
                    OrderExecutionState state = GetOrderState(order_id);
                    if (state.Complete)
                        return true;
                    Thread.Sleep(250);
                }
                catch (Exception)
                {
                    return true;
                }
            }

            Console.WriteLine("10 minute timeout to wait for the trade expired");
            return false;
        }

        // Get the current order state
        static OrderExecutionState GetOrderState(string order_id)
        {
            OrderExecutionState state;
            if (!mOrdersExecution.TryGetValue(order_id, out state))
            {
                state = new OrderExecutionState();
                mOrdersExecution[order_id] = state;
            }
            return state;                   
        }

        /// Describe the part of the order execution, i.e. the opened/closed trade or reject.        
        struct OrderExecutionPart
        {
            public OrderExecutionType Type;
            public string TradeID;
            public int Amount;
        };

        enum OrderExecutionType
        {
            OpenTrade,
            CloseTrade,
            Reject, 
            Cancel
        };

        // Describe the current state of the order execution.
        class OrderExecutionState
        {
            public bool Complete = false;
            public List<OrderExecutionPart> Parts = new List<OrderExecutionPart>();
        };

        static Dictionary<string, OrderExecutionState> mOrdersExecution = new Dictionary<string, OrderExecutionState>();        

        #endregion        

        static FXCore.CoreAut mCore;
        static FXCore.TradeDeskAut mDesk;  
    }       
}

This Article in Other Languages

Language: English  • español