Monitor Order Execution Using Events Handling (O2GO, CS)
From FxCodeBaseWiki
This is a sample of order execution processing using events handling. The structure of the sample is as follows:
- An order is created (in this sample it is an Open Market order created using the OpenTrade method).
- In events handlers, information about the received order execution events is printed and saved into the helper OrderExecutionState structure.
- 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 |
---|