private OrderModified GenerateOrderModifiedEvent(ExecutionReport message)
        {
            var orderId       = this.GetOrderId(message);
            var orderIdBroker = new OrderIdBroker(message.GetField(Tags.OrderID));
            var orderType     = FxcmMessageHelper.GetOrderType(message.GetField(Tags.OrdType));
            var quantity      = message.IsSetField(Tags.LeavesQty)
                ? Quantity.Create(message.GetDecimal(Tags.LeavesQty))
                : Quantity.Create(message.GetDecimal(Tags.OrderQty));
            var price        = FxcmMessageHelper.GetOrderPrice(orderType, message);
            var modifiedTime = FxcmMessageHelper.ParseTimestamp(message.GetField(Tags.TransactTime));

            return(new OrderModified(
                       this.accountId,
                       orderId,
                       orderIdBroker,
                       quantity,
                       price,
                       modifiedTime,
                       this.NewGuid(),
                       this.TimeNow()));
        }
        public void OnMessage(ExecutionReport message)
        {
            Debug.NotNull(this.tradingGateway, nameof(this.tradingGateway));

            switch (message.OrdStatus.Obj)
            {
            case OrdStatus.REJECTED:
            {
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.REJECTED)})");

                this.tradingGateway?.Send(this.GenerateOrderRejectedEvent(message));
                break;
            }

            case OrdStatus.PENDING_NEW:
            {
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.PENDING_NEW)}).");

                // Do nothing
                break;
            }

            case OrdStatus.NEW:
            {
                var fxcmOrdStatus = message.GetField(FxcmTags.OrdStatus);
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.NEW)}-{fxcmOrdStatus})");

                switch (fxcmOrdStatus)
                {
                case "P":         // In Process
                    this.tradingGateway?.Send(this.GenerateOrderAcceptedEvent(message));
                    this.tradingGateway?.Send(this.GenerateOrderWorkingEvent(message));
                    break;

                case "I":         // Dealer Intervention
                    this.tradingGateway?.Send(this.GenerateOrderAcceptedEvent(message));
                    this.tradingGateway?.Send(this.GenerateOrderWorkingEvent(message));
                    break;

                case "W":         // Waiting (conditional order inactive state)
                    if (message.IsSetField(Tags.SecondaryOrderID))
                    {
                        // Accepted Conditional Order
                        this.tradingGateway?.Send(this.GenerateOrderAcceptedEvent(message));
                    }
                    else
                    {
                        // Working Primary Order
                        this.tradingGateway?.Send(this.GenerateOrderWorkingEvent(message));
                    }

                    break;

                default:
                    this.Logger.LogError(LogId.Network, $"Cannot process event (FXCMOrdStatus {fxcmOrdStatus} not recognized).");
                    break;
                }

                break;
            }

            case OrdStatus.PENDING_CANCEL:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.PENDING_CANCEL)}).");
#endif

                // Do nothing
                break;
            }

            case OrdStatus.CANCELED:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.CANCELED)})");
#endif

                this.tradingGateway?.Send(this.GenerateOrderCancelledEvent(message));
                break;
            }

            case OrdStatus.REPLACED:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.REPLACED)})");
#endif

                this.tradingGateway?.Send(this.GenerateOrderModifiedEvent(message));
                break;
            }

            case OrdStatus.EXPIRED:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.EXPIRED)})");
#endif

                this.tradingGateway?.Send(this.GenerateOrderExpiredEvent(message));
                break;
            }

            case OrdStatus.STOPPED:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.STOPPED)}).");
#endif

                // Order is executing
                break;
            }

            case OrdStatus.FILLED:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.FILLED)})");
#endif

                this.tradingGateway?.Send(this.GenerateOrderFilledEvent(message));
                break;
            }

            case OrdStatus.PARTIALLY_FILLED:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.PARTIALLY_FILLED)})");
