/// <inheritdoc />
        public virtual IMessageAdapter TryGetAdapter(string portfolioName)
        {
            if (portfolioName.IsEmpty())
            {
                throw new ArgumentNullException(nameof(portfolioName));
            }

            return(_adapters.TryGetValue(portfolioName));
        }
        /// <summary>
        /// To get a board by the code.
        /// </summary>
        /// <param name="code">The board code <see cref="ExchangeBoard.Code"/>.</param>
        /// <returns>Trading board. If the board with the specified code does not exist, then <see langword="null" /> will be returned.</returns>
        public ExchangeBoard GetExchangeBoard(string code)
        {
            if (code.IsEmpty())
            {
                throw new ArgumentNullException(nameof(code));
            }

            return(_boards.TryGetValue(code));
        }
        /// <summary>
        /// To get an exchange by the code.
        /// </summary>
        /// <param name="code">The exchange code <see cref="Exchange.Name"/>.</param>
        /// <returns>Exchange. If the exchange with the specified code does not exist, then <see langword="null" /> will be returned.</returns>
        public Exchange GetExchange(string code)
        {
            if (code.IsEmpty())
            {
                throw new ArgumentNullException(nameof(code));
            }

            if (code.CompareIgnoreCase("RTS"))
            {
                code = "FORTS";
            }

            return(_exchanges.TryGetValue(code));
        }
예제 #4
0
        private void Refresh()
        {
            var ids = Invoke(f => f.GetStrategies(_lastCheckTime)).ToArray();

            foreach (var tuple in ids.Where(t => t.Item2 < 0))
            {
                var strategy = _strategies.TryGetValue(tuple.Item1);

                if (strategy != null)
                {
                    StrategyDeleted?.Invoke(strategy);
                }
            }

            var newIds     = new List <long>();
            var updatedIds = new List <long>();

            foreach (var tuple in ids.Where(t => t.Item2 >= 0))
            {
                var strategy = _strategies.TryGetValue(tuple.Item1);

                if (strategy != null)
                {
                    updatedIds.Add(tuple.Item1);
                }
                else
                {
                    newIds.Add(tuple.Item1);
                }
            }

            var newStrategies = Invoke(f => f.GetDescription(newIds.ToArray()));

            foreach (var newStrategy in newStrategies)
            {
                _strategies.Add(newStrategy.Id, newStrategy);
                StrategyCreated?.Invoke(newStrategy);
            }

            var updatedStrategies = Invoke(f => f.GetDescription(updatedIds.ToArray()));

            foreach (var updatedStrategy in updatedStrategies)
            {
                var strategy = _strategies[updatedStrategy.Id];
                CopyTo(updatedStrategy, strategy);
                StrategyUpdated?.Invoke(strategy);
            }

            _lastCheckTime = DateTime.Now;
        }
예제 #5
0
        /// <summary>
        /// To process the message, containing market data.
        /// </summary>
        /// <param name="message">The message, containing market data.</param>
        public void ProcessMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;

                if (execMsg.ExecutionType != ExecutionTypes.Tick)
                {
                    break;
                }

                var queue = _securityPnLs.TryGetValue(execMsg.SecurityId);

                if (queue != null)
                {
                    queue.ProcessExecution(execMsg);
                }

                break;
            }

            case MessageTypes.Level1Change:
            {
                var levelMsg = (Level1ChangeMessage)message;
                var queue    = _securityPnLs.TryGetValue(levelMsg.SecurityId);

                if (queue != null)
                {
                    queue.ProcessLevel1(levelMsg);
                }

                break;
            }

            case MessageTypes.QuoteChange:
            {
                var quoteMsg = (QuoteChangeMessage)message;
                var queue    = _securityPnLs.TryGetValue(quoteMsg.SecurityId);

                if (queue != null)
                {
                    queue.ProcessQuotes(quoteMsg);
                }

                break;
            }
            }
        }
