/// <summary>
		/// To get the underlying asset by the derivative.
		/// </summary>
		/// <param name="derivative">The derivative.</param>
		/// <param name="provider">The provider of information about instruments.</param>
		/// <returns>Underlying asset.</returns>
		public static Security GetUnderlyingAsset(this Security derivative, ISecurityProvider provider)
		{
			if (derivative == null)
				throw new ArgumentNullException("derivative");

			if (provider == null)
				throw new ArgumentNullException("provider");

			if (derivative.Type == SecurityTypes.Option)
			{
				derivative.CheckOption();

				return _underlyingSecurities.SafeAdd(derivative, key =>
				{
					var underlyingSecurity = provider.LookupById(key.UnderlyingSecurityId);

					if (underlyingSecurity == null)
						throw new InvalidOperationException(LocalizedStrings.Str704Params.Put(key.UnderlyingSecurityId));

					return underlyingSecurity;
				});
			}
			else
			{
				return provider.LookupById(derivative.UnderlyingSecurityId);
			}
		}
		/// <summary>
		/// To get the underlying asset.
		/// </summary>
		/// <param name="derivative">The derivative.</param>
		/// <param name="provider">The provider of information about instruments.</param>
		/// <returns>Underlying asset.</returns>
		public static Security GetAsset(this Security derivative, ISecurityProvider provider)
		{
			var asset = provider.LookupById(derivative.UnderlyingSecurityId);

			if (asset == null)
				throw new ArgumentException(LocalizedStrings.Str705Params.Put(derivative));

			return asset;
		}
        /// <inheritdoc />
        protected override void OnSendInMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Reset:
            {
                _subscriptions.Clear();
                _subscriptionsById.Clear();
                break;
            }

            case MessageTypes.MarketData:
            {
                var mdMsg = (MarketDataMessage)message;

                if (mdMsg.SecurityId.IsDefault())
                {
                    break;
                }

                var security = _securityProvider.LookupById(mdMsg.SecurityId);

                if (security == null)
                {
                    if (!mdMsg.IsBasket())
                    {
                        break;
                    }

                    security = mdMsg.ToSecurity(_exchangeInfoProvider).ToBasket(_processorProvider);
                }
                else if (!security.IsBasket())
                {
                    break;
                }

                if (mdMsg.IsSubscribe)
                {
                    var processor = _processorProvider.CreateProcessor(security);
                    var info      = new SubscriptionInfo(processor, mdMsg.TransactionId);

                    var dict = _subscriptions.SafeAdd(mdMsg.DataType);
                    _subscriptionsById.Add(mdMsg.TransactionId, info);

                    var inners = new MarketDataMessage[processor.BasketLegs.Length];

                    for (var i = 0; i < inners.Length; i++)
                    {
                        var inner = (MarketDataMessage)mdMsg.Clone();

                        inner.TransactionId = TransactionIdGenerator.GetNextId();
                        inner.SecurityId    = processor.BasketLegs[i];

                        inners[i] = inner;

                        info.LegsSubscriptions.Add(inner.TransactionId);
                        dict.Add(inner.TransactionId, info);
                    }

                    foreach (var inner in inners)
                    {
                        base.OnSendInMessage(inner);
                    }
                }
                else
                {
                    if (!_subscriptionsById.TryGetValue(mdMsg.OriginalTransactionId, out var info))
                    {
                        break;
                    }

                    _subscriptionsById.Remove(mdMsg.OriginalTransactionId);

                    foreach (var id in info.LegsSubscriptions)
                    {
                        base.OnSendInMessage(new MarketDataMessage
                            {
                                TransactionId         = TransactionIdGenerator.GetNextId(),
                                IsSubscribe           = false,
                                OriginalTransactionId = id
                            });
                    }
                }

                RaiseNewOutMessage(new MarketDataMessage
                    {
                        OriginalTransactionId = mdMsg.TransactionId
                    });

                return;
            }
            }

            base.OnSendInMessage(message);
        }
 public override Security CreateSecurity(string id)
 {
     return(_securityProvider.LookupById(id) ?? base.CreateSecurity(id));
 }
 /// <inheritdoc />
 public Security LookupById(SecurityId id)
 {
     return(_inner.TryGetValue(id) ?? _underlying.LookupById(id));
 }