#endif

                this.tradingGateway?.Send(this.GenerateOrderPartiallyFilledEvent(message));
                break;
            }

            case OrdStatus.SUSPENDED:
            {
                this.Logger.LogError(LogId.Network, $"{Received}{Fix} Unhandled {nameof(ExecutionReport)}({nameof(OrdStatus.SUSPENDED)}).");
                break;
            }

            case OrdStatus.CALCULATED:
            {
                this.Logger.LogError(LogId.Network, $"{Received}{Fix} Unhandled {nameof(ExecutionReport)}({nameof(OrdStatus.CALCULATED)}).");
                break;
            }

            case OrdStatus.DONE_FOR_DAY:
            {
#if DEBUG
                this.Logger.LogDebug(LogId.Network, $"{Received}{Fix} {nameof(ExecutionReport)}({nameof(OrdStatus.DONE_FOR_DAY)}).");
#endif

                this.tradingGateway?.Send(this.GenerateOrderExpiredEvent(message));
                break;
            }

            case OrdStatus.PENDING_REPLACE:
            {
                this.Logger.LogError(LogId.Network, $"{Received}{Fix} Unhandled {nameof(ExecutionReport)}({nameof(OrdStatus.PENDING_REPLACE)}).");
                break;
            }

            case OrdStatus.ACCEPTED_FOR_BIDDING:
            {
                this.Logger.LogError(LogId.Network, $"{Received}{Fix} Unhandled {nameof(ExecutionReport)}({nameof(OrdStatus.ACCEPTED_FOR_BIDDING)}).");
                break;
            }

            default:
                throw ExceptionFactory.InvalidSwitchArgument(message.OrdStatus, nameof(message.OrdStatus));
            }
        }
