private static int ChangeSubscribers(SynchronizedDictionary <Security, int> subscribers, Security subscriber, int delta)
        {
            if (subscribers == null)
            {
                throw new ArgumentNullException("subscribers");
            }

            lock (subscribers.SyncRoot)
            {
                var value = subscribers.TryGetValue2(subscriber) ?? 0;

                value += delta;

                if (value > 0)
                {
                    subscribers[subscriber] = value;
                }
                else
                {
                    subscribers.Remove(subscriber);
                }

                return(value);
            }
        }
        private void OnCandlesResponse(CandlesResponse response)
        {
            var key           = Tuple.Create(response.SecId, response.Period);
            var transactionId = _candleTransactions.TryGetValue2(key);

            if (transactionId == null)
            {
                SendOutError(LocalizedStrings.Str3513Params.Put(response.SecCode, response.Board, response.Period));
                return;
            }

            var isFinished = false;

            switch (response.Status)
            {
            case CandleResponseStatus.Finished:
            case CandleResponseStatus.Done:
            case CandleResponseStatus.NotAvailable:
                isFinished = true;
                _candleTransactions.Remove(key);
                break;
            }

            var index = 0;

            foreach (var candle in response.Candles)
            {
                var time = candle.Date.ToDto();

                SendOutMessage(new TimeFrameCandleMessage
                {
                    OriginalTransactionId = (long)transactionId,
                    SecurityId            = new SecurityId {
                        Native = response.SecId
                    },
                    OpenPrice    = candle.Open,
                    HighPrice    = candle.High,
                    LowPrice     = candle.Low,
                    ClosePrice   = candle.Close,
                    TotalVolume  = candle.Volume,
                    OpenTime     = time,
                    CloseTime    = time + _candlePeriods[response.Period],
                    OpenInterest = candle.Oi,
                    IsFinished   = isFinished && ++index == response.Candles.Length,
                    State        = CandleStates.Finished,
                });
            }
        }
		private static int ChangeSubscribers(SynchronizedDictionary<Security, int> subscribers, Security subscriber, int delta)
		{
			if (subscribers == null)
				throw new ArgumentNullException("subscribers");

			lock (subscribers.SyncRoot)
			{
				var value = subscribers.TryGetValue2(subscriber) ?? 0;

				value += delta;

				if (value > 0)
					subscribers[subscriber] = value;
				else
					subscribers.Remove(subscriber);

				return value;
			}
		}
