public ProtoMessage CreateExecutionEvent(ProtoOAExecutionType executionType, ProtoOAOrder order, ProtoOAPosition position = null, string reasonCode = null, string clientMsgId = null) { var _msg = ProtoOAExecutionEvent.CreateBuilder(); _msg.SetExecutionType(executionType); _msg.SetOrder(order); if (position != null) { _msg.SetPosition(position); } return(CreateMessage((uint)_msg.PayloadType, _msg.Build().ToByteString(), clientMsgId)); }
public ProtoMessage CreateExecutionEvent(ProtoOAExecutionType executionType, ProtoOAOrder order, ProtoOAPosition position = null, string reasonCode = null, string clientMsgId = null) { var _msg = new ProtoOAExecutionEvent(); _msg.executionType = executionType; _msg.order = order; if (position != null) { _msg.position = position; } if (reasonCode != null) { _msg.reasonCode = reasonCode; } return(CreateMessage((uint)_msg.payloadType, Utils.Serialize <ProtoOAExecutionEvent>(_msg), clientMsgId)); }
static string OpenApiExecEventsToString(ProtoMessage msg) { if ((ProtoOAPayloadType)msg.PayloadType != ProtoOAPayloadType.PROTO_OA_EXECUTION_EVENT) { return("ERROR in OpenApiExecutionEvents: Wrong message type"); } if (!msg.HasPayload) { return("ERROR in OpenApiExecutionEvents: Corrupted execution event, no payload found"); } var _msg = ProtoOAExecutionEvent.CreateBuilder().MergeFrom(msg.Payload).Build(); var _str = OpenApiExecutionTypeToString(_msg.ExecutionType) + "{" + OpenApiOrderToString(_msg.Order) + (_msg.HasPosition ? ", " + OpenApiPositionToString(_msg.Position) : "") + (_msg.HasErrorCode ? ", errorCode:" + _msg.ErrorCode : ""); return(_str + "}"); }
//public ProtoOASubscribeForTradingEventsReq GetSubscribeForTradingEventsRequest(byte[] msg = null) //{ // return ProtoOASubscribeForTradingEventsReq.CreateBuilder().MergeFrom(GetPayload(msg)).Build(); //} //public ProtoOASubscribeForTradingEventsRes GetSubscribeForTradingEventsResponse(byte[] msg = null) //{ // return ProtoOASubscribeForTradingEventsRes.CreateBuilder().MergeFrom(GetPayload(msg)).Build(); //} //public ProtoOAUnsubscribeFromTradingEventsReq GetUnsubscribeForTradingEventsRequest(byte[] msg = null) //{ // return ProtoOAUnsubscribeFromTradingEventsReq.CreateBuilder().MergeFrom(GetPayload(msg)).Build(); //} //public ProtoOAUnsubscribeFromTradingEventsRes GetUnsubscribeForTradingEventsResponse(byte[] msg = null) //{ // return ProtoOAUnsubscribeFromTradingEventsRes.CreateBuilder().MergeFrom(GetPayload(msg)).Build(); //} //public ProtoOAGetSubscribedAccountsReq GetAllSubscriptionsForTradingEventsRequest(byte[] msg = null) //{ // return ProtoOAGetSubscribedAccountsReq.CreateBuilder().MergeFrom(GetPayload(msg)).Build(); //} //public ProtoOAGetSubscribedAccountsRes GetAllSubscriptionsForTradingEventsResponse(byte[] msg = null) //{ // return ProtoOAGetSubscribedAccountsRes.CreateBuilder().MergeFrom(GetPayload(msg)).Build(); //} public ProtoOAExecutionEvent GetExecutionEvent(byte[] msg = null) { return(ProtoOAExecutionEvent.CreateBuilder().MergeFrom(GetPayload(msg)).Build()); }
private void Listen(SslStream sslStream) { while (!isShutdown) { //Read the message into a proto message Thread.Sleep(1); byte[] _length = new byte[sizeof(int)]; int readBytes = 0; do { Thread.Sleep(0); readBytes += sslStream.Read(_length, readBytes, _length.Length - readBytes); } while (readBytes < _length.Length); int length = BitConverter.ToInt32(_length.Reverse().ToArray(), 0); if (length <= 0) { continue; } if (length > MaxMessageSize) { string exceptionMsg = "Message length " + length.ToString() + " is out of range (0 - " + MaxMessageSize.ToString() + ")"; throw new System.IndexOutOfRangeException(); } byte[] _message = new byte[length]; readBytes = 0; do { Thread.Sleep(0); readBytes += sslStream.Read(_message, readBytes, _message.Length - readBytes); } while (readBytes < length); var msgFactory = new OpenApiMessagesFactory(); var protoMessage = msgFactory.GetMessage(_message); //recieved a msg so show View connection is still alive HeartBeatHandler?.Invoke(); if (protoMessage.PayloadType > 49 && protoMessage.PayloadType < 54) { switch ((ProtoPayloadType)protoMessage.PayloadType) { case ProtoPayloadType.ERROR_RES: ErrorHandler?.Invoke(protoMessage.ToString()); break; case ProtoPayloadType.HEARTBEAT_EVENT: //heartbeat Event HeartBeatHandler?.Invoke(); break; case ProtoPayloadType.PING_REQ: MessageHandler?.Invoke("Ping req"); break; case ProtoPayloadType.PING_RES: MessageHandler?.Invoke("Ping res"); break; } } else { //check what the message type is and perform the relevant operations switch ((ProtoOAPayloadType)protoMessage.PayloadType) { case ProtoOAPayloadType.PROTO_OA_ERROR_RES: //an error has been received var error = ProtoOAErrorRes.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); ErrorHandler?.Invoke("Proto message error " + error.ErrorCode + " " + error.Description); break; case ProtoOAPayloadType.PROTO_OA_ORDER_ERROR_EVENT: //an error with an order has been found var orderError = ProtoOAOrderErrorEvent.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); OnTradeFail?.Invoke(orderError.CtidTraderAccountId, "Trade Failed: " + orderError.ErrorCode + " " + orderError.Description); break; case ProtoOAPayloadType.PROTO_OA_EXECUTION_EVENT: var executionEvent = ProtoOAExecutionEvent.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); if (executionEvent.ExecutionType == ProtoOAExecutionType.ORDER_ACCEPTED) { if (executionEvent.Order.OrderType == ProtoOAOrderType.MARKET) { if (executionEvent.Order.ClosingOrder) { OnOrderAccepted?.Invoke(executionEvent.Order.ClientOrderId, executionEvent.Order.PositionId, true); } else { OnOrderAccepted?.Invoke(executionEvent.Order.ClientOrderId, executionEvent.Order.PositionId, false); } } else if (executionEvent.Order.OrderType == ProtoOAOrderType.STOP_LOSS_TAKE_PROFIT) { OnStopTargetAccepted?.Invoke(executionEvent.Order.ClientOrderId, executionEvent.Order.PositionId); } } else if (executionEvent.ExecutionType == ProtoOAExecutionType.ORDER_FILLED) { if (executionEvent.Order.ClosingOrder) { OnOrderFilled?.Invoke(executionEvent.Order.ClientOrderId, executionEvent.Order.PositionId, executionEvent.Order.ExecutedVolume, true); } else { OnOrderFilled?.Invoke(executionEvent.Order.ClientOrderId, executionEvent.Order.PositionId, executionEvent.Order.ExecutedVolume, false); } } else if (executionEvent.ExecutionType == ProtoOAExecutionType.ORDER_CANCELLED) { OnOrderCancelled?.Invoke(executionEvent.Order.ClientOrderId, executionEvent.Order.PositionId); } break; case ProtoOAPayloadType.PROTO_OA_ACCOUNT_AUTH_RES: //auth has been recieved for the account var auth = ProtoOAAccountAuthRes.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); OnAccountAuthorised?.Invoke(auth.CtidTraderAccountId); break; case ProtoOAPayloadType.PROTO_OA_APPLICATION_AUTH_RES: //Application has been authorised so continue the connection to get account and symbol data MessageHandler?.Invoke("App authorised."); BeginConnection(); break; case ProtoOAPayloadType.PROTO_OA_SYMBOLS_LIST_RES: //When requesting the list of all available assets var symbols = ProtoOASymbolsListRes.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); MessageHandler?.Invoke("Symbols downloaded for account " + symbols.CtidTraderAccountId); //get the associated user UserConfig config = Users.Where(x => x.Value.AccountId == symbols.CtidTraderAccountId).Select(x => x.Value).FirstOrDefault(); //store the symbols in a dictionary where the key is the id foreach (ProtoOALightSymbol symbol in symbols.SymbolList) { config.Symbols.Add(new Symbol((int)symbol.SymbolId, symbol.SymbolName)); } //Save to file so they can be easily reloaded on program restart try { config.SaveToFile(); } catch (IOException ex) //non critical so just flag an error { ErrorHandler?.Invoke("Could not save symbols list for account id " + symbols.CtidTraderAccountId + ": " + ex.Message); } //start subscribing to tick events StartSubscribes(symbols.CtidTraderAccountId); break; case ProtoOAPayloadType.PROTO_OA_SPOT_EVENT: //Tick has been recieved var details = ProtoOASpotEvent.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); //record the time of the tick in UTC time (the tick time doesn't actually come with the payload) DateTime tickTime = DateTime.UtcNow; //get the associated user UserConfig config_spot = Users.Where(x => x.Value.AccountId == details.CtidTraderAccountId).Select(x => x.Value).FirstOrDefault(); //Queue this for writing to file - queue as TickData class which also has the time at which the tick was recieved if (details.HasBid) { if (ShouldWriteTicks) { _ticksToWrite[config_spot.Token].Enqueue(new TickData((int)details.SymbolId, tickTime, true, details.Bid)); } //Notify a tick has been recieved SymbolTickHandler?.Invoke(config_spot, details.SymbolId, true, details.Bid, tickTime); } if (details.HasAsk) { if (ShouldWriteTicks) { _ticksToWrite[config_spot.Token].Enqueue(new TickData((int)details.SymbolId, tickTime, false, details.Ask)); } //Notify a tick has been recieved SymbolTickHandler?.Invoke(config_spot, details.SymbolId, false, details.Ask, tickTime); } break; case ProtoOAPayloadType.PROTO_OA_GET_ACCOUNTS_BY_ACCESS_TOKEN_RES: var accounts_list = ProtoOAGetAccountListByAccessTokenRes.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); //get the first account - we only need 1 account to extract tick data - no trading will take place ProtoOACtidTraderAccount account = accounts_list.CtidTraderAccountList.FirstOrDefault(); //assign the account id that will be used to extract ticks (Users are stored as a dictionary with token as the key) if (account != null) { Users[accounts_list.AccessToken].AccountId = (long)account.CtidTraderAccountId; } else { throw new MissingFieldException("There are no trading accounts associated with this token."); } MessageHandler?.Invoke("Account selected: " + account.CtidTraderAccountId); //Save to file so it can be easily reloaded on program restart try { Config.SaveToFile(); } catch (IOException ex) //non critical so just flag an error { ErrorHandler?.Invoke("Could not save config file with updated account id: " + ex.Message); } //get the symbols available to this account AuthAccount(accounts_list.AccessToken); break; case ProtoOAPayloadType.PROTO_OA_SUBSCRIBE_SPOTS_RES: var spotRes = ProtoOASubscribeSpotsRes.CreateBuilder().MergeFrom(protoMessage.Payload).Build(); break; default: ErrorHandler?.Invoke((ProtoOAPayloadType)protoMessage.PayloadType + " message not handled."); break; } ; } } }
private void OnExecutionEvent(ProtoOAExecutionEvent executionEvent) { testOrderId = executionEvent.Order.OrderId; testPositionId = executionEvent.Position.PositionId; }
private void ProcessExecutionEvent(ProtoOAExecutionEvent args) { if (args.ctidTraderAccountId != CtidTraderAccount) { return; } switch (args.executionType) { case ProtoOAExecutionType.OrderAccepted: { if (args.Order.closingOrder) { if (Positions.ContainsKey(args.Position.positionId)) { Positions.Remove(args.Position.positionId); } } else { switch (args.Order.orderType) { case ProtoOAOrderType.Limit: case ProtoOAOrderType.Stop: case ProtoOAOrderType.StopLimit: Orders[args.Order.orderId] = args.Order; break; case ProtoOAOrderType.Market: case ProtoOAOrderType.MarketRange: case ProtoOAOrderType.StopLossTakeProfit: break; default: throw new ArgumentOutOfRangeException(); } } break; } case ProtoOAExecutionType.OrderFilled: { if (Orders.ContainsKey(args.Order.orderId)) { Orders.Remove(args.Order.orderId); } switch (args.Position.positionStatus) { case ProtoOAPositionStatus.PositionStatusOpen: { Positions[args.Position.positionId] = args.Position; break; } case ProtoOAPositionStatus.PositionStatusClosed: { if (Positions.ContainsKey(args.Position.positionId)) { Positions.Remove(args.Position.positionId); } break; } case ProtoOAPositionStatus.PositionStatusCreated: { Positions[args.Position.positionId] = args.Position; break; } case ProtoOAPositionStatus.PositionStatusError: break; default: throw new ArgumentOutOfRangeException(); } break; } case ProtoOAExecutionType.OrderReplaced: { Orders[args.Order.orderId] = args.Order; break; } case ProtoOAExecutionType.OrderCancelled: case ProtoOAExecutionType.OrderExpired: { if (Orders.ContainsKey(args.Order.orderId)) { Orders.Remove(args.Order.orderId); } break; } case ProtoOAExecutionType.OrderPartialFill: case ProtoOAExecutionType.OrderCancelRejected: { Orders[args.Order.orderId] = args.Order; Positions[args.Position.positionId] = args.Position; break; } case ProtoOAExecutionType.OrderRejected: case ProtoOAExecutionType.BonusDepositWithdraw: case ProtoOAExecutionType.DepositWithdraw: case ProtoOAExecutionType.Swap: { break; } default: throw new ArgumentOutOfRangeException(); } }
static string OpenApiMessageToString(ProtoMessage msg) { switch ((ProtoOAPayloadType)msg.PayloadType) { case ProtoOAPayloadType.PROTO_OA_APPLICATION_AUTH_REQ: var app_auth_req = ProtoOAApplicationAuthReq.CreateBuilder().MergeFrom(msg.Payload).Build(); return("AppAuthRequest{clientId:" + app_auth_req.ClientId + ", clientSecret:" + app_auth_req.ClientSecret + "}"); case ProtoOAPayloadType.PROTO_OA_APPLICATION_AUTH_RES: return("ApAuthResponse"); case ProtoOAPayloadType.PROTO_OA_ACCOUNT_AUTH_REQ: var acc_auth_req = ProtoOAAccountAuthReq.CreateBuilder().MergeFrom(msg.Payload).Build(); return("AccAuthRequest{CtidTraderAccountId:" + acc_auth_req.CtidTraderAccountId + "}"); case ProtoOAPayloadType.PROTO_OA_ACCOUNT_AUTH_RES: return("AccAuthResponse"); case ProtoOAPayloadType.PROTO_OA_GET_ACCOUNTS_BY_ACCESS_TOKEN_REQ: return("GetAccountsByAccessTokenReq"); case ProtoOAPayloadType.PROTO_OA_GET_ACCOUNTS_BY_ACCESS_TOKEN_RES: var accounts_list = ProtoOAGetAccountListByAccessTokenRes.CreateBuilder().MergeFrom(msg.Payload).Build(); var sbAccounts = new StringBuilder(); foreach (var account in accounts_list.CtidTraderAccountList) { sbAccounts.Append("ID: " + account.CtidTraderAccountId + (account.IsLive ? " Status: Live" + Environment.NewLine : " Status: Demo " + Environment.NewLine)); } return("GetAccountsByAccessTokenRes{" + sbAccounts.ToString() + "}"); case ProtoOAPayloadType.PROTO_OA_TRADER_REQ: return("PotoOATraderReq"); case ProtoOAPayloadType.PROTO_OA_SYMBOLS_LIST_REQ: return("GetSymbolsList"); case ProtoOAPayloadType.PROTO_OA_SYMBOLS_LIST_RES: var symbols_list = ProtoOASymbolsListRes.CreateBuilder().MergeFrom(msg.Payload).Build(); var sbSymbols = new StringBuilder(); foreach (var symbol in symbols_list.SymbolList) { sbSymbols.Append("ID: " + symbol.SymbolId + Environment.NewLine); sbSymbols.Append("Name: " + symbol.SymbolName + Environment.NewLine); } return("Symbols{" + sbSymbols.ToString() + "}"); case ProtoOAPayloadType.PROTO_OA_EXECUTION_EVENT: return(OpenApiExecEventsToString(msg)); case ProtoOAPayloadType.PROTO_OA_DEAL_LIST_REQ: return("DealListRequest{}"); case ProtoOAPayloadType.PROTO_OA_DEAL_LIST_RES: var deal_list = ProtoOADealListRes.CreateBuilder().MergeFrom(msg.Payload).Build(); var sbDeals = new StringBuilder(); foreach (var deal in deal_list.DealList) { sbDeals.Append("ID: " + deal.DealId + Environment.NewLine); sbDeals.Append("Status: " + deal.DealStatus + Environment.NewLine); sbDeals.Append("Volume: " + deal.Volume + Environment.NewLine); } return("DealList{" + sbDeals.ToString() + "}"); case ProtoOAPayloadType.PROTO_OA_RECONCILE_REQ: return("ReconcileRequest{}"); case ProtoOAPayloadType.PROTO_OA_RECONCILE_RES: var reconcile_response = ProtoOAReconcileRes.CreateBuilder().MergeFrom(msg.Payload).Build(); var sbReconcile = new StringBuilder(); foreach (var order in reconcile_response.OrderList) { sbReconcile.Append("ID: " + order.OrderId + Environment.NewLine); sbReconcile.Append("Status: " + order.OrderStatus + Environment.NewLine); sbReconcile.Append("Volume: " + order.TradeData.Volume + Environment.NewLine); } foreach (var position in reconcile_response.PositionList) { sbReconcile.Append("ID: " + position.HasPositionId + Environment.NewLine); sbReconcile.Append("Status: " + position.PositionStatus + Environment.NewLine); sbReconcile.Append("Volume: " + position.TradeData.Volume + Environment.NewLine); } return("ReconcileList{" + sbReconcile.ToString() + "}"); case ProtoOAPayloadType.PROTO_OA_CASH_FLOW_HISTORY_LIST_REQ: return("CashFlowHistoryRequest{}"); case ProtoOAPayloadType.PROTO_OA_CASH_FLOW_HISTORY_LIST_RES: var cashflow_history = ProtoOACashFlowHistoryListRes.CreateBuilder().MergeFrom(msg.Payload).Build(); var sbDCashflow = new StringBuilder(); foreach (var entry in cashflow_history.DepositWithdrawList) { sbDCashflow.Append("ID: " + entry.BalanceHistoryId + Environment.NewLine); sbDCashflow.Append("Type: " + entry.OperationType + Environment.NewLine); sbDCashflow.Append("Delta: " + entry.Delta + Environment.NewLine); } return("CashFlowHistory{" + sbDCashflow.ToString() + "}"); case ProtoOAPayloadType.PROTO_OA_GET_TRENDBARS_REQ: return("GetTrendbarsRequest{}"); case ProtoOAPayloadType.PROTO_OA_GET_TRENDBARS_RES: var trendbar = ProtoOAGetTrendbarsRes.CreateBuilder().MergeFrom(msg.Payload).Build(); var sbTrendbar = new StringBuilder(); foreach (var entry in trendbar.TrendbarList) { sbTrendbar.Append("Open: " + entry.DeltaOpen + Environment.NewLine); sbTrendbar.Append("High: " + entry.DeltaHigh + Environment.NewLine); sbTrendbar.Append("Low: " + entry.Low + Environment.NewLine); sbTrendbar.Append("Close: " + entry.DeltaClose + Environment.NewLine); } return("Trendbars{" + sbTrendbar.ToString() + "}"); case ProtoOAPayloadType.PROTO_OA_GET_TICKDATA_REQ: return("GetTickDataRequest{}"); case ProtoOAPayloadType.PROTO_OA_GET_TICKDATA_RES: var tickData = ProtoOAGetTickDataRes.CreateBuilder().MergeFrom(msg.Payload).Build(); var sbTickData = new StringBuilder(); foreach (var entry in tickData.TickDataList) { sbTickData.Append("Tick: " + entry.Tick + Environment.NewLine); } return("Tick Data{" + sbTickData.ToString() + "}"); case ProtoOAPayloadType.PROTO_OA_CANCEL_ORDER_REQ: return("CancelOrderRequest{}"); case ProtoOAPayloadType.PROTO_OA_NEW_ORDER_REQ: var exev = ProtoOAExecutionEvent.CreateBuilder().MergeFrom(msg.Payload).Build(); return("CreateOrderRequest{}"); case ProtoOAPayloadType.PROTO_OA_CLOSE_POSITION_REQ: return("ClosePositionRequest{}"); case ProtoOAPayloadType.PROTO_OA_AMEND_ORDER_REQ: return("AmendOrderRequest{}"); case ProtoOAPayloadType.PROTO_OA_AMEND_POSITION_SLTP_REQ: return("AmendPositionRequest{}"); case ProtoOAPayloadType.PROTO_OA_SUBSCRIBE_SPOTS_REQ: return("SubscribeForSpotsRequest{}"); case ProtoOAPayloadType.PROTO_OA_SUBSCRIBE_SPOTS_RES: return("SubscribeForSpotsResponse{}"); case ProtoOAPayloadType.PROTO_OA_UNSUBSCRIBE_SPOTS_REQ: return("UnsubscribeFromSpotsRequest{}"); case ProtoOAPayloadType.PROTO_OA_UNSUBSCRIBE_SPOTS_RES: return("UnsubscribeFromSpotsResponse{}"); case ProtoOAPayloadType.PROTO_OA_SPOT_EVENT: var _spot_event = ProtoOASpotEvent.CreateBuilder().MergeFrom(msg.Payload).Build(); return("SpotEvent{symbolId:" + _spot_event.SymbolId + ", bidPrice:" + (_spot_event.HasBid ? _spot_event.Bid.ToString() : " ") + ", askPrice:" + (_spot_event.HasAsk ? _spot_event.Ask.ToString() : " ") + "}"); case ProtoOAPayloadType.PROTO_OA_ERROR_RES: var _err = ProtoOAErrorRes.CreateBuilder().MergeFrom(msg.Payload).Build(); return("ErrorResponse{errorCode:" + _err.ErrorCode + (_err.HasDescription ? ", description:" + _err.Description : "") + "}"); case ProtoOAPayloadType.PROTO_OA_ORDER_ERROR_EVENT: var _orderErr = ProtoOAOrderErrorEvent.CreateBuilder().MergeFrom(msg.Payload).Build(); return("OrderErrorResponse{errorCode:" + _orderErr.ErrorCode + (_orderErr.HasDescription ? ", description:" + _orderErr.Description : "") + "}"); default: return("unknown"); } }
private void Process_Execution_Event() { ProtoOAExecutionEvent args = Serializer.Deserialize <ProtoOAExecutionEvent>(_processorMemoryStream); if (args.Order != null) { string executionEvent = "ProtoOAExecutionEvent::Order:: " + $"ctidTraderAccountId: {args.ctidTraderAccountId}; " + $"executionType: {args.executionType}; " + $"isServerEvent: {args.isServerEvent}; " + $"errorCode: {args.errorCode}; " + $"depositWithdraw: {args.depositWithdraw}; " + $"Order: [orderId: {args.Order.orderId}; " + $"positionId: {args.Order.positionId}; " + $"closingOrder: {args.Order.closingOrder}; " + $"clientOrderId: {args.Order.clientOrderId}; " + $"orderType: {args.Order.orderType}; " + $"orderStatus: {args.Order.orderStatus}; " + $"executedVolume: {args.Order.executedVolume}; " + $"executionPrice: {args.Order.executionPrice}; " + $"limitPrice: {args.Order.limitPrice}; " + $"stopPrice: {args.Order.stopPrice}; " + $"stopLoss: {args.Order.stopLoss}; " + $"takeProfit: {args.Order.takeProfit}; " + $"relativeStopLoss: {args.Order.relativeStopLoss}; " + $"relativeTakeProfit: {args.Order.relativeTakeProfit}; " + $"trailingStopLoss: {args.Order.trailingStopLoss}; " + $"baseSlippagePrice: {args.Order.baseSlippagePrice}; " + $"slippageInPoints: {args.Order.slippageInPoints}; " + $"isStopOut: {args.Order.isStopOut}; " + $"timeInForce: {args.Order.timeInForce}; " + $"tradeData.symbolId: {args.Order.tradeData.symbolId} " + $"({TradingAccounts[args.ctidTraderAccountId].TradingSymbols[args.Order.tradeData.symbolId].LightSymbol.symbolName}); " + $"tradeData.tradeSide: {args.Order.tradeData.tradeSide}; " + $"tradeData.Volume: {args.Order.tradeData.Volume}; " + $"tradeData.Label: {args.Order.tradeData.Label}; " + $"tradeData.guaranteedStopLoss: {args.Order.tradeData.guaranteedStopLoss}; " + $"tradeData.openTimestamp: {args.Order.tradeData.openTimestamp} ({EpochToString(args.Order.tradeData.openTimestamp)}); " + $"expirationTimestamp: {args.Order.expirationTimestamp} ({EpochToString(args.Order.expirationTimestamp)}); " + $"stopTriggerMethod: {args.Order.stopTriggerMethod}]"; Log.Info(executionEvent); } if (args.Position != null) { string executionEvent = "ProtoOAExecutionEvent::Position:: " + $"ctidTraderAccountId: {args.ctidTraderAccountId}; " + $"executionType: {args.executionType}; " + $"isServerEvent: {args.isServerEvent}; " + $"errorCode: {args.errorCode}; " + $"depositWithdraw: {args.depositWithdraw}; " + $"Position: [positionId: {args.Position.positionId}; " + $"positionStatus: {args.Position.positionStatus}; " + $"Price: {args.Position.Price}; " + $"stopLoss: {args.Position.stopLoss}; " + $"takeProfit: {args.Position.takeProfit}; " + $"Swap: {args.Position.Swap}; " + $"Commission: {args.Position.Commission}; " + $"mirroringCommission: {args.Position.mirroringCommission}; " + $"marginRate: {args.Position.marginRate}; " + $"usedMargin: {args.Position.usedMargin}; " + $"guaranteedStopLoss: {args.Position.guaranteedStopLoss}; " + $"tradeData.openTimestamp: {args.Position.tradeData.openTimestamp} ({EpochToString(args.Position.tradeData.openTimestamp)}); " + $"tradeData.symbolId: {args.Position.tradeData.symbolId} " + $"({TradingAccounts[args.ctidTraderAccountId].TradingSymbols[args.Position.tradeData.symbolId].LightSymbol.symbolName}); " + $"tradeData.tradeSide: {args.Position.tradeData.tradeSide}; " + $"tradeData.Volume: {args.Position.tradeData.Volume}; " + $"tradeData.guaranteedStopLoss: {args.Position.tradeData.guaranteedStopLoss}; " + $"tradeData.Label: {args.Position.tradeData.Label}; " + $"stopLossTriggerMethod: {args.Position.stopLossTriggerMethod}; " + $"utcLastUpdateTimestamp: {args.Position.utcLastUpdateTimestamp} ({EpochToString(args.Position.utcLastUpdateTimestamp)})]"; Log.Info(executionEvent); } if (args.Deal != null) { string executionEvent = "ProtoOAExecutionEvent::Deal:: " + $"ctidTraderAccountId: {args.ctidTraderAccountId}; " + $"executionType: {args.executionType}; " + $"isServerEvent: {args.isServerEvent}; " + $"errorCode: {args.errorCode}; " + $"depositWithdraw: {args.depositWithdraw}; " + $"Deal: [dealId: {args.Deal.dealId}; " + $"dealStatus: {args.Deal.dealStatus}; " + $"positionId: {args.Deal.positionId}; " + $"orderId: {args.Deal.orderId}; " + $"symbolId: {args.Deal.symbolId} " + $"({TradingAccounts[args.ctidTraderAccountId].TradingSymbols[args.Deal.symbolId].LightSymbol.symbolName}); " + $"tradeSide: {args.Deal.tradeSide}; " + $"Volume: {args.Deal.Volume}; " + $"filledVolume: {args.Deal.filledVolume}; " + $"executionPrice: {args.Deal.executionPrice}; " + $"createTimestamp: {args.Deal.createTimestamp} ({EpochToString(args.Deal.createTimestamp)}); " + $"executionTimestamp: {args.Deal.executionTimestamp} ({EpochToString(args.Deal.executionTimestamp)}); " + $"Commission: {args.Deal.Commission}; " + $"marginRate: {args.Deal.marginRate}; " + $"baseToUsdConversionRate: {args.Deal.baseToUsdConversionRate}; " + $"utcLastUpdateTimestamp: {args.Deal.utcLastUpdateTimestamp} ({EpochToString(args.Deal.utcLastUpdateTimestamp)})]"; if (args.Deal.closePositionDetail != null) { executionEvent += $"closePositionDetail.Balance: {args.Deal.closePositionDetail.Balance}; " + $"closePositionDetail.balanceVersion: {args.Deal.closePositionDetail.balanceVersion}; " + $"closePositionDetail.entryPrice: {args.Deal.closePositionDetail.entryPrice}; " + $"closePositionDetail.closedVolume: {args.Deal.closePositionDetail.closedVolume}; " + $"closePositionDetail.Commission: {args.Deal.closePositionDetail.Commission}; " + $"closePositionDetail.Swap: {args.Deal.closePositionDetail.Swap}; " + $"closePositionDetail.grossProfit: {args.Deal.closePositionDetail.grossProfit}; " + $"closePositionDetail.quoteToDepositConversionRate: {args.Deal.closePositionDetail.quoteToDepositConversionRate}; "; } Log.Info(executionEvent); } if (args.bonusDepositWithdraw != null) { string executionEvent = "ProtoOAExecutionEvent::bonusDepositWithdraw:: " + $"ctidTraderAccountId: {args.ctidTraderAccountId}; " + $"executionType: {args.executionType}; " + $"isServerEvent: {args.isServerEvent}; " + $"errorCode: {args.errorCode}; " + $"depositWithdraw: {args.depositWithdraw}; " + $"bonusDepositWithdraw.operationType: {args.bonusDepositWithdraw.operationType}; " + $"bonusDepositWithdraw.bonusHistoryId: {args.bonusDepositWithdraw.bonusHistoryId}; " + $"bonusDepositWithdraw.changeBonusTimestamp: {args.bonusDepositWithdraw.changeBonusTimestamp} " + $"({EpochToString(args.bonusDepositWithdraw.changeBonusTimestamp)}); " + $"bonusDepositWithdraw.externalNote: {args.bonusDepositWithdraw.externalNote}; " + $"bonusDepositWithdraw.ibBonus: {args.bonusDepositWithdraw.ibBonus}; " + $"bonusDepositWithdraw.ibDelta: {args.bonusDepositWithdraw.ibDelta}; " + $"bonusDepositWithdraw.managerBonus: {args.bonusDepositWithdraw.managerBonus}; " + $"bonusDepositWithdraw.managerDelta: {args.bonusDepositWithdraw.managerDelta}; " + $"bonusDepositWithdraw.introducingBrokerId: {args.bonusDepositWithdraw.introducingBrokerId}; " + $"bonusDepositWithdraw.externalNote: {args.bonusDepositWithdraw.externalNote}"; Log.Info(executionEvent); } OnExecutionEventReceived?.Invoke(args); }