Exemple #3
0
        private bool _er_Update(ExecutionReport er, FixOrderStatus ordS, string desc, string bolsa)
        {
            try
            {
                int account;
                if (bolsa.Equals(ExchangePrefixes.BOVESPA, StringComparison.InvariantCultureIgnoreCase))
                {
                    string acc = er.Account.getValue();
                    acc     = (acc.Remove(acc.Length - 1));
                    account = Convert.ToInt32(acc);
                }
                else
                {
                    account = Convert.ToInt32(er.Account.getValue());
                }

                // Buscar Ordem Original, de algum jeito!!!
                // 1a. tentativa: Tentar via ExchangeNumber
                // 2a. tentativa: Tentar via ClOrdID e OrigClOrdID
                // 3a. tentativa: Tentar via ClOrdID no tb_fix_order_update e buscar a ordem pelo OrderID
                // 4a. tentativa: ahhh foda-se, nao achou mesmo

                OrderDbInfo orderOrig = null;

                // 1a. tentativa
                if (er.IsSetOrderID() && !er.OrderID.getValue().Equals("NONE"))
                {
                    orderOrig = _db.BuscarOrdemPorExchangeNumber(er.OrderID.getValue());
                }
                // 2a. Tentativa
                if (null == orderOrig || orderOrig.OrderID == 0)
                {
                    orderOrig = _db.BuscarOrdem(er.ClOrdID.getValue(), account, er.Symbol.getValue());
                    if (orderOrig.OrderID == 0)
                    {
                        // Se ordem nao encontrada, entao procurar pelo OrigClOrdID
                        if (er.IsSetOrigClOrdID())
                        {
                            orderOrig = _db.BuscarOrdem(er.OrigClOrdID.getValue(), account, er.Symbol.getValue());
                            if (orderOrig.OrderID == 0)
                            {
                                orderOrig = _db.BuscarOrdem(er.OrigClOrdID.getValue(), account, er.Symbol.getValue(), true);
                                //if (orderOrig.OrderID == 0)
                                //{
                                //    logger.Info("01 ER - Nao achou a ordem em questao!!!: " + er.OrigClOrdID.getValue() + " Status: " + ordS.ToString() + " Desc: " + desc);
                                //    return false;
                                //}
                            }
                            else
                            {
                                orderOrig = _db.BuscarOrdem(er.OrigClOrdID.getValue(), account, er.Symbol.getValue());
                            }
                        }
                        else
                        {
                            orderOrig = _db.BuscarOrdem(er.ClOrdID.getValue(), account, er.Symbol.getValue(), true);
                            //if (orderOrig.OrderID == 0)
                            //{
                            //    logger.Info("02 ER - Nao achou a ordem em questao!!!: " + er.ClOrdID.getValue() + " Status: " + ordS.ToString() + " Desc: " + desc);
                            //    return false;
                            //}
                        }
                    }
                }

                // 3a. Tentativa
                if (null == orderOrig || orderOrig.OrderID == 0)
                {
                    // Buscar a partir de tb_fix_order_update
                    OrderDbUpdateInfo orderUpdate = _db.BuscarOrdemUpdate(er.ClOrdID.getValue());
                    // Buscar ordem original a partir do order ID
                    if (orderUpdate.OrderID != 0)
                    {
                        orderOrig = _db.BuscarOrdemPorOrderID(orderUpdate.OrderID);
                    }
                    else
                    {
                        logger.Info("01 ER - Nao achou a ordem em questao!!!: " + er.ClOrdID.getValue() + " Status: " + ordS.ToString() + " Desc: " + desc);
                        return(false);
                    }
                }
                if (null == orderOrig || orderOrig.OrderID == 0)
                {
                    logger.Info("02 ER - Nao achou a ordem em questao!!!: " + er.ClOrdID.getValue() + " Status: " + ordS.ToString() + " Desc: " + desc);
                    return(false);
                }
                //}
                //else
                //{
                //    orderOrig = _db.BuscarOrdemPorExchangeNumber(er.OrderID.getValue());
                //    if (orderOrig.OrderID == 0)
                //    {
                //        logger.Info("ER - Nao achou a ordem em questao via exchange number (OrderID ER)!!!: " + er.OrderID.getValue() + " Status: " + ordS.ToString() + " Desc: " + desc);
                //        return false;
                //    }
                // }
                // Adicionar OrdemDetalhe
                OrderDbDetalheInfo detail = new OrderDbDetalheInfo();
                detail.OrderID       = orderOrig.OrderID;
                detail.TransactID    = er.ExecID.getValue();
                detail.OrderQty      = Convert.ToInt32(er.OrderQty.getValue());
                detail.Price         = er.IsSetField(Tags.Price) ? er.Price.getValue() : Decimal.Zero;
                detail.OrderStatusID = (int)ordS;
                detail.TransactTime  = er.TransactTime.getValue();
                if (er.IsSetField(Tags.Text))
                {
                    detail.Description = desc + " - " + er.Text.getValue();
                }
                else
                {
                    detail.Description = desc;
                }

                detail.TradeQty     = er.IsSetField(Tags.LastQty) ? Convert.ToInt32(er.LastQty.getValue()) : 0;
                detail.CumQty       = er.IsSetField(Tags.CumQty) ? Convert.ToInt32(er.CumQty.getValue()) : 0;
                detail.FixMsgSeqNum = Convert.ToInt32(er.Header.GetField(Tags.MsgSeqNum));
                if (!_db.InserirOrdemDetalhe(detail, orderOrig.ClOrdID))
                {
                    logger.Info("Erro ao inserir o registro na tabela tb_fix_order_update");
                    return(false);
                }

                // Atualizar Ordem
                orderOrig.ExchangeNumberID = er.OrderID.getValue();
                orderOrig.OrdStatus        = (int)ordS;
                orderOrig.TransactTime     = er.TransactTime.getValue();
                // orderOrig.ClOrdID = er.ClOrdID.getValue();
                // if (er.IsSetOrigClOrdID())
                //    orderOrig.OrigClOrdID = er.OrigClOrdID.getValue();
                if (er.IsSetField(Tags.LeavesQty))
                {
                    orderOrig.OrderQtyRemaining = Convert.ToInt32(er.LeavesQty.getValue());
                }
                if (er.IsSetField(Tags.CumQty))
                {
                    orderOrig.CumQty = Convert.ToInt32(er.CumQty.getValue());
                }
                orderOrig.Memo = er.IsSetField(Tags.Memo) ? er.GetField(Tags.Memo): string.Empty;
                if (!_db.AtualizarOrdem(orderOrig))
                {
                    logger.Info("Problemas na atualizacao da ordem. ClOrdID: " + orderOrig.ClOrdID);
                    return(false);
                }

                DropCopyCallbackManager.Instance.EnqueueCallback(orderOrig);

                return(true);
            }
            catch (Exception ex)
            {
                logger.Error("_er_Update: Erro na atualizacao dos status da ordem: " + ex.Message, ex);
                return(false);
            }
        }