예제 #6
0
        ///// <summary>
        ///// To get the source or executable codes.
        ///// </summary>
        ///// <param name="strategy">The strategy data.</param>
        //public void Download(StrategyData strategy)
        //{
        //	if (strategy == null)
        //		throw new ArgumentNullException(nameof(strategy));

        //	var content = Invoke(f => f.GetContent(SessionId, strategy.Id));

        //	strategy.Revision = content.Revision;
        //	strategy.Content = content.Content;
        //	strategy.ContentName = content.ContentName;
        //}

        /// <summary>
        /// To subscribe for the strategy.
        /// </summary>
        /// <param name="isAutoRenew">Is auto renewable subscription.</param>
        /// <param name="strategy">The strategy data.</param>
        /// <returns>The strategy subscription.</returns>
        public StrategySubscription Subscribe(StrategyData strategy, bool isAutoRenew)
        {
            if (strategy == null)
            {
                throw new ArgumentNullException(nameof(strategy));
            }

            var subscription = Invoke(f => f.Subscribe(SessionId, strategy.Id, isAutoRenew));

            if (subscription.Id < 0)
            {
                ValidateError((byte)-subscription.Id, strategy.Id);
            }
            else
            {
                lock (_subscriptions.SyncRoot)
                {
                    var prevSubscr = _subscriptions.TryGetValue(subscription.Id);

                    if (prevSubscr == null)
                    {
                        _subscriptions.Add(subscription.Id, subscription);
                    }
                    else
                    {
                        subscription = prevSubscr;
                    }
                }

                StrategySubscribed?.Invoke(subscription);
            }

            return(subscription);
        }
예제 #7
0
        /// <summary>
        /// Зарегистрировать индикатор. После регистрации данный индикатор начнет обновляться с использованием переданного источника.
        /// Если по данному источнику уже есть сохраненные данные, то они будут использованы для инициализации индикатора.
        /// Если пара индикатор-источник уже была ранее зарегистрирована, то вернется существующий токен.
        /// </summary>
        /// <param name="indicator">Индикатор.</param>
        /// <param name="source">Источник данных для индикатора.</param>
        /// <returns>Токен, который был зарегистрирован.</returns>
        public virtual IndicatorToken RegisterIndicator(IIndicator indicator, IIndicatorSource source)
        {
            lock (_indicatorUsages.SyncRoot)
            {
                var token = new IndicatorToken(indicator, source);

                var inDict = _indicatorUsages.TryGetValue(token);
                if (inDict != null)
                {
                    //найден индикатор, увеличим количество ссылок
                    inDict.Second++;
                    return(inDict.First);
                }

                //индикатора нет, добавим
                lock (_sources.SyncRoot)
                {
                    var indicators = _sources.SafeAdd(source, key => new IndicatorList(this, key));

                    token = new IndicatorToken(indicator, indicators.Source)
                    {
                        Container = Container
                    };
                    _indicatorUsages.Add(token, new RefPair <IndicatorToken, int>(token, 1));
                    indicators.Add(token);                     // тут пройдет подписка на события источника и обработка тех значений, которые уже есть в источнике
                }

                return(token);
            }
        }
예제 #8
0
        public Position TryAddPosition(Portfolio portfolio, Security security, string clientCode, string depoName, TPlusLimits?limitType, string description, out bool isNew)
        {
            isNew = false;
            Position position;

            lock (_positions.SyncRoot)
            {
                if (depoName == null)
                {
                    depoName = string.Empty;
                }

                if (clientCode == null)
                {
                    clientCode = string.Empty;
                }

                var key = Tuple.Create(portfolio, security, clientCode, depoName, limitType);

                if (!_positions.TryGetValue(key, out position))
                {
                    isNew = true;

                    position             = EntityFactory.CreatePosition(portfolio, security);
                    position.DepoName    = depoName;
                    position.LimitType   = limitType;
                    position.Description = description;
                    position.ClientCode  = clientCode;
                    _positions.Add(key, position);
                }
            }

            return(position);
        }