Beispiel #4
0
        /// <summary>
        /// Send message.
        /// </summary>
        /// <param name="message">Message.</param>
        protected override void OnSendInMessage(Message message)
        {
            if (message.IsBack)
            {
                var adapter = message.Adapter;

                if (adapter == null)
                {
                    throw new InvalidOperationException();
                }

                adapter.SendInMessage(message);
                return;
            }

            switch (message.Type)
            {
            case MessageTypes.Reset:
                ProcessReset(message);
                break;

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

                _hearbeatAdapters.AddRange(GetSortedAdapters().Select(CreateWrappers).ToDictionary(a => a, a =>
                    {
                        var hearbeatAdapter = new HeartbeatMessageAdapter(a);
                        ((IMessageAdapter)hearbeatAdapter).Parent = this;
                        hearbeatAdapter.NewOutMessage            += m => OnInnerAdapterNewOutMessage(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.Cache.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;
                ProcessAdapterMessage(ordMsg.PortfolioName, ordMsg);
                break;
            }

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

            case MessageTypes.MarketData:
            {
                IMessageAdapter[] adapters = null;

                if (message.Adapter != null)
                {
                    var wrapper = _hearbeatAdapters.Values.FirstOrDefault(w => GetUnderlyingAdapter(w) == message.Adapter);

                    if (wrapper != null)
                    {
                        adapters = new IMessageAdapter[] { wrapper }
                    }
                    ;
                }

                if (adapters == null)
                {
                    adapters = _messageTypeAdapters.TryGetValue(message.Type)?.Cache;
                }

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

                var mdMsg = (MarketDataMessage)message;

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

                default:
                {
                    var key = mdMsg.CreateKey();

                    var state = _subscriptionStates.TryGetValue2(key);

                    if (mdMsg.IsSubscribe)
                    {
                        if (state != null)
                        {
                            switch (state)
                            {
                            case SubscriptionStates.Subscribed:
                            {
                                var adapter = _subscriptions.TryGetValue(key);

                                if (adapter != null)
                                {
                                    adapter.SendInMessage(mdMsg);
                                }
                                else
                                {
                                    RaiseMarketDataMessage(null, mdMsg.OriginalTransactionId, new InvalidOperationException(state.Value.ToString()), true);
                                }

                                break;
                            }

                            case SubscriptionStates.Subscribing:
                                //case SubscriptionStates.Unsubscribing:
                                _suspendedSubscriptions.SafeAdd(key).Add(mdMsg);
                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }

                            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.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;
            }

            case MessageTypes.ChangePassword:
            {
                var adapter = GetSortedAdapters().FirstOrDefault(a => a.SupportedMessages.Contains(MessageTypes.ChangePassword));

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

                adapter.SendInMessage(message);
                break;
            }

            default:
            {
                if (message.Adapter != null)
                {
                    message.Adapter.SendInMessage(message);
                    break;
                }

                var adapters = _messageTypeAdapters.TryGetValue(message.Type)?.Cache;

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

                adapters.ForEach(a => a.SendInMessage(message));
                break;
            }
            }
        }
Beispiel #5
0
        private void ProcessIQFeedMessage(IQFeedWrapper feed, Message message)
        {
            switch (message.Type)
            {
            case ExtendedMessageTypes.System:
            {
                var systemMsg = (IQFeedSystemMessage)message;

                switch (systemMsg.Value)
                {
                case "SERVER DISCONNECTED":
                case "SERVER RECONNECT FAILED":
                    SendOutMessage(systemMsg);
                    break;

                default:
                {
                    if (feed == _lookupFeed)
                    {
                        _currSystemType = ExtendedMessageTypes.ListedMarket;
                        _lookupFeed.RequestListedMarkets();
                    }

                    break;
                }
                }

                break;
            }

            case ExtendedMessageTypes.HistoryExtraDayCandle:

                // расширенное сообщение лучше передавать внешнему коду, чтобы ему хоть как-то получить информацию
                //case ExtendedMessageTypes.Data:

                break;

            case ExtendedMessageTypes.ListedMarket:
            {
                var lmMsg = (IQFeedListedMarketMessage)message;
                _markets[lmMsg.Id] = lmMsg.Code;
                break;
            }

            case ExtendedMessageTypes.SecurityType:
            {
                var stMsg = (IQFeedSecurityTypeMessage)message;

                try
                {
                    var secType = stMsg.Code.ToSecurityType();

                    if (secType == null)
                    {
                        this.AddWarningLog(LocalizedStrings.Str2140Params.Put(stMsg.Code));
                    }

                    _securityTypes[stMsg.Id] = secType;
                }
                catch (Exception ex)
                {
                    this.AddErrorLog(ex);
                }

                break;
            }

            case ExtendedMessageTypes.End:
            {
                var type      = feed == _lookupFeed ? _currSystemType : null;
                var requestId = 0L;

                if (_currSystemType == null)
                {
                    requestId = message.GetRequestId();

                    type = _requestsType.TryGetValue2(requestId);

                    if (type == null)
                    {
                        return;
                    }

                    _requestsType.Remove(requestId);
                    _secIds.Remove(requestId);

                    if (type == MessageTypes.CandleTimeFrame ||
                        type == MessageTypes.CandleVolume ||
                        type == MessageTypes.CandleTick ||
                        type == ExtendedMessageTypes.HistoryExtraDayCandle)
                    {
                        _candleParsers.Remove(requestId);
                    }
                }

                switch (type)
                {
                case MessageTypes.Security:
                {
                    var result = _lookupResult.TryGetValue(requestId);

                    if (result == null)
                    {
                        return;
                    }

                    _lookupResult.Remove(requestId);

                    SendOutMessage(new SecurityLookupResultMessage {
                                OriginalTransactionId = requestId
                            });

                    break;
                }

                case ExtendedMessageTypes.ListedMarket:
                {
                    _currSystemType = ExtendedMessageTypes.SecurityType;
                    _lookupFeed.RequestSecurityTypes();
                    break;
                }

                case ExtendedMessageTypes.SecurityType:
                {
                    _currSystemType = null;
                    SendOutMessage(new ConnectMessage());
                    break;
                }

                // для сделок и свечек отправляем фиктивный объект,
                // чтобы сообщить, что получение исторических данных завершено

                case MessageTypes.Execution:
                {
                    SendOutMessage(new Level1ChangeMessage
                            {
                                ExtensionInfo = new Dictionary <object, object>
                                {
                                    { "IsFinished", true },
                                }
                            }.InitRequestId(requestId));
                    break;
                }

                case MessageTypes.CandleTimeFrame:
                case MessageTypes.CandleTick:
                case MessageTypes.CandleVolume:
                case ExtendedMessageTypes.HistoryExtraDayCandle:
                {
                    SendOutMessage(new TimeFrameCandleMessage
                            {
                                IsFinished            = true,
                                OriginalTransactionId = requestId,
                            });
                    break;
                }
                }

                break;
            }

            //case MessageTypes.Security:
            //{
            //	var secMsg = (SecurityMessage)message;

            //	var exchangeRoot = message.GetValue<string>("ExchangeRoot");

            //	switch (secMsg.SecurityType)
            //	{
            //		case SecurityTypes.Future:
            //			secMsg.ExpiryDate = message.GetValue<DateTime>("ExpiryDate");
            //			secMsg.UnderlyingSecurityCode = exchangeRoot;
            //			break;

            //		case SecurityTypes.Option:
            //			secMsg.ExpiryDate = message.GetValue<DateTime>("ExpiryDate");
            //			secMsg.UnderlyingSecurityCode = exchangeRoot;
            //			secMsg.Strike = message.GetValue<decimal>("Strike");
            //			break;
            //	}

            //	SendOutMessage(secMsg);
            //	break;
            //}

            default:
                SendOutMessage(message);
                break;
            }
        }