Exemple #1
0
        public Tuple <Order, bool, bool> ProcessOrderMessage(Security security, ExecutionMessage message)
        {
            if (security == null)
            {
                throw new ArgumentNullException("security");
            }

            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (message.Error != null)
            {
                throw new ArgumentException(LocalizedStrings.Str714Params.PutEx(message));
            }

            bool isNew;

            var transactionId = message.TransactionId;

            if (transactionId == 0)
            {
                // ExecMsg.OriginalTransactionId == OrderStatMsg.TransactionId when orders info requested by OrderStatMsg
                transactionId = _orderStatusTransactions.Contains(message.OriginalTransactionId) ? 0 : message.OriginalTransactionId;
            }

            var securityData = _cache.GetData(security);

            var orderInfo = GetOrderInfo(securityData, message.OrderType, transactionId, message.OrderId, message.OrderStringId, trId =>
            {
                var o = EntityFactory.CreateOrder(security, message.OrderType, trId);

                o.Time        = message.ServerTime;
                o.Price       = message.Price;
                o.Volume      = message.Volume ?? 0;
                o.Direction   = message.Side;
                o.Comment     = message.Comment;
                o.ExpiryDate  = message.ExpiryDate;
                o.Condition   = message.Condition;
                o.UserOrderId = message.UserOrderId;
                o.Portfolio   = message.PortfolioName.IsEmpty()
                                        ? _portfolios.FirstOrDefault().Value
                                        : ProcessPortfolio(message.PortfolioName).Item1;

                return(o);
            }, out isNew, true);

            var order       = orderInfo.Item1;
            var isCancelled = orderInfo.Item2;
            //var isReReregisterCancelled = orderInfo.Item3;
            var raiseNewOrder = orderInfo.Item3;

            var isPending = order.State == OrderStates.Pending;
            //var isPrevIdSet = (order.Id != null || !order.StringId.IsEmpty());

            bool isChanged;

            if (order.State == OrderStates.Done)
            {
                // данные о заявке могут приходить из маркет-дата и транзакционного адаптеров
                isChanged = false;
                //throw new InvalidOperationException("Изменение заявки в состоянии Done невозможно.");
            }
            else
            {
                if (message.OrderId != null)
                {
                    order.Id = message.OrderId.Value;
                }

                if (!message.OrderStringId.IsEmpty())
                {
                    order.StringId = message.OrderStringId;
                }

                if (!message.OrderBoardId.IsEmpty())
                {
                    order.BoardId = message.OrderBoardId;
                }

                //// некоторые коннекторы не транслируют при отмене отмененный объем
                //// esper. при перерегистрации заявок необходимо обновлять баланс
                //if (message.Balance > 0 || !isCancelled || isReReregisterCancelled)
                //{
                //	// BTCE коннектор не транслирует баланс заявки
                //	if (!(message.OrderState == OrderStates.Active && message.Balance == 0))
                //		order.Balance = message.Balance;
                //}

                if (message.Balance != null)
                {
                    order.Balance = message.Balance.Value;
                }

                // IB коннектор не транслирует состояние заявки в одном из своих сообщений
                if (message.OrderState != null)
                {
                    order.State = message.OrderState.Value;
                }

                if (order.Time == DateTimeOffset.MinValue)
                {
                    order.Time = message.ServerTime;
                }

                // для новых заявок используем серверное время,
                // т.к. заявка получена первый раз и не менялась
                // ServerTime для заявки - это время регистрации
                order.LastChangeTime = isNew ? message.ServerTime : message.LocalTime;
                order.LocalTime      = message.LocalTime;

                //нулевой объем может быть при перерегистрации
                if (order.Volume == 0 && message.Volume != null)
                {
                    order.Volume = message.Volume.Value;
                }

                if (message.Commission != null)
                {
                    order.Commission = message.Commission;
                }

                if (message.TimeInForce != null)
                {
                    order.TimeInForce = message.TimeInForce.Value;
                }

                if (isPending)
                {
                    if (order.State != OrderStates.Pending && message.Latency != null)
                    {
                        order.LatencyRegistration = message.Latency.Value;
                    }
                }
                else if (isCancelled && order.State == OrderStates.Done)
                {
                    if (message.Latency != null)
                    {
                        order.LatencyCancellation = message.Latency.Value;
                    }
                }

                isChanged = true;
            }

            //if (isNew || (!isPrevIdSet && (order.Id != null || !order.StringId.IsEmpty())))
            //{

            // так как биржевые идентифиаторы могут повторяться, то переписываем старые заявки новыми как наиболее актуальными

            if (order.Id != null)
            {
                securityData.OrdersById[order.Id.Value] = order;
                _cache.AllOrdersById[order.Id.Value]    = order;
            }

            if (!order.StringId.IsEmpty())
            {
                securityData.OrdersByStringId[order.StringId] = order;
                _cache.AllOrdersByStringId[order.StringId]    = order;
            }

            //}

            //if (message.OrderType == OrderTypes.Conditional && (message.DerivedOrderId != null || !message.DerivedOrderStringId.IsEmpty()))
            //{
            //	var derivedOrder = GetOrder(security, 0L, message.DerivedOrderId ?? 0, message.DerivedOrderStringId);

            //	if (order == null)
            //		_orderStopOrderAssociations.Add(Tuple.Create(message.DerivedOrderId ?? 0, message.DerivedOrderStringId), new RefPair<Order, Action<Order, Order>>(order, (s, o) => s.DerivedOrder = o));
            //	else
            //		order.DerivedOrder = derivedOrder;
            //}

            message.CopyExtensionInfo(order);

            return(Tuple.Create(order, raiseNewOrder, isChanged));
        }