예제 #9
0
        /// <summary>
        /// Сообщить, что данный токен больше не требуется.
        /// Если количество вызовов будет равно количеству вызовов <see cref="RegisterIndicator"/>, то все данные по индикатору будут удалены.
        /// </summary>
        /// <param name="indicatorToken">Токен индикатора.</param>
        public virtual void UnRegisterIndicator(IndicatorToken indicatorToken)
        {
            lock (_indicatorUsages.SyncRoot)
            {
                var inDict = _indicatorUsages[indicatorToken];

                if (inDict.Second <= 0)
                {
                    throw new InvalidOperationException();
                }

                if (--inDict.Second == 0)
                {
                    _indicatorUsages.Remove(indicatorToken);

                    //чистим значения в контейнере
                    Container.RemoveIndicator(indicatorToken);

                    //удаляем из списка источника
                    lock (_sources.SyncRoot)
                    {
                        var indicators = _sources.TryGetValue(indicatorToken.Source);
                        if (indicators != null)
                        {
                            indicators.Remove(indicatorToken);
                        }
                    }
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Load settings.
        /// </summary>
        /// <param name="storage">Settings storage.</param>
        public void Load(SettingsStorage storage)
        {
            var drives = storage
                         .GetValue <IEnumerable <SettingsStorage> >(nameof(Drives))
                         .Select(s => s.LoadEntire <IMarketDataDrive>())
                         .ToArray();

            lock (_drives.SyncRoot)
            {
                foreach (var drive in drives)
                {
                    _drives.TryAdd(CreatePair(drive.Path), drive);
                }
            }

            if (storage.ContainsKey(nameof(DefaultDrive)))
            {
                var pair = CreatePair(storage.GetValue <string>(nameof(DefaultDrive)));

                if (_drives.TryGetValue(pair, out var drive))
                {
                    DefaultDrive = drive;
                }
            }
        }
예제 #11
0
        /// <inheritdoc />
        public Portfolio LookupByPortfolioName(string name)
        {
            if (name.IsEmpty())
            {
                throw new ArgumentNullException(nameof(name));
            }

            return(_inner.TryGetValue(name));
        }
예제 #12
0
        /// <summary>
        /// To get an exchange by the code.
        /// </summary>
        /// <param name="code">The exchange code <see cref="Exchange.Name"/>.</param>
        /// <returns>Exchange. If the exchange with the specified code does not exist, then <see langword="null" /> will be returned.</returns>
        public Exchange GetExchange(string code)
        {
            if (code.IsEmpty())
            {
                throw new ArgumentNullException("code");
            }

            return(_exchanges.TryGetValue(code));
        }
예제 #13
0
        IExtendedInfoStorageItem IExtendedInfoStorage.Get(string storageName)
        {
            if (storageName.IsEmpty())
            {
                throw new ArgumentNullException(nameof(storageName));
            }

            return(_items.TryGetValue(storageName));
        }
예제 #14
0
        private void DecRefProcessor(IMessageProcessor processor)
        {
            var ptr = _processorPointers.TryGetValue(processor);

            if (ptr != null)
            {
                ptr.DecRef();
            }
        }
예제 #15
0
        /// <summary>
        /// Прекратить получение данных, запущенное через <see cref="Start"/>.
        /// </summary>
        /// <param name="series">Серия свечек.</param>
        public override void Stop(CandleSeries series)
        {
            lock (_series.SyncRoot)
            {
                var info = _series.TryGetValue(series);

                if (info != null)
                {
                    info.IsStopping = true;
                }
            }
        }
            public void UpdateTimeOut(long transactionId)
            {
                if (transactionId == 0)
                {
                    return;
                }

                lock (_registeredIds.SyncRoot)
                {
                    if (!_registeredIds.TryGetValue(transactionId, out var timeOut))
                    {
                        return;
                    }

                    _registeredIds[transactionId] = timeOut;
                }
            }
예제 #17
0
        private MarketDataGenerator TryGetGenerator(MarketDataMessage message)
        {
            switch (message.DataType)
            {
            case MarketDataTypes.Trades:
                return(_tradeGenerators.TryGetValue(message.SecurityId));

            case MarketDataTypes.MarketDepth:
                return(_depthGenerators.TryGetValue(message.SecurityId));

            case MarketDataTypes.OrderLog:
                return(_orderLogGenerators.TryGetValue(message.SecurityId));

            default:
                return(null);
            }
        }
            public void UpdateTimeOut <TMessage>(TMessage message)
                where TMessage : IOriginalTransactionIdMessage
            {
                var transactionId = message.OriginalTransactionId;

                if (transactionId == 0)
                {
                    return;
                }

                lock (_registeredIds.SyncRoot)
                {
                    if (!_registeredIds.TryGetValue(transactionId, out var timeOut))
                    {
                        return;
                    }

                    _registeredIds[transactionId] = timeOut;
                }
            }
예제 #19
0
 T IStorageEntityList <T> .ReadById(object id)
 {
     return(_items.TryGetValue(id));
 }
예제 #20
0
        /// <summary>
        /// To calculate position.
        /// </summary>
        /// <param name="message">Message.</param>
        /// <returns>The position by order or trade.</returns>
        public decimal?ProcessMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Reset:
            {
                Reset();
                break;
            }

            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;
                var key     = Tuple.Create(execMsg.SecurityId, execMsg.PortfolioName);

                if (ByOrders && execMsg.HasOrderInfo())
                {
                    var orderId     = execMsg.OriginalTransactionId;
                    var newPosition = execMsg.GetPosition();

                    bool    isNew;
                    decimal position;

                    lock (_positions.SyncRoot)
                    {
                        decimal prev;
                        isNew = _positions.TryGetValue(key, out prev);

                        Tuple <Sides, decimal> oldPosition;

                        if (_byOrderPositions.TryGetValue(orderId, out oldPosition))
                        {
                            if (newPosition != oldPosition.Item2)
                            {
                                _byOrderPositions[orderId] = Tuple.Create(execMsg.Side, newPosition);
                            }

                            position = newPosition - oldPosition.Item2;
                        }
                        else
                        {
                            _byOrderPositions.Add(orderId, Tuple.Create(execMsg.Side, newPosition));
                            position = newPosition;
                        }

                        _positions[key] = prev + position;
                        Position       += position;
                    }

                    if (isNew)
                    {
                        NewPosition?.Invoke(new KeyValuePair <Tuple <SecurityId, string>, decimal>(key, Position));
                    }
                    else
                    {
                        PositionChanged?.Invoke(new KeyValuePair <Tuple <SecurityId, string>, decimal>(key, Position));
                    }

                    return(position);
                }

                if (!ByOrders && execMsg.HasTradeInfo())
                {
                    var position = execMsg.GetPosition();

                    if (position == 0)
                    {
                        break;
                    }

                    bool isNew;

                    lock (_positions.SyncRoot)
                    {
                        decimal prev;
                        isNew           = _positions.TryGetValue(key, out prev);
                        _positions[key] = prev + position;
                        Position       += position;
                    }

                    if (isNew)
                    {
                        NewPosition?.Invoke(new KeyValuePair <Tuple <SecurityId, string>, decimal>(key, Position));
                    }
                    else
                    {
                        PositionChanged?.Invoke(new KeyValuePair <Tuple <SecurityId, string>, decimal>(key, Position));
                    }

                    return(position);
                }

                break;
            }
            }

            return(null);
        }