Exemple #4
0
 /// <summary>
 /// Returns the order expiry time if the given FIX message contains the tag (else null).
 /// </summary>
 /// <param name="message">The execution report FIX message.</param>
 /// <returns>A <see cref="decimal"/>.</returns>
 public static ZonedDateTime?GetExpireTime(ExecutionReport message)
 {
     return(message.IsSetField(Tags.ExpireTime)
         ? ParseTimestamp(message.GetField(Tags.ExpireTime))
         : null);
 }
Exemple #5
0
        /// <summary>
        /// Validar os estados da ordem e executar as respectivas operacoes no dicionario de mensagens
        /// (Mensagens de Execution Report - ER)
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="eType"></param>
        /// <param name="oStatus"></param>
        /// <param name="dic"></param>
        /// Retorna o TOORderSession referente ao Execution Report
        /// OBS: strChave - no momento esta considerando sempre clOrdID
        public void VerifyOrderSituationER(ExecutionReport msg, char e, char o, SessionID ss,
                                           OrderSessionManager dic, string strChave, out TOOrderSession ord)

        {
            ord = null;
            try
            {
                string strOrigClChave     = string.Empty;
                string strExchNumberChave = msg.OrderID.ToString() + "-" + msg.Account.ToString() + "-" + msg.Symbol.ToString();
                if (null != ss)// Registry found
                {
                    // Atualiza o TO com o ExchangeNumber (Tag 37, order ID)
                    TOOrderSession aux = null;
                    dic.GetOrder(strChave, out aux);
                    if (null != aux)
                    {
                        aux.ExchangeNumberID = strExchNumberChave;
                    }

                    // New Order, Exec: New, OrdStatus: New - nao faz nada, somente retorna o TOOrderSession correspondente
                    if (e == ExecType.NEW && o == OrdStatus.NEW)
                    {
                        // Por ser new order, nao se aplica fazer busca pelo exchange number id
                        // pois ainda não foi atualizado
                        dic.GetOrder(strChave, out ord);
                        //ord.ExchangeNumberID = msg.OrderID.getValue() + "-" + msg.Account.getValue() + "-" + msg.Symbol.getValue();
                    }
                    // Retornar o TOOrderSession correspondente para
                    if (o == OrdStatus.FILLED || o == OrdStatus.PARTIALLY_FILLED)
                    {
                        dic.GetOrder(strChave, out ord, strExchNumberChave);
                        //ord.ExchangeNumberID = msg.OrderID.getValue() + "-" + msg.Account.getValue() + "-" + msg.Symbol.getValue();
                    }

                    // Stop Order Entry, Exec: New, OrdStatus: New - nao faz nada
                    // No request stop order trigger, Exec: New, OrdStatus: New - nao faz nada
                    // Order with on close, Exec: New, OrdStatus: New
                    // Order with on close attribute is activated when the closing auction starts, Exec: New, Order: New
                    // MinQty order entry, not enough quantity, Exec: new, Order: new

                    // New Order, Exec: Rejected, OrdStatus: Rejected - excluir a chave
                    // New Order, Exec: Suspended, OrdStatus: Suspended
                    // No request, Exec: Trade, OrdStatus: Filled
                    if ((e == ExecType.REJECTED && o == OrdStatus.REJECTED) ||
                        (e == ExecType.SUSPENDED && o == OrdStatus.SUSPENDED) ||
                        (e == ExecType.TRADE && o == OrdStatus.FILLED) ||
                        (e == ExecType.EXPIRED && o == OrdStatus.EXPIRED))
                    {
                        lock (dic)
                        {
                            TOOrderSession toOS = null;
                            int            ret  = dic.GetOrder(strChave, out toOS, strExchNumberChave);
                            ord  = toOS;
                            toOS = null;
                            if (ret == FindType.EXCHANGE_NUMBER)
                            {
                                dic.RemoveOrder(ord.ChaveDicionario);
                            }
                            else
                            {
                                dic.RemoveOrder(strChave);
                            }
                        }
                    }
                    // Order Modify, Exec: Replace, OrdStatus: Replaced
                    if (e == ExecType.REPLACE && o == OrdStatus.REPLACED)
                    {
                        strOrigClChave = msg.OrigClOrdID.ToString() + "-" + msg.Account.ToString() + "-" + msg.Symbol.ToString();
                        lock (dic)
                        {
                            //if (dic.ExistOrder(strOrigClChave))
                            //{
                            TOOrderSession toOS = null;
                            int            ret  = dic.GetOrder(strOrigClChave, out toOS, strExchNumberChave, KeyType.ORIGCLORDID);
                            ord  = toOS;
                            toOS = null;
                            if (ret == FindType.EXCHANGE_NUMBER)
                            {
                                dic.RemoveOrder(ord.ChaveDicionario);
                            }
                            else
                            {
                                dic.RemoveOrder(strOrigClChave);
                            }
                            //}
                        }
                    }
                    // Cancelation, Exec: Cancelled, OrdStatus: Cancelled
                    // No request FAK Partially Filled, Exec: Canceled, OrdStatus: Canceled
                    // No request FOK Partially Filled, Exec: Canceled, OrdStatus: Canceled
                    // MinQty order entry, not enough quantity  rejected, Exec: Cancelled, Order: Cancelled
                    if (e == ExecType.CANCELED && o == OrdStatus.CANCELED)
                    {
                        bool processOrig = true;
                        // Tratamento de outros tipos de timeinforce (para execucao e cancelamento, o orig clord id não é fornecido)
                        if (msg.IsSetField(Tags.TimeInForce))
                        {
                            switch (msg.TimeInForce.getValue())
                            {
                            case TimeInForce.IMMEDIATE_OR_CANCEL:
                            case TimeInForce.FILL_OR_KILL:
                                processOrig    = false;
                                strOrigClChave = msg.ClOrdID.ToString() + "-" + msg.Account.ToString() + "-" + msg.Symbol.ToString();
                                break;

                            default:
                            {
                                // Caso o cancelamento tenha partido da bolsa, tambem nao eh fornecido o OrigClOrdID
                                // entao tenta-se utilizar o ClOrdID vindo do ExecutionReport
                                string aux1 = msg.IsSetOrigClOrdID() ? msg.OrigClOrdID.ToString() : msg.ClOrdID.ToString();
                                strOrigClChave = aux1 + "-" + msg.Account.ToString() + "-" + msg.Symbol.ToString();
                            }
                            break;
                            }
                        }
                        else
                        {
                            // TimeInForce = 0 (DAY) - Default
                            // Caso o Orig nao esteja na mensagem, tenta-se buscar pelo ClOrdID
                            string aux1 = msg.IsSetOrigClOrdID() ? msg.OrigClOrdID.ToString() : msg.ClOrdID.ToString();
                            strOrigClChave = aux1 + "-" + msg.Account.ToString() + "-" + msg.Symbol.ToString();
                        }
                        lock (dic)
                        {
                            TOOrderSession toOS = null;
                            int            ret  = 0;
                            ret = dic.GetOrder(strOrigClChave, out toOS, strExchNumberChave, KeyType.ORIGCLORDID);
                            if (null != toOS)
                            {
                                ord  = toOS;
                                toOS = null;
                                if (ret == FindType.EXCHANGE_NUMBER)
                                {
                                    dic.RemoveOrder(ord.ChaveDicionario);
                                }
                                else
                                {
                                    dic.RemoveOrder(strOrigClChave);
                                }
                            }
                            if (processOrig)
                            {
                                ret = dic.GetOrder(strChave, out toOS, strExchNumberChave);
                                if (ret == FindType.EXCHANGE_NUMBER)
                                {
                                    dic.RemoveOrder(toOS.ChaveDicionario);
                                }
                                else
                                {
                                    dic.RemoveOrder(strChave);
                                }
                                toOS = null;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error("VerifyOrderSituationER(): " + ex.Message, ex);
            }
        }