Exemple #2
0
        public IEnumerable <Tuple <Order, bool, bool> > ProcessOrderMessage(Order order, Security security, ExecutionMessage message, long transactionId, out Tuple <Portfolio, bool, bool> pfInfo)
        {
            if (security == null)
            {
                throw new ArgumentNullException(nameof(security));
            }

            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (message.Error != null)
            {
                throw new ArgumentException(LocalizedStrings.Str714Params.PutEx(message));
            }

            var securityData = GetData(security);

            if (transactionId == 0 && message.OrderId == null && message.OrderStringId.IsEmpty())
            {
                throw new ArgumentException(LocalizedStrings.Str719);
            }

            pfInfo = null;

            var orders = securityData.Orders;

            if (transactionId == 0)
            {
                var info = orders.CachedValues.FirstOrDefault(i =>
                {
                    if (order != null)
                    {
                        return(i.Order == order);
                    }

                    if (message.OrderId != null)
                    {
                        return(i.Order.Id == message.OrderId);
                    }
                    else
                    {
                        return(i.Order.StringId.CompareIgnoreCase(message.OrderStringId));
                    }
                });

                if (info == null)
                {
                    return(null);
                    //throw new InvalidOperationException(LocalizedStrings.Str1156Params.Put(orderId.To<string>() ?? orderStringId));
                }

                var orderInfo = info.ApplyChanges(message, false);
                UpdateOrderIds(info.Order, securityData);
                return(new[] { orderInfo });
            }
            else
            {
                var cancelKey   = CreateOrderKey(message.OrderType, transactionId, true);
                var registerKey = CreateOrderKey(message.OrderType, transactionId, false);

                var cancelledInfo  = orders.TryGetValue(cancelKey);
                var registetedInfo = orders.TryGetValue(registerKey);

                // проверяем не отмененная ли заявка пришла
                if (cancelledInfo != null)                 // && (cancelledOrder.Id == orderId || (!cancelledOrder.StringId.IsEmpty() && cancelledOrder.StringId.CompareIgnoreCase(orderStringId))))
                {
                    var cancellationOrder = cancelledInfo.Order;

                    if (registetedInfo == null)
                    {
                        var i = cancelledInfo.ApplyChanges(message, true);
                        UpdateOrderIds(cancellationOrder, securityData);
                        return(new[] { i });
                    }

                    var retVal     = new List <Tuple <Order, bool, bool> >();
                    var orderState = message.OrderState;

                    if (orderState != null && cancellationOrder.State != OrderStates.Done && orderState != OrderStates.None && orderState != OrderStates.Pending)
                    {
                        cancellationOrder.State = cancellationOrder.State.CheckModification(OrderStates.Done);

                        if (message.Latency != null)
                        {
                            cancellationOrder.LatencyCancellation = message.Latency.Value;
                        }

                        retVal.Add(Tuple.Create(cancellationOrder, false, true));
                    }

                    var isCancelOrder = (message.OrderId != null && message.OrderId == cancellationOrder.Id) ||
                                        (message.OrderStringId != null && message.OrderStringId == cancellationOrder.StringId) ||
                                        (message.OrderBoardId != null && message.OrderBoardId == cancellationOrder.BoardId);

                    var regOrder = registetedInfo.Order;

                    if (!isCancelOrder)
                    {
                        var replacedInfo = registetedInfo.ApplyChanges(message, false);
                        UpdateOrderIds(regOrder, securityData);
                        retVal.Add(replacedInfo);
                    }

                    return(retVal);
                }

                if (registetedInfo == null)
                {
                    var o = EntityFactory.CreateOrder(security, message.OrderType, registerKey.Item1);

                    if (o == null)
                    {
                        throw new InvalidOperationException(LocalizedStrings.Str720Params.Put(registerKey.Item1));
                    }

                    o.Time        = message.ServerTime;
                    o.Price       = message.OrderPrice;
                    o.Volume      = message.OrderVolume ?? 0;
                    o.Direction   = message.Side;
                    o.Comment     = message.Comment;
                    o.ExpiryDate  = message.ExpiryDate;
                    o.Condition   = message.Condition;
                    o.UserOrderId = message.UserOrderId;
                    o.ClientCode  = message.ClientCode;
                    o.BrokerCode  = message.BrokerCode;

                    if (message.PortfolioName.IsEmpty())
                    {
                        o.Portfolio = _portfolios.FirstOrDefault().Value;
                    }
                    else
                    {
                        pfInfo      = ProcessPortfolio(message.PortfolioName);
                        o.Portfolio = ProcessPortfolio(message.PortfolioName).Item1;
                    }

                    if (o.ExtensionInfo == null)
                    {
                        o.ExtensionInfo = new Dictionary <object, object>();
                    }

                    AddOrder(o);
                    _allOrdersByTransactionId.Add(Tuple.Create(transactionId, false), o);

                    registetedInfo = new OrderInfo(o);
                    orders.Add(registerKey, registetedInfo);
                }

                var orderInfo = registetedInfo.ApplyChanges(message, false);

                if (orderInfo != null)
                {
                    UpdateOrderIds(registetedInfo.Order, securityData);
                    return(new[] { orderInfo });
                }
                else
                {
                    return(Enumerable.Empty <Tuple <Order, bool, bool> >());
                }
            }
        }