예제 #21
0
        private void Refresh()
        {
            var ids = Invoke(f => f.GetStrategies(_lastCheckTime)).ToArray();

            foreach (var tuple in ids.Where(t => t.Item2 < 0))
            {
                var strategy = _strategies.TryGetValue(tuple.Item1);

                if (strategy != null)
                {
                    StrategyDeleted?.Invoke(strategy);
                }
            }

            var newIds     = new List <long>();
            var updatedIds = new List <long>();

            foreach (var tuple in ids.Where(t => t.Item2 >= 0))
            {
                var strategy = _strategies.TryGetValue(tuple.Item1);

                if (strategy != null)
                {
                    updatedIds.Add(tuple.Item1);
                }
                else
                {
                    newIds.Add(tuple.Item1);
                }
            }

            var newStrategies = Invoke(f => f.GetDescription(newIds.ToArray()));

            foreach (var newStrategy in newStrategies)
            {
                _strategies.Add(newStrategy.Id, newStrategy);
                StrategyCreated?.Invoke(newStrategy);
            }

            var updatedStrategies = Invoke(f => f.GetDescription(updatedIds.ToArray()));

            foreach (var updatedStrategy in updatedStrategies)
            {
                var strategy = _strategies[updatedStrategy.Id];
                CopyTo(updatedStrategy, strategy);
                StrategyUpdated?.Invoke(strategy);
            }

            _lastCheckTime = DateTime.Now;

            foreach (var backtest in _backtests.CachedValues)
            {
                if (_backtestResults.ContainsKey(backtest))
                {
                    continue;
                }

                var resultId = Invoke(f => f.GetBacktestResult(SessionId, backtest.Id));

                if (resultId == null)
                {
                    continue;
                }

                _backtestResults.Add(backtest, resultId.Value);
                BacktestStopped?.Invoke(backtest);

                _startedBacktests.Remove(backtest);
            }

            foreach (var backtest in _startedBacktests.CachedKeys)
            {
                var count     = Invoke(f => f.GetCompletedIterationCount(SessionId, backtest.Id));
                var prevCount = _startedBacktests[backtest];

                if (count == prevCount)
                {
                    continue;
                }

                BacktestProgressChanged?.Invoke(backtest, count);

                if (count == backtest.Iterations.Length)
                {
                    _startedBacktests.Remove(backtest);
                }
                else
                {
                    _startedBacktests[backtest] = count;
                }
            }
        }
예제 #22
0
 ExchangeBoard IExchangeInfoProvider.GetExchangeBoard(string code)
 {
     return(_boards.TryGetValue(code));
 }
예제 #23
0
 Exchange IExchangeInfoProvider.GetExchange(string code)
 {
     return(_exchanges.TryGetValue(code));
 }
예제 #24
0
 public T ReadById(object id)
 {
     return(_items.TryGetValue(id));
 }
예제 #25
0
        /// <summary>
        /// To process the message, containing market data.
        /// </summary>
        /// <param name="message">The message, containing market data.</param>
        /// <returns><see cref="PnL"/> was changed.</returns>
        public bool ProcessMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;

                if (execMsg.ExecutionType != ExecutionTypes.Tick)
                {
                    break;
                }

                var queue = _securityPnLs.TryGetValue(execMsg.SecurityId);

                if (queue == null)
                {
                    break;
                }

                queue.ProcessExecution(execMsg);
                return(true);
            }

            case MessageTypes.Level1Change:
            {
                var levelMsg = (Level1ChangeMessage)message;

                var queue = _securityPnLs.TryGetValue(levelMsg.SecurityId);

                if (queue == null)
                {
                    break;
                }

                queue.ProcessLevel1(levelMsg);
                return(true);
            }

            case MessageTypes.QuoteChange:
            {
                var quoteMsg = (QuoteChangeMessage)message;

                var queue = _securityPnLs.TryGetValue(quoteMsg.SecurityId);

                if (queue == null)
                {
                    break;
                }

                queue.ProcessQuotes(quoteMsg);
                return(true);
            }

            case MessageTypes.PositionChange:
            {
                var posMsg = (PositionChangeMessage)message;

                var leverage = posMsg.Changes.TryGetValue(PositionChangeTypes.Leverage).To <decimal?>();
                if (leverage != null)
                {
                    if (posMsg.IsMoney())
                    {
                        _securityPnLs.CachedValues.ForEach(q => q.Leverage = leverage.Value);
                    }
                    else
                    {
                        _securityPnLs.SafeAdd(posMsg.SecurityId, security => new PnLQueue(security)).Leverage = leverage.Value;
                    }
                }

                break;
            }
            }

            return(false);
        }
예제 #26
0
        /// <summary>
        /// To process the message, containing market data.
        /// </summary>
        /// <param name="message">The message, containing market data.</param>
        public void ProcessMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Execution:
            {
                var execMsg = (ExecutionMessage)message;

                if (execMsg.ExecutionType != ExecutionTypes.Tick)
                {
                    break;
                }

                var queue = _securityPnLs.TryGetValue(execMsg.SecurityId);
                queue?.ProcessExecution(execMsg);

                break;
            }

            case MessageTypes.Level1Change:
            {
                var levelMsg = (Level1ChangeMessage)message;

                var queue = _securityPnLs.TryGetValue(levelMsg.SecurityId);
                queue?.ProcessLevel1(levelMsg);

                break;
            }

            case MessageTypes.QuoteChange:
            {
                var quoteMsg = (QuoteChangeMessage)message;

                var queue = _securityPnLs.TryGetValue(quoteMsg.SecurityId);
                queue?.ProcessQuotes(quoteMsg);

                break;
            }

            case MessageTypes.PortfolioChange:
            {
                var pfMsg = (PortfolioChangeMessage)message;

                var leverage = pfMsg.Changes.TryGetValue(PositionChangeTypes.Leverage).To <decimal?>();
                if (leverage != null)
                {
                    _securityPnLs.CachedValues.ForEach(q => q.Leverage = leverage.Value);
                }

                break;
            }

            case MessageTypes.PositionChange:
            {
                var posMsg = (PositionChangeMessage)message;

                var leverage = posMsg.Changes.TryGetValue(PositionChangeTypes.Leverage).To <decimal?>();
                if (leverage != null)
                {
                    _securityPnLs.SafeAdd(posMsg.SecurityId, security => new PnLQueue(security)).Leverage = leverage.Value;
                }

                break;
            }
            }
        }
예제 #27
0
 /// <summary>
 /// Get series by request identifier.
 /// </summary>
 /// <param name="transactionId">Request identifier.</param>
 /// <returns>Candles series or <see langword="null"/> if identifier is non exist.</returns>
 public CandleSeries TryGetCandleSeries(long transactionId) => _holders.TryGetValue(transactionId)?.Series;
예제 #28
0
 public OrderInfo TryGetOrder(OrderTypes?type, long transactionId, bool isCancel)
 {
     return(Orders.TryGetValue(CreateOrderKey(type, transactionId, isCancel))
            ?? (type == null ? Orders.TryGetValue(CreateOrderKey(OrderTypes.Conditional, transactionId, isCancel)) : null));
 }
예제 #29
0
        /// <summary>
        /// Send message.
        /// </summary>
        /// <param name="message">Message.</param>
        protected override void OnSendInMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Reset:
                ProcessReset(message);
                break;

            case MessageTypes.Connect:
                if (_isFirstConnect)
                {
                    _isFirstConnect = false;
                }
                else
                {
                    ProcessReset(new ResetMessage());
                }

                _hearbeatAdapters.AddRange(GetSortedAdapters().ToDictionary(a => a, a =>
                {
                    var hearbeatAdapter            = (IMessageAdapter) new HeartbeatAdapter(a);
                    hearbeatAdapter.Parent         = this;
                    hearbeatAdapter.NewOutMessage += m => OnInnerAdapterNewMessage(a, m);
                    return(hearbeatAdapter);
                }));

                if (_hearbeatAdapters.Count == 0)
                {
                    throw new InvalidOperationException(LocalizedStrings.Str3650);
                }

                _hearbeatAdapters.Values.ForEach(a => a.SendInMessage(message));
                break;

            case MessageTypes.Disconnect:
                _connectedAdapters
                .CachedValues
                .SelectMany(c => c.Cache)
                .Distinct()
                .ForEach(a => a.SendInMessage(message));
                break;

            case MessageTypes.Portfolio:
            {
                var pfMsg = (PortfolioMessage)message;
                ProcessPortfolioMessage(pfMsg.PortfolioName, pfMsg);
                break;
            }

            case MessageTypes.OrderRegister:
            case MessageTypes.OrderReplace:
            case MessageTypes.OrderCancel:
            case MessageTypes.OrderGroupCancel:
            {
                var ordMsg = (OrderMessage)message;
                ProcessPortfolioMessage(ordMsg.PortfolioName, ordMsg);
                break;
            }

            case MessageTypes.OrderPairReplace:
            {
                var ordMsg = (OrderPairReplaceMessage)message;
                ProcessPortfolioMessage(ordMsg.Message1.PortfolioName, ordMsg);
                break;
            }

            case MessageTypes.MarketData:
            {
                var adapters = _connectedAdapters.TryGetValue(message.Type);

                if (adapters == null)
                {
                    throw new InvalidOperationException(LocalizedStrings.Str629Params.Put(message.Type));
                }

                var mdMsg = (MarketDataMessage)message;

                switch (mdMsg.DataType)
                {
                case MarketDataTypes.News:
                    adapters.Cache.ForEach(a => a.SendInMessage(mdMsg));
                    break;

                default:
                {
                    var key = CreateKey(mdMsg);

                    var state = _subscriptionStates.TryGetValue2(key);

                    if (mdMsg.IsSubscribe)
                    {
                        if (state != null)
                        {
                            RaiseMarketDataMessage(null, mdMsg.OriginalTransactionId, new InvalidOperationException(state.Value.ToString()), true);
                            break;
                        }
                        else
                        {
                            _subscriptionStates.Add(key, SubscriptionStates.Subscribing);
                        }
                    }
                    else
                    {
                        var canProcess = false;

                        switch (state)
                        {
                        case SubscriptionStates.Subscribed:
                            canProcess = true;
                            _subscriptionStates[key] = SubscriptionStates.Unsubscribing;
                            break;

                        case SubscriptionStates.Subscribing:
                        case SubscriptionStates.Unsubscribing:
                            RaiseMarketDataMessage(null, mdMsg.OriginalTransactionId, new InvalidOperationException(state.Value.ToString()), false);
                            break;

                        case null:
                            RaiseMarketDataMessage(null, mdMsg.OriginalTransactionId, null, false);
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        if (!canProcess)
                        {
                            break;
                        }
                    }

                    if (mdMsg.TransactionId != 0)
                    {
                        _subscriptionKeys.Add(mdMsg.TransactionId, key);
                    }

                    if (mdMsg.IsSubscribe)
                    {
                        //if (_subscriptionQueue.ContainsKey(key))
                        //	return;

                        var enumerator = adapters.Cache.Cast <IMessageAdapter>().GetEnumerator();

                        _subscriptionQueue.Add(key, enumerator);
                        ProcessSubscriptionAction(enumerator, mdMsg, mdMsg.TransactionId);
                    }
                    else
                    {
                        var adapter = _subscriptions.TryGetValue(key);

                        if (adapter != null)
                        {
                            _subscriptions.Remove(key);
                            adapter.SendInMessage(message);
                        }
                    }

                    break;
                }
                }

                break;
            }

            default:
            {
                var adapters = _connectedAdapters.TryGetValue(message.Type);

                if (adapters == null)
                {
                    throw new InvalidOperationException(LocalizedStrings.Str629Params.Put(message.Type));
                }

                adapters.Cache.ForEach(a => a.SendInMessage(message));
                break;
            }
            }
        }
 /// <inheritdoc />
 public virtual IMessageAdapter GetAdapter(string portfolioName)
 {
     return(_adapters.TryGetValue(portfolioName));
 }