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> >()); } } }
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)); }
private Portfolio GetPortfolio(string name) { return(!name.IsEmpty() ? ProcessPortfolio(name).Item1 : _portfolios.FirstOrDefault().Value); }