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;
                    }
                    ;
                }
            }
        }
Beispiel #6
0
        private void OnExecutionEvent(ProtoOAExecutionEvent executionEvent)
        {
            testOrderId = executionEvent.Order.OrderId;

            testPositionId = executionEvent.Position.PositionId;
        }
Beispiel #7
0
        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();
            }
        }
Beispiel #8
0
        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);
        }