context: namespace StockSharp.Algo
  {
  	using System;
  	using System.Collections;
  	using System.Collections.Generic;
  	using System.Linq;
  
  	using Ecng.Collections;
  	using Ecng.Common;
  
  	using StockSharp.BusinessEntities;
  	using StockSharp.Messages;
  	using StockSharp.Localization;
  
  	/// <summary>
  	/// Reasons for orders cancelling in the orders log.
  	/// </summary>
  	public enum OrderLogCancelReasons
  	{
  		/// <summary>
  		/// The order re-registration.
  		/// </summary>
  		ReRegistered,
  
  		/// <summary>
  		/// Cancel order.
  		/// </summary>
  		Canceled,
  
  		/// <summary>
  		/// Group canceling of orders.
  		/// </summary>
  		GroupCanceled,
  
  		/// <summary>
  		/// The sign of deletion of order residual due to cross-trade.
  		/// </summary>
  		CrossTrade,
  	}
  
  	/// <summary>
  	/// Building order book by the orders log.
  	/// </summary>
  	public static class OrderLogHelper
  	{
  		/// <summary>
  		/// To check, does the string contain the order registration.
  		/// </summary>
  		/// <param name="item">Order log item.</param>
  		/// <returns><see langword="true" />, if the string contains the order registration, otherwise, <see langword="false" />.</returns>
  		public static bool IsOrderLogRegistered(this ExecutionMessage item)
  		{
  			if (item == null)
  				throw new ArgumentNullException("item");
  
  			return item.OrderState == OrderStates.Active && item.TradePrice == null;
  		}
  
  		/// <summary>
  		/// To check, does the string contain the order registration.
  		/// </summary>
  		/// <param name="item">Order log item.</param>
  		/// <returns><see langword="true" />, if the string contains the order registration, otherwise, <see langword="false" />.</returns>
  		public static bool IsRegistered(this OrderLogItem item)
  		{
  			return item.ToMessage().IsOrderLogRegistered();
  		}
  
  		/// <summary>
  		/// To check, does the string contain the cancelled order.
  		/// </summary>
  		/// <param name="item">Order log item.</param>
  		/// <returns><see langword="true" />, if the string contain the cancelled order, otherwise, <see langword="false" />.</returns>
  		public static bool IsOrderLogCanceled(this ExecutionMessage item)
  		{
  			if (item == null)
  				throw new ArgumentNullException("item");
  
  			return item.OrderState == OrderStates.Done && item.TradePrice == null;
  		}
  
  		/// <summary>
  		/// To check, does the string contain the cancelled order.
  		/// </summary>
  		/// <param name="item">Order log item.</param>
  		/// <returns><see langword="true" />, if the string contain the cancelled order, otherwise, <see langword="false" />.</returns>
  		public static bool IsCanceled(this OrderLogItem item)
  		{
  			return item.ToMessage().IsOrderLogCanceled();
  		}
  
  		/// <summary>
  		/// To check, does the string contain the order matching.
  		/// </summary>
  		/// <param name="item">Order log item.</param>
  		/// <returns><see langword="true" />, if the string contains order matching, otherwise, <see langword="false" />.</returns>
  		public static bool IsOrderLogMatched(this ExecutionMessage item)
  		{
  			if (item == null)
  				throw new ArgumentNullException("item");
  
  			return item.TradeId != null;
  		}
  
  		/// <summary>
  		/// To check, does the string contain the order matching.
  		/// </summary>
  		/// <param name="item">Order log item.</param>
  		/// <returns><see langword="true" />, if the string contains order matching, otherwise, <see langword="false" />.</returns>
  		public static bool IsMatched(this OrderLogItem item)
  		{
  			return item.ToMessage().IsOrderLogMatched();
  		}
  
  		/// <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, "item");
  
  			if (item.OrderStatus == null)
  				throw new ArgumentException(LocalizedStrings.Str938, "item");
  
  			var status = (int)item.OrderStatus;
  
  			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("item", status, LocalizedStrings.Str939);
  		}
  
  		/// <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 GetCancelReason(this OrderLogItem item)
  		{
  			return item.ToMessage().GetOrderLogCancelReason();
  		}
  
  		private sealed class DepthEnumerable : SimpleEnumerable<QuoteChangeMessage>, IEnumerableEx<QuoteChangeMessage>
  		{
  			private sealed class DepthEnumerator : IEnumerator<QuoteChangeMessage>
  			{
  				private readonly TimeSpan _interval;
  				private readonly IEnumerator<ExecutionMessage> _itemsEnumerator;
  				private readonly IOrderLogMarketDepthBuilder _builder;
  				private readonly int _maxDepth;
  
  				public DepthEnumerator(IEnumerable<ExecutionMessage> items, IOrderLogMarketDepthBuilder builder, TimeSpan interval, int maxDepth)
  				{
  					if (builder == null)
  						throw new ArgumentNullException("builder");
  
  					if (items == null)
  						throw new ArgumentNullException("items");
  
  					if (maxDepth < 1)
  						throw new ArgumentOutOfRangeException("maxDepth", maxDepth, LocalizedStrings.Str941);
  
  					_itemsEnumerator = items.GetEnumerator();
  					_builder = builder;
  					_interval = interval;
  					_maxDepth = maxDepth;
  				}
  
  				public QuoteChangeMessage Current { get; private set; }
  
  				bool IEnumerator.MoveNext()
  				{
  					while (_itemsEnumerator.MoveNext())
  					{
  						var item = _itemsEnumerator.Current;
  
  						//if (_builder == null)
  						//	_builder = new OrderLogMarketDepthBuilder(new QuoteChangeMessage { SecurityId = item.SecurityId, IsSorted = true }, _maxDepth);
  
  						if (!_builder.Update(item))
  							continue;
  
  						if (Current != null && (_builder.Depth.ServerTime - Current.ServerTime) < _interval)
  							continue;
  
  						Current = (QuoteChangeMessage)_builder.Depth.Clone();
  
  						if (_maxDepth < int.MaxValue)
  						{
  							//Current.MaxDepth = _maxDepth;
  							Current.Bids = Current.Bids.Take(_maxDepth).ToArray();
  							Current.Asks = Current.Asks.Take(_maxDepth).ToArray();
  						}
  
  						return true;
  					}
  
  					Current = null;
  					return false;
  				}
  
  				public void Reset()
  				{
  					_itemsEnumerator.Reset();
  					Current = null;
  				}
  
  				object IEnumerator.Current
  				{
  					get { return Current; }
  				}
  
  				void IDisposable.Dispose()
  				{
  					Reset();
  					_itemsEnumerator.Dispose();
  				}
  			}
  
  			private readonly IEnumerableEx<ExecutionMessage> _items;
  
  			public DepthEnumerable(IEnumerableEx<ExecutionMessage> items, IOrderLogMarketDepthBuilder builder, TimeSpan interval, int maxDepth)
  				: base(() => new DepthEnumerator(items, builder, interval, maxDepth))
  			{
  				if (items == null)
  					throw new ArgumentNullException("items");
  
  				if (interval < TimeSpan.Zero)
  					throw new ArgumentOutOfRangeException("interval", interval, LocalizedStrings.Str940);
  
  				_items = items;
  			}
  
  			int IEnumerableEx.Count
  			{
  				get { return _items.Count; }
  			}
  		}
  
  		/// <summary>
  		/// Build market depths from order log.
  		/// </summary>
  		/// <param name="items">Orders log lines.</param>
  		/// <param name="builder">Order log to market depth builder.</param>
  		/// <param name="interval">The interval of the order book generation. The default is <see cref="TimeSpan.Zero"/>, which means order books generation at each new string of orders log.</param>
  		/// <param name="maxDepth">The maximal depth of order book. The default is <see cref="Int32.MaxValue"/>, which means endless depth.</param>
  		/// <returns>Market depths.</returns>
  		public static IEnumerableEx<MarketDepth> ToMarketDepths(this IEnumerableEx<OrderLogItem> items, IOrderLogMarketDepthBuilder builder, TimeSpan interval = default(TimeSpan), int maxDepth = int.MaxValue)
  		{
  			var first = items.FirstOrDefault();
  
  
gt: 			if (first == null)