/// <summary> /// To get the reason for cancelling order in orders log. /// </summary> /// <param name="item">Order log item.</param> /// <returns>The reason for order cancelling in order log.</returns> public static OrderLogCancelReasons GetOrderLogCancelReason(this ExecutionMessage item) { if (!item.IsOrderLogCanceled()) { throw new ArgumentException(LocalizedStrings.Str937, nameof(item)); } if (item.OrderStatus == null) { throw new ArgumentException(LocalizedStrings.Str938, nameof(item)); } var status = item.OrderStatus.Value; if (status.HasBits(0x100000)) { return(OrderLogCancelReasons.ReRegistered); } else if (status.HasBits(0x200000)) { return(OrderLogCancelReasons.Canceled); } else if (status.HasBits(0x400000)) { return(OrderLogCancelReasons.GroupCanceled); } else if (status.HasBits(0x800000)) { return(OrderLogCancelReasons.CrossTrade); } else { throw new ArgumentOutOfRangeException(nameof(item), status, LocalizedStrings.Str939); } }
/// <summary> /// Добавить новую строчку из лога заявок к стакану. /// </summary> /// <param name="item">Строчка лога заявок.</param> /// <returns>Был ли изменен стакан.</returns> public bool Update(ExecutionMessage item) { if (item == null) { throw new ArgumentNullException("item"); } if (item.ExecutionType != ExecutionTypes.OrderLog) { throw new ArgumentException("item"); } var changed = false; try { // Очистить стакан в вечерний клиринг if (item.ServerTime.TimeOfDay >= _clearingBeginTime) { // Garic - переделал // Очищаем только в рабочие дни поскольку в субботу/воскресенье допустима отмена заявок if (_lastUpdateTime != null && _lastUpdateTime.Value.TimeOfDay < _clearingBeginTime && _exchange.WorkingTime.IsTradeDate(item.ServerTime.LocalDateTime, true)) { _depth.ServerTime = item.ServerTime; _depth.Bids = Enumerable.Empty <QuoteChange>(); _depth.Asks = Enumerable.Empty <QuoteChange>(); _matchingOrder = null; changed = true; } } _lastUpdateTime = item.ServerTime.LocalDateTime; if (!item.IsSystem || item.TradePrice != 0 || item.Price == 0 /* нулевая цена может появится при поставке опционов */) { return(changed); } if (item.IsOrderLogRegistered()) { changed = TryApplyTrades(null); if ( (item.Side == Sides.Buy && (_depth.Asks.IsEmpty() || item.Price < _depth.Asks.First().Price)) || (item.Side == Sides.Sell && (_depth.Bids.IsEmpty() || item.Price > _depth.Bids.First().Price)) ) { if (item.TimeInForce == TimeInForce.PutInQueue) { var quotes = (item.Side == Sides.Buy ? _bids : _asks); var quote = quotes.TryGetValue(item.Price); if (quote == null) { quote = new QuoteChange { Side = item.Side, Price = item.Price, Volume = item.Volume, }; quotes.Add(item.Price, quote); if (item.Side == Sides.Buy) { _depth.Bids = GetArray(quotes); } else { _depth.Asks = GetArray(quotes); } } else { quote.Volume += item.Volume; } changed = true; } } else { _matchingOrder = (ExecutionMessage)item.Clone(); // mika // из-за того, что могут быть кросс-сделки, матчинг только по заявкам невозможен // (сначала идет регистрация вглубь стакана, затем отмена по причине кросс-сделки) // http://forum.rts.ru/viewtopic.asp?t=24197 // } } else if (item.IsOrderLogCanceled()) { var isSame = _matchingOrder != null && _matchingOrder.OrderId == item.OrderId; changed = TryApplyTrades(item); if (!isSame && item.TimeInForce == TimeInForce.PutInQueue) { // http://forum.rts.ru/viewtopic.asp?t=24197 if (item.GetOrderLogCancelReason() != OrderLogCancelReasons.CrossTrade) { var quotes = (item.Side == Sides.Buy ? _bids : _asks); var quote = quotes.TryGetValue(item.Price); if (quote != null) { quote.Volume -= item.Volume; if (quote.Volume <= 0) { quotes.Remove(item.Price); if (item.Side == Sides.Buy) { _depth.Bids = GetArray(quotes); } else { _depth.Asks = GetArray(quotes); } } } } changed = true; } } else { throw new ArgumentException(LocalizedStrings.Str943Params.Put(item), "item"); // для одной сделки соответствуют две строчки в ОЛ //_trades[item.Trade.Id] = item; } } finally { if (changed) { _depth.ServerTime = item.ServerTime; } } return(changed); }