Esempio n. 1
0
        private async void Handle(ExecutionReport msg)
        {
            var    clOrderId     = msg.ClOrdID.Obj;
            string origClOrderId = null;

            if (msg.IsSetOrigClOrdID())
            {
                origClOrderId = msg.OrigClOrdID.Obj;
            }

            var state = msg.IsSetOrdStatus() ? ConvertOrderState(msg.OrdStatus) : null;
            var price = msg.IsSetPrice() ? msg.Price.Obj : (decimal?)null;

            price = price != 0M ? price : null;
            var qty             = msg.IsSetOrderQty() ? (uint)msg.OrderQty.Obj : (uint?)null;
            var filledQty       = msg.IsSetLastQty() ? (uint)msg.LastQty.Obj : (uint?)null;
            var activeQty       = msg.IsSetLeavesQty() ? (uint)msg.LeavesQty.Obj : (uint?)null;
            var time            = msg.IsSetTransactTime() ? ParseTransactTime() : DateTime.Now;
            var orderExchangeId = msg.IsSetOrderID() ? msg.OrderID.Obj : null;

            var transactionId = _orders.GetOrCreateOrderTransactionId(origClOrderId ?? clOrderId);

            var oscm = new OrderStateChangeMessage
            {
                TransactionId   = transactionId,
                State           = state,
                Price           = price,
                Quantity        = qty,
                FilledQuantity  = filledQty,
                ActiveQuantity  = activeQty,
                ChangeTime      = time,
                OrderExchangeId = orderExchangeId
            };

            switch (msg.ExecType.Obj)
            {
            case ExecType.NEW:
                _newOrderTransactions.Accept(clOrderId);
                _orders.SaveOrderExchangeId(transactionId, orderExchangeId);
                SendMessage(oscm);
                break;

            case ExecType.TRADE:
                _newOrderTransactions.Accept(clOrderId);
                _orders.SaveOrderExchangeId(transactionId, orderExchangeId);

                SendMessage(oscm);
                await EmitFillAsync();

                if (oscm.State == OrderState.Filled)
                {
                    _newOrderTransactions.Forget(transactionId);
                    _killOrderTransactions.Forget(msg.ClOrdID.Obj);
                    _orders.ForgetOrder(transactionId);
                }
                break;

            case ExecType.FILL:
                _newOrderTransactions.Accept(clOrderId);

                _orders.SaveOrderExchangeId(transactionId, orderExchangeId);
                SendMessage(oscm);
                await EmitFillAsync();

                if (oscm.State == OrderState.Filled)
                {
                    _newOrderTransactions.Forget(transactionId);
                    _killOrderTransactions.Forget(msg.ClOrdID.Obj);
                    _orders.ForgetOrder(transactionId);
                }
                break;

            case ExecType.PARTIAL_FILL:
                _newOrderTransactions.Accept(clOrderId);
                _orders.SaveOrderExchangeId(transactionId, orderExchangeId);
                SendMessage(oscm);
                await EmitFillAsync();

                break;

            case ExecType.REJECTED:
                string rejectReason;
                switch (msg.OrdRejReason.Obj)
                {
                case OrdRejReason.UNKNOWN_SYMBOL:
                    rejectReason = "Unknown symbol";
                    break;

                case OrdRejReason.EXCHANGE_CLOSED:
                    rejectReason = "Exchange closed";
                    break;

                case OrdRejReason.ORDER_EXCEEDS_LIMIT:
                    rejectReason = "Order exceeds limit";
                    break;

                case OrdRejReason.DUPLICATE_ORDER:
                    rejectReason = "Duplicate order";
                    break;

                default:
                    rejectReason = $"#{msg.OrdRejReason.Obj}";
                    break;
                }
                if (!string.IsNullOrEmpty(msg.Text?.Obj))
                {
                    rejectReason = $"{rejectReason}. {msg.Text?.Obj}";
                }
                _newOrderTransactions.Reject(clOrderId, rejectReason);
                _orders.ForgetOrder(transactionId);
                break;

            case ExecType.PENDING_CANCEL:
                _killOrderTransactions.Accept(msg.ClOrdID.Obj);
                SendMessage(oscm);
                break;

            case ExecType.CANCELED:
                _killOrderTransactions.Accept(msg.ClOrdID.Obj);
                _newOrderTransactions.Forget(transactionId);
                _killOrderTransactions.Forget(msg.ClOrdID.Obj);
                _orders.ForgetOrder(transactionId);
                SendMessage(oscm);
                break;

            case ExecType.PENDING_REPLACE:
                _modifyOrderTransactions.Accept(clOrderId);
                break;

            case ExecType.REPLACED:
                _newOrderTransactions.Forget(origClOrderId);
                _killOrderTransactions.Forget(clOrderId);
                _orders.UpdateOrderParams(
                    orderExchangeId: orderExchangeId,
                    origClOrderId: origClOrderId,
                    clOrderId: clOrderId,
                    symbol: msg.Symbol.Obj,
                    qty: msg.OrderQty.Obj,
                    side: msg.Side.Obj);

                SendMessage(oscm);
                break;

            default:
                _Log.Warn().PrintFormat("Unknown ExecType: {0}", msg.ExecType.Obj);
                break;
            }

            OrderState?ConvertOrderState(OrdStatus field)
            {
                switch (field.Obj)
                {
                case OrdStatus.PENDING_NEW: return(OrderState.New);

                case OrdStatus.NEW: return(OrderState.Active);

                case OrdStatus.CANCELED: return(OrderState.Cancelled);

                case OrdStatus.FILLED: return(OrderState.Filled);

                case OrdStatus.PARTIALLY_FILLED: return(OrderState.PartiallyFilled);

                case OrdStatus.REJECTED: return(OrderState.Error);

                case OrdStatus.PENDING_CANCEL: return(null);

                case OrdStatus.PENDING_REPLACE: return(null);

                default:
                    _Log.Warn().PrintFormat("Unknown OrdStatus: {0}", field.Obj);
                    return(null);
                }
            }

            DateTime ParseTransactTime()
            {
                var maxLen = "20170912-09:39:57.2761221".Length;

                var str = msg.GetString(60 /*TransactTime*/);

                if (str.Length > maxLen)
                {
                    str = str.Substring(0, maxLen);
                }
                var t = DateTime.ParseExact(str, "yyyyMMdd-HH:mm:ss.fffffff", null, DateTimeStyles.AssumeUniversal);

                return(t);
            }

            async Task EmitFillAsync()
            {
                if (!msg.IsSetSecondaryExecID())
                {
                    return;
                }

                var fillExchangeId = msg.SecondaryExecID.Obj;
                var fillPrice      = msg.IsSetLastPx() ? msg.LastPx.Obj : (decimal?)null;

                price = price != 0M ? price : null;
                var fillQty = msg.IsSetLastQty() ? (uint)msg.LastQty.Obj : (uint?)null;

                if (fillPrice == null || fillQty == null)
                {
                    return;
                }

                Instrument instrument;

                try
                {
                    instrument = await _settings.InstrumentConverter.ResolveSymbolAsync(this, msg.Symbol.Obj);
                }
                catch (Exception e)
                {
                    _Log.Error().Print(e, $"Failed to resolve instrument {msg.Symbol.Obj}");
                    return;
                }

                var fill = new FillMessage
                {
                    Price           = fillPrice.Value,
                    Quantity        = fillQty.Value,
                    DateTime        = time,
                    Instrument      = instrument,
                    Account         = msg.Account.Obj,
                    Operation       = msg.Side.Obj == Side.BUY ? OrderOperation.Buy : OrderOperation.Sell,
                    ExchangeId      = fillExchangeId,
                    ExchangeOrderId = orderExchangeId
                };

                SendMessage(fill);
            }
        }
Esempio n. 2
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);
            }
        }