コード例 #1
0
ファイル: IQFeedMessage.cs プロジェクト: RakotVT/StockSharp
		public IQFeedSystemMessage(IQFeedWrapper feed, string value)
			: base(ExtendedMessageTypes.System)
		{
			if (feed == null)
				throw new ArgumentNullException(nameof(feed));

			Feed = feed;
			Value = value;
		}
コード例 #2
0
        public IQFeedSystemMessage(IQFeedWrapper feed, string value)
            : base(ExtendedMessageTypes.System)
        {
            if (feed == null)
            {
                throw new ArgumentNullException("feed");
            }

            Feed  = feed;
            Value = value;
        }
コード例 #3
0
 private void SafeDisconnectFeed(ref IQFeedWrapper feed)
 {
     try
     {
         feed.Disconnect();
         feed = null;
     }
     catch (Exception ex)
     {
         SendOutError(ex);
     }
 }
コード例 #4
0
        private IEnumerable <Message> ToMessages(IQFeedWrapper feed, string str, MessageTypes type, long requestId)
        {
            var messages = ParseMessages(feed, str, type, requestId);

            if (requestId == 0)
            {
                return(messages);
            }

            return(messages.Select(m =>
            {
                m.InitRequestId(requestId);
                return m;
            }));
        }
コード例 #5
0
        private IQFeedWrapper CreateFeed(EndPoint endPoint, string name)
        {
            var feed = new IQFeedWrapper(this, name, endPoint);

            feed.ProcessReply += line =>
            {
                IEnumerable <Message> messages;

                try
                {
                    messages = ConvertToMessages(feed, line).ToArray();
                }
                catch (Exception ex)
                {
                    ex = new InvalidOperationException(LocalizedStrings.Str2141Params.Put(line), ex);
                    this.AddErrorLog(ex);
                    messages = new[] { new ErrorMessage {
                                           Error = ex
                                       } };
                }

                foreach (var message in messages)
                {
                    ProcessIQFeedMessage(feed, message);
                }
            };
            feed.ConnectionError += err =>
            {
                if (name == "LookupFeed")
                {
                    SendOutMessage(new ConnectMessage {
                        Error = err
                    });
                }
                else
                {
                    SendOutError(err);
                }

                //feed.Disconnect();
                //feed.Connect();
            };

            feed.Connect();

            return(feed);
        }
コード例 #6
0
		private IEnumerable<Message> ParseMessages(IQFeedWrapper feed, string str, MessageTypes type, long requestId)
		{
			switch (type)
			{
				case ExtendedMessageTypes.System:
					yield return new IQFeedSystemMessage(feed, str);
					break;
				case ExtendedMessageTypes.SecurityType:
				{
					var parts = str.SplitByComma();
					yield return new IQFeedSecurityTypeMessage(parts[0].To<int>(), parts[1], parts[2]);
					break;
				}
				case ExtendedMessageTypes.ListedMarket:
				{
					var parts = str.SplitByComma();
					yield return new IQFeedListedMarketMessage(parts[0].To<int>(), parts[1], parts[2]);
					break;
				}
				case ExtendedMessageTypes.Data:
					yield return new IQFeedDataMessage(str);
					break;
				case ExtendedMessageTypes.End:
					yield return new IQFeedEndMessage();
					break;
				case MessageTypes.Time:
					yield return new TimeMessage { ServerTime = str.ToDateTime("yyyyMMdd HH:mm:ss").ApplyTimeZone(TimeHelper.Est) };
					break;
				case MessageTypes.Security:
				{
					var parts = str.SplitByComma();

					yield return new SecurityMessage
					{
						SecurityId = CreateSecurityId(parts[0], parts[1].To<int>()),
						Name = parts[3],
						OriginalTransactionId = requestId,
						SecurityType = _securityTypes[parts[2].To<int>()],
					};

					break;
				}
				
				case ExtendedMessageTypes.Fundamental:
				{
					foreach (var result in ToSecurityFundamentalMessages(str))
						yield return result;

					break;
				}
				
				case MessageTypes.Level1Change:
				{
					foreach (var result in ToSecurityUpdateMessage(str))
						yield return result;

					break;
				}
				
				case MessageTypes.Execution:
				{
					yield return ToLevel1(str, _secIds[requestId]);
					break;
				}

				case MessageTypes.News:
					yield return ToNewsMessage(str);
					break;

				case ExtendedMessageTypes.NewsStory:
				{
					yield return new NewsMessage
					{
						Id = _newsIds[requestId],
						Story = str.StripBrackets("<BEGIN>", "<END>"),
						ServerTime = CurrentTime.Convert(TimeHelper.Est)
					};

					break;
				}

				case MessageTypes.CandleTimeFrame:
				case MessageTypes.CandleTick:
				case MessageTypes.CandleVolume:
				case ExtendedMessageTypes.HistoryExtraDayCandle:
				{
					var parts = str.SplitByComma();

					var tuple = _candleParsers[requestId];

					var candleMsg = tuple.Item1(parts);

					candleMsg.OriginalTransactionId = requestId;
					candleMsg.SecurityId = _secIds[requestId];

					if (tuple.Item2 is TimeSpan)
					{
						var tf = (TimeSpan)tuple.Item2;

						if (tf == TimeSpan.FromDays(1))
						{
							candleMsg.OpenTime = candleMsg.CloseTime;
							candleMsg.CloseTime = candleMsg.OpenTime.EndOfDay();
						}
						else// if (tf == TimeSpan.FromDays(7) || tf.Ticks == TimeHelper.TicksPerMonth)
						{
							candleMsg.CloseTime -= TimeSpan.FromTicks(1);
							candleMsg.OpenTime = tf.GetCandleBounds(candleMsg.CloseTime.ToLocalTime(TimeHelper.Est)).Min;
						}
					}
					else
						candleMsg.OpenTime = candleMsg.CloseTime;
					
					yield return candleMsg;
					break;
				}

				case MessageTypes.QuoteChange:
				{
					var l1Msg = ToLevel2(str);

					if (l1Msg != null)
						yield return l1Msg;

					break;
				}

				case MessageTypes.Error:
					yield return new ErrorMessage { Error = new InvalidOperationException(str) };
					break;

				default:
					throw new InvalidOperationException(LocalizedStrings.Str2142Params.Put(type));
			}
		}
コード例 #7
0
		private IEnumerable<Message> ToMessages(IQFeedWrapper feed, string str, MessageTypes type, long requestId)
		{
			var messages = ParseMessages(feed, str, type, requestId);

			if (requestId == 0)
				return messages;

			return messages.Select(m =>
			{
				m.InitRequestId(requestId);
				return m;
			});
		}
コード例 #8
0
		private IEnumerable<Message> ConvertToMessages(IQFeedWrapper feed, string line)
		{
			//Market Depth & NASDAQ Level 2 via TCP/IP
			//This is a deprecated message and only sent for backwards compatability
			if (line.CompareIgnoreCase("O"))
				return Enumerable.Empty<Message>();

			long requestId = 0;

			var match = _regexRequestId.Match(line);
			if (match.Success)
			{
				requestId = match.Groups[1].Value.To<long>();
				line = match.Groups[2].Value;
			}

			match = _regexError.Match(line);

			if (match.Success)
			{
				var text = match.Groups[1].Value;

				return text.Equals("!NO_DATA!")
					? Enumerable.Empty<Message>()
					: ToMessages(feed, text, MessageTypes.Error, requestId);
			}

			match = _regexTime.Match(line);

			if (match.Success)
				return ToMessages(feed, match.Groups[1].Value, MessageTypes.Time, requestId);

			match = _regexLastMessage.Match(line);

			if (match.Success)
				return ToMessages(feed, match.Groups[1].Value, ExtendedMessageTypes.End, requestId);

			MessageTypes type;

			if (feed == _lookupFeed && _currSystemType != null)
				type = _currSystemType.Value;
			else if (!_requestsType.TryGetValue(requestId, out type))
			{
				match = _regex.Match(line);

				if (match.Success)
				{
					var cmd = match.Groups[1].Value;
					line = match.Groups[2].Value;

					switch (cmd)
					{
						case "S":
							type = ExtendedMessageTypes.System;
							break;
						case "n":
							type = MessageTypes.Error;
							line = LocalizedStrings.Str704Params.Put(line);
							break;
						case "Z":
						case "2":
							type = MessageTypes.QuoteChange;
							break;
						case "F":
							type = ExtendedMessageTypes.Fundamental;
							break;
						case "P":
						case "Q":
							type = MessageTypes.Level1Change;
							break;
						case "N":
							type = MessageTypes.News;
							break;
						default:
							type = ExtendedMessageTypes.Data;
							break;
					}
				}
				else
					type = ExtendedMessageTypes.Data;
			}

			return ToMessages(feed, line, type, requestId);
		}
コード例 #9
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;
			}
		}
コード例 #10
0
		private IQFeedWrapper CreateFeed(EndPoint endPoint, string name)
		{
			var feed = new IQFeedWrapper(this, name, endPoint);
			
			feed.ProcessReply += line =>
			{
				IEnumerable<Message> messages;

				try
				{
					messages = ConvertToMessages(feed, line).ToArray();
				}
				catch (Exception ex)
				{
					ex = new InvalidOperationException(LocalizedStrings.Str2141Params.Put(line), ex);
					this.AddErrorLog(ex);
					messages = new[] { new ErrorMessage { Error = ex } };
				}

				foreach (var message in messages)
				{
					ProcessIQFeedMessage(feed, message);
				}
			};
			feed.ConnectionError += err =>
			{
				if (name == "LookupFeed")
					SendOutMessage(new ConnectMessage { Error = err });
				else
					SendOutError(err);

				//feed.Disconnect();
				//feed.Connect();
			};

			feed.Connect();

			return feed;
		}
コード例 #11
0
		/// <summary>
		/// Отправить сообщение.
		/// </summary>
		/// <param name="message">Сообщение.</param>
		protected override void OnSendInMessage(Message message)
		{
			switch (message.Type)
			{
				case MessageTypes.Reset:
				{
					_requestsType.Clear();
					_secIds.Clear();
					_candleParsers.Clear();
					_newsIds.Clear();

					_lookupResult.Clear();

					_currSystemType = null;

					if (_lookupFeed != null)
						SafeDisconnectFeed(ref _lookupFeed);

					if (_level1Feed != null)
						SafeDisconnectFeed(ref _level1Feed);

					if (_level2Feed != null)
						SafeDisconnectFeed(ref _level2Feed);

					if (_derivativeFeed != null)
						SafeDisconnectFeed(ref _derivativeFeed);

					SendOutMessage(new ResetMessage());

					break;
				}

				case MessageTypes.Connect:
				{
					_isDownloadSecurityFromSite = IsDownloadSecurityFromSite;

					_lookupFeed = CreateFeed(LookupAddress, "LookupFeed");
					_level1Feed = CreateFeed(Level1Address, "Level1Feed");
					_level2Feed = CreateFeed(Level2Address, "Level2Feed");
					_derivativeFeed = CreateFeed(DerivativeAddress, "DerivativeFeed");

					_level1Feed.SetLevel1FieldSet(new[]
						{
							Level1ColumnRegistry.Symbol,
							Level1ColumnRegistry.ExchangeId,
							Level1ColumnRegistry.LastTradeMarket,
							Level1ColumnRegistry.BidMarket,
							Level1ColumnRegistry.AskMarket
						}
						.Concat(Level1Columns)
						.Select(c => c.Name)
						.ToArray());

					break;
				}

				case MessageTypes.Disconnect:
				{
					SafeDisconnectFeed(ref _lookupFeed);
					SafeDisconnectFeed(ref _level1Feed);
					SafeDisconnectFeed(ref _level2Feed);
					SafeDisconnectFeed(ref _derivativeFeed);

					//_isCommonLookupDone = null;

					SendOutMessage(new DisconnectMessage());
					break;
				}

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

					var from = mdMsg.From.ToLocalTime(TimeHelper.Est);
					var to = mdMsg.To.ToLocalTime(TimeHelper.Est);

					switch (mdMsg.DataType)
					{
						case MarketDataTypes.Level1:
						{
							if (mdMsg.To == DateTimeOffset.MaxValue)
							{
								if (mdMsg.IsSubscribe)
									_level1Feed.SubscribeSymbol(mdMsg.SecurityId.SecurityCode);
								else
									_level1Feed.UnSubscribeSymbol(mdMsg.SecurityId.SecurityCode);
							}
							else
							{
								if (mdMsg.IsSubscribe)
								{
									_requestsType.Add(mdMsg.TransactionId, MessageTypes.Execution);
									_secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);

									if (mdMsg.Count != 0)
										_lookupFeed.RequestTicks(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, mdMsg.Count);
									else
										_lookupFeed.RequestTicks(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, from, to);
								}
							}

							break;
						}
						case MarketDataTypes.MarketDepth:
						{
							if (mdMsg.IsSubscribe)
								_level2Feed.SubscribeSymbol(mdMsg.SecurityId.SecurityCode);
							else
								_level2Feed.UnSubscribeSymbol(mdMsg.SecurityId.SecurityCode);

							break;
						}
						//case MarketDataTypes.Trades:
						//{
						//	if (mdMsg.To == DateTime.MaxValue)
						//	{
						//		if (mdMsg.IsSubscribe)
						//			_level1Feed.SubscribeSymbol(mdMsg.SecurityId.SecurityCode);
						//		else
						//			_level1Feed.UnSubscribeSymbol(mdMsg.SecurityId.SecurityCode);
						//	}
						//	else
						//	{
						//		if (mdMsg.IsSubscribe)
						//		{
						//			_requestsType.Add(mdMsg.TransactionId, MessageTypes.Execution);
						//			_lookupFeed.RequestTrades(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, mdMsg.From, mdMsg.To);
						//		}
						//	}

						//	break;
						//}
						case MarketDataTypes.News:
						{
							if (mdMsg.IsSubscribe)
							{
								if (mdMsg.NewsId.IsEmpty())
								{
									if (mdMsg.From.IsDefault())
										_level1Feed.SubscribeNews();
									else
									{
										_requestsType.Add(mdMsg.TransactionId, MessageTypes.News);
										_lookupFeed.RequestNewsHeadlines(mdMsg.TransactionId, from);
									}
								}
								else
								{
									var newsId = mdMsg.NewsId;
									_newsIds.Add(mdMsg.TransactionId, newsId);
									_requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.NewsStory);
									_lookupFeed.RequestNewsStory(mdMsg.TransactionId, newsId);
								}
							}
							else
								_level1Feed.UnSubscribeNews();

							break;
						}
						case MarketDataTypes.CandleTimeFrame:
						case MarketDataTypes.CandleTick:
						case MarketDataTypes.CandleVolume:
						case MarketDataTypes.CandleRange:
						case MarketDataTypes.CandlePnF:
						case MarketDataTypes.CandleRenko:
						{
							if (mdMsg.IsSubscribe)
							{
								// streaming
								if (from == DateTimeOffset.MaxValue && mdMsg.Count == 0)
								{
									string strArg, intervalType;
									GetCandleParams(mdMsg.DataType, mdMsg.Arg, out strArg, out intervalType);

									_requestsType.Add(mdMsg.TransactionId, mdMsg.DataType.ToCandleMessageType());
									_secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
									_candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleStreamingParser, mdMsg.Arg));

									_derivativeFeed.SubscribeCandles(mdMsg.SecurityId.SecurityCode, intervalType, strArg, from, mdMsg.TransactionId);
									break;
								}

								if (mdMsg.Arg is TimeSpan)
								{
									var tf = (TimeSpan)mdMsg.Arg;

									if (tf.Ticks == TimeHelper.TicksPerMonth)
									{
										_requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.HistoryExtraDayCandle);
										_secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
										_candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleParser, mdMsg.Arg));

										var count = mdMsg.Count;

										if (count == 0)
											count = ExchangeBoard.Associated.GetTimeFrameCount(new Range<DateTimeOffset>(mdMsg.From, mdMsg.To), tf);

										_lookupFeed.RequestMonthlyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, count);
									}
									else if (tf == TimeSpan.FromDays(7))
									{
										_requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.HistoryExtraDayCandle);
										_secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
										_candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleParser, mdMsg.Arg));

										var count = mdMsg.Count;

										if (count == 0)
											count = ExchangeBoard.Associated.GetTimeFrameCount(new Range<DateTimeOffset>(mdMsg.From, mdMsg.To), tf);

										_lookupFeed.RequestWeeklyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, count);
									}
									else if (tf == TimeSpan.FromDays(1))
									{
										_requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.HistoryExtraDayCandle);
										_secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
										_candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleParser, mdMsg.Arg));

										if (mdMsg.Count != 0)
											_lookupFeed.RequestDailyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, mdMsg.Count);
										else
											_lookupFeed.RequestDailyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, from, to);
									}
									else if (tf < TimeSpan.FromDays(1))
									{
										string strArg, intervalType;
										GetCandleParams(mdMsg.DataType, mdMsg.Arg, out strArg, out intervalType);

										_requestsType.Add(mdMsg.TransactionId, mdMsg.DataType.ToCandleMessageType());
										_secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
										_candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleIntradayParser, mdMsg.Arg));

										//var interval = tf.TotalSeconds.To<int>();

										if (mdMsg.Count != 0)
											_lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, mdMsg.Count);
										else
											_lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, from, to);
									}
									else
									{
										throw new InvalidOperationException(LocalizedStrings.Str2139Params.Put(tf));
									}
								}
								else
								{
									string strArg, intervalType;
									GetCandleParams(mdMsg.DataType, mdMsg.Arg, out strArg, out intervalType);

									if (mdMsg.Count != 0)
										_lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, mdMsg.Count);
									else
										_lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, from, to);
								}
							}
							else
							{
								_derivativeFeed.UnSubscribeCandles(mdMsg.SecurityId.SecurityCode, mdMsg.OriginalTransactionId);
							}

							break;
						}
						default:
						{
							SendOutMarketDataNotSupported(mdMsg.TransactionId);
							return;
						}
					}

					var reply = (MarketDataMessage)message.Clone();
					reply.OriginalTransactionId = mdMsg.TransactionId;
					SendOutMessage(reply);

					break;
				}

				case MessageTypes.SecurityLookup:
				{
					var lookupMsg = (SecurityLookupMessage)message;

					var securityTypes = new HashSet<SecurityTypes>();

					if (lookupMsg.SecurityTypes != null)
						securityTypes.AddRange(lookupMsg.SecurityTypes);
					else if (lookupMsg.SecurityType != null)
						securityTypes.Add(lookupMsg.SecurityType.Value);

					if (_isDownloadSecurityFromSite)
					{
						_isDownloadSecurityFromSite = false;

						using (var zip = new ZipArchive(
							SecuritiesFile.IsEmpty()
								? IQFeedHelper.DownloadSymbols().To<Stream>()
								: File.OpenRead(SecuritiesFile)))
						{
							var entry = zip.GetEntry("mktsymbols_v2.txt");

							using (var reader = entry.Open())
							{
								reader
									.ReadLines()
									.Skip(1)
									.Select(line => line.Split('\t'))
									.ForEach(parts =>
									{
										if (parts.Length == 9)
										{
											// mika 2014.09.16
											// below line has incorrect tabulation
											// CS.17.CB	CREDIT SUISSE NEW YORK 1.375% 05/26/17		NYSE	NYSE	BONDS			

											var list = parts.ToList();
											list.RemoveAt(2);

											parts = list.ToArray();
										}

										var secType = parts[4].ToSecurityType();

										if (secType == null)
											this.AddWarningLog(LocalizedStrings.Str2140Params.Put(parts[4]));

										if (secType != null && !securityTypes.Contains(secType.Value))
											return;

										var secCode = parts[0];
										var secName = parts[0];
										var boardCode = parts[2];

										SendOutMessage(new BoardMessage
										{
											Code = boardCode,
											ExchangeCode = boardCode
										});

										SendOutMessage(new SecurityMessage
										{
											SecurityId = new SecurityId
											{
												SecurityCode = secCode,
												BoardCode = boardCode
											},
											Name = secName,
											SecurityType = secType,
											OriginalTransactionId = lookupMsg.TransactionId
										});
									});
							}
						}

						break;
					}

					var requestedTypes = _securityTypes
						.Where(t => t.Value != null && securityTypes.Contains(t.Value.Value))
						.Select(i => i.Key.To<string>())
						.ToArray();

					_requestsType.Add(lookupMsg.TransactionId, MessageTypes.Security);
					_lookupResult.Add(lookupMsg.TransactionId, lookupMsg);

					var code = lookupMsg.SecurityId.SecurityCode;

					if (code.IsEmpty())
						code = "*";

					_lookupFeed.RequestSecurities(lookupMsg.TransactionId, IQFeedSearchField.Symbol, code, IQFeedFilterType.SecurityType, requestedTypes);
					break;
				}
			}
		}
コード例 #12
0
		private void SafeDisconnectFeed(ref IQFeedWrapper feed)
		{
			try
			{
				feed.Disconnect();
				feed = null;
			}
			catch (Exception ex)
			{
				SendOutError(ex);
			}
		}
コード例 #13
0
        private IEnumerable <Message> ParseMessages(IQFeedWrapper feed, string str, MessageTypes type, long requestId)
        {
            switch (type)
            {
            case ExtendedMessageTypes.System:
                yield return(new IQFeedSystemMessage(feed, str));

                break;

            case ExtendedMessageTypes.SecurityType:
            {
                var parts = str.SplitByComma();
                yield return(new IQFeedSecurityTypeMessage(parts[0].To <int>(), parts[1], parts[2]));

                break;
            }

            case ExtendedMessageTypes.ListedMarket:
            {
                var parts = str.SplitByComma();
                yield return(new IQFeedListedMarketMessage(parts[0].To <int>(), parts[1], parts[2]));

                break;
            }

            case ExtendedMessageTypes.Data:
                yield return(new IQFeedDataMessage(str));

                break;

            case ExtendedMessageTypes.End:
                yield return(new IQFeedEndMessage());

                break;

            case MessageTypes.Time:
                yield return(new TimeMessage {
                    ServerTime = str.ToDateTime("yyyyMMdd HH:mm:ss").ApplyTimeZone(TimeHelper.Est)
                });

                break;

            case MessageTypes.Security:
            {
                var parts = str.SplitByComma();

                yield return(new SecurityMessage
                    {
                        SecurityId = CreateSecurityId(parts[0], parts[1].To <int>()),
                        Name = parts[3],
                        OriginalTransactionId = requestId,
                        SecurityType = _securityTypes[parts[2].To <int>()],
                    });

                break;
            }

            case ExtendedMessageTypes.Fundamental:
            {
                foreach (var result in ToSecurityFundamentalMessages(str))
                {
                    yield return(result);
                }

                break;
            }

            case MessageTypes.Level1Change:
            {
                foreach (var result in ToSecurityUpdateMessage(str))
                {
                    yield return(result);
                }

                break;
            }

            case MessageTypes.Execution:
            {
                yield return(ToLevel1(str, _secIds[requestId]));

                break;
            }

            case MessageTypes.News:
                yield return(ToNewsMessage(str));

                break;

            case ExtendedMessageTypes.NewsStory:
            {
                yield return(new NewsMessage
                    {
                        Id = _newsIds[requestId],
                        Story = str.StripBrackets("<BEGIN>", "<END>"),
                        ServerTime = CurrentTime.Convert(TimeHelper.Est)
                    });

                break;
            }

            case MessageTypes.CandleTimeFrame:
            case MessageTypes.CandleTick:
            case MessageTypes.CandleVolume:
            case ExtendedMessageTypes.HistoryExtraDayCandle:
            {
                var parts = str.SplitByComma();

                var tuple = _candleParsers[requestId];

                var candleMsg = tuple.Item1(parts);

                candleMsg.OriginalTransactionId = requestId;
                candleMsg.SecurityId            = _secIds[requestId];

                if (tuple.Item2 is TimeSpan)
                {
                    var tf = (TimeSpan)tuple.Item2;

                    if (tf == TimeSpan.FromDays(1))
                    {
                        candleMsg.OpenTime  = candleMsg.CloseTime;
                        candleMsg.CloseTime = candleMsg.OpenTime.EndOfDay();
                    }
                    else                            // if (tf == TimeSpan.FromDays(7) || tf.Ticks == TimeHelper.TicksPerMonth)
                    {
                        candleMsg.CloseTime -= TimeSpan.FromTicks(1);
                        candleMsg.OpenTime   = tf.GetCandleBounds(candleMsg.CloseTime.ToLocalTime(TimeHelper.Est)).Min;
                    }
                }
                else
                {
                    candleMsg.OpenTime = candleMsg.CloseTime;
                }

                yield return(candleMsg);

                break;
            }

            case MessageTypes.QuoteChange:
            {
                var l1Msg = ToLevel2(str);

                if (l1Msg != null)
                {
                    yield return(l1Msg);
                }

                break;
            }

            case MessageTypes.Error:
                yield return(new ErrorMessage {
                    Error = new InvalidOperationException(str)
                });

                break;

            default:
                throw new InvalidOperationException(LocalizedStrings.Str2142Params.Put(type));
            }
        }
コード例 #14
0
        private IEnumerable <Message> ConvertToMessages(IQFeedWrapper feed, string line)
        {
            //Market Depth & NASDAQ Level 2 via TCP/IP
            //This is a deprecated message and only sent for backwards compatability
            if (line.CompareIgnoreCase("O"))
            {
                return(Enumerable.Empty <Message>());
            }

            long requestId = 0;

            var match = _regexRequestId.Match(line);

            if (match.Success)
            {
                requestId = match.Groups[1].Value.To <long>();
                line      = match.Groups[2].Value;
            }

            match = _regexError.Match(line);

            if (match.Success)
            {
                var text = match.Groups[1].Value;

                return(text.Equals("!NO_DATA!")
                                        ? Enumerable.Empty <Message>()
                                        : ToMessages(feed, text, MessageTypes.Error, requestId));
            }

            match = _regexTime.Match(line);

            if (match.Success)
            {
                return(ToMessages(feed, match.Groups[1].Value, MessageTypes.Time, requestId));
            }

            match = _regexLastMessage.Match(line);

            if (match.Success)
            {
                return(ToMessages(feed, match.Groups[1].Value, ExtendedMessageTypes.End, requestId));
            }

            MessageTypes type;

            if (feed == _lookupFeed && _currSystemType != null)
            {
                type = _currSystemType.Value;
            }
            else if (!_requestsType.TryGetValue(requestId, out type))
            {
                match = _regex.Match(line);

                if (match.Success)
                {
                    var cmd = match.Groups[1].Value;
                    line = match.Groups[2].Value;

                    switch (cmd)
                    {
                    case "S":
                        type = ExtendedMessageTypes.System;
                        break;

                    case "n":
                        type = MessageTypes.Error;
                        line = LocalizedStrings.Str704Params.Put(line);
                        break;

                    case "Z":
                    case "2":
                        type = MessageTypes.QuoteChange;
                        break;

                    case "F":
                        type = ExtendedMessageTypes.Fundamental;
                        break;

                    case "P":
                    case "Q":
                        type = MessageTypes.Level1Change;
                        break;

                    case "N":
                        type = MessageTypes.News;
                        break;

                    default:
                        type = ExtendedMessageTypes.Data;
                        break;
                    }
                }
                else
                {
                    type = ExtendedMessageTypes.Data;
                }
            }

            return(ToMessages(feed, line, type, requestId));
        }
コード例 #15
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;
            }
        }
コード例 #16
0
        /// <summary>
        /// Отправить сообщение.
        /// </summary>
        /// <param name="message">Сообщение.</param>
        protected override void OnSendInMessage(Message message)
        {
            switch (message.Type)
            {
            case MessageTypes.Reset:
            {
                _requestsType.Clear();
                _secIds.Clear();
                _candleParsers.Clear();
                _newsIds.Clear();

                _lookupResult.Clear();

                _currSystemType = null;

                if (_lookupFeed != null)
                {
                    SafeDisconnectFeed(ref _lookupFeed);
                }

                if (_level1Feed != null)
                {
                    SafeDisconnectFeed(ref _level1Feed);
                }

                if (_level2Feed != null)
                {
                    SafeDisconnectFeed(ref _level2Feed);
                }

                if (_derivativeFeed != null)
                {
                    SafeDisconnectFeed(ref _derivativeFeed);
                }

                SendOutMessage(new ResetMessage());

                break;
            }

            case MessageTypes.Connect:
            {
                _isDownloadSecurityFromSite = IsDownloadSecurityFromSite;

                _lookupFeed     = CreateFeed(LookupAddress, "LookupFeed");
                _level1Feed     = CreateFeed(Level1Address, "Level1Feed");
                _level2Feed     = CreateFeed(Level2Address, "Level2Feed");
                _derivativeFeed = CreateFeed(DerivativeAddress, "DerivativeFeed");

                _level1Feed.SetLevel1FieldSet(new[]
                    {
                        Level1ColumnRegistry.Symbol,
                        Level1ColumnRegistry.ExchangeId,
                        Level1ColumnRegistry.LastTradeMarket,
                        Level1ColumnRegistry.BidMarket,
                        Level1ColumnRegistry.AskMarket
                    }
                                              .Concat(Level1Columns)
                                              .Select(c => c.Name)
                                              .ToArray());

                break;
            }

            case MessageTypes.Disconnect:
            {
                SafeDisconnectFeed(ref _lookupFeed);
                SafeDisconnectFeed(ref _level1Feed);
                SafeDisconnectFeed(ref _level2Feed);
                SafeDisconnectFeed(ref _derivativeFeed);

                //_isCommonLookupDone = null;

                SendOutMessage(new DisconnectMessage());
                break;
            }

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

                var from = mdMsg.From.ToLocalTime(TimeHelper.Est);
                var to   = mdMsg.To.ToLocalTime(TimeHelper.Est);

                switch (mdMsg.DataType)
                {
                case MarketDataTypes.Level1:
                {
                    if (mdMsg.To == DateTimeOffset.MaxValue)
                    {
                        if (mdMsg.IsSubscribe)
                        {
                            _level1Feed.SubscribeSymbol(mdMsg.SecurityId.SecurityCode);
                        }
                        else
                        {
                            _level1Feed.UnSubscribeSymbol(mdMsg.SecurityId.SecurityCode);
                        }
                    }
                    else
                    {
                        if (mdMsg.IsSubscribe)
                        {
                            _requestsType.Add(mdMsg.TransactionId, MessageTypes.Execution);
                            _secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);

                            if (mdMsg.Count != 0)
                            {
                                _lookupFeed.RequestTicks(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, mdMsg.Count);
                            }
                            else
                            {
                                _lookupFeed.RequestTicks(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, from, to);
                            }
                        }
                    }

                    break;
                }

                case MarketDataTypes.MarketDepth:
                {
                    if (mdMsg.IsSubscribe)
                    {
                        _level2Feed.SubscribeSymbol(mdMsg.SecurityId.SecurityCode);
                    }
                    else
                    {
                        _level2Feed.UnSubscribeSymbol(mdMsg.SecurityId.SecurityCode);
                    }

                    break;
                }
                //case MarketDataTypes.Trades:
                //{
                //	if (mdMsg.To == DateTime.MaxValue)
                //	{
                //		if (mdMsg.IsSubscribe)
                //			_level1Feed.SubscribeSymbol(mdMsg.SecurityId.SecurityCode);
                //		else
                //			_level1Feed.UnSubscribeSymbol(mdMsg.SecurityId.SecurityCode);
                //	}
                //	else
                //	{
                //		if (mdMsg.IsSubscribe)
                //		{
                //			_requestsType.Add(mdMsg.TransactionId, MessageTypes.Execution);
                //			_lookupFeed.RequestTrades(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, mdMsg.From, mdMsg.To);
                //		}
                //	}

                //	break;
                //}
                case MarketDataTypes.News:
                {
                    if (mdMsg.IsSubscribe)
                    {
                        if (mdMsg.NewsId.IsEmpty())
                        {
                            if (mdMsg.From.IsDefault())
                            {
                                _level1Feed.SubscribeNews();
                            }
                            else
                            {
                                _requestsType.Add(mdMsg.TransactionId, MessageTypes.News);
                                _lookupFeed.RequestNewsHeadlines(mdMsg.TransactionId, from);
                            }
                        }
                        else
                        {
                            var newsId = mdMsg.NewsId;
                            _newsIds.Add(mdMsg.TransactionId, newsId);
                            _requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.NewsStory);
                            _lookupFeed.RequestNewsStory(mdMsg.TransactionId, newsId);
                        }
                    }
                    else
                    {
                        _level1Feed.UnSubscribeNews();
                    }

                    break;
                }

                case MarketDataTypes.CandleTimeFrame:
                case MarketDataTypes.CandleTick:
                case MarketDataTypes.CandleVolume:
                case MarketDataTypes.CandleRange:
                case MarketDataTypes.CandlePnF:
                case MarketDataTypes.CandleRenko:
                {
                    if (mdMsg.IsSubscribe)
                    {
                        // streaming
                        if (from == DateTimeOffset.MaxValue && mdMsg.Count == 0)
                        {
                            string strArg, intervalType;
                            GetCandleParams(mdMsg.DataType, mdMsg.Arg, out strArg, out intervalType);

                            _requestsType.Add(mdMsg.TransactionId, mdMsg.DataType.ToCandleMessageType());
                            _secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
                            _candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleStreamingParser, mdMsg.Arg));

                            _derivativeFeed.SubscribeCandles(mdMsg.SecurityId.SecurityCode, intervalType, strArg, from, mdMsg.TransactionId);
                            break;
                        }

                        if (mdMsg.Arg is TimeSpan)
                        {
                            var tf = (TimeSpan)mdMsg.Arg;

                            if (tf.Ticks == TimeHelper.TicksPerMonth)
                            {
                                _requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.HistoryExtraDayCandle);
                                _secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
                                _candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleParser, mdMsg.Arg));

                                var count = mdMsg.Count;

                                if (count == 0)
                                {
                                    count = ExchangeBoard.Associated.GetTimeFrameCount(new Range <DateTimeOffset>(mdMsg.From, mdMsg.To), tf);
                                }

                                _lookupFeed.RequestMonthlyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, count);
                            }
                            else if (tf == TimeSpan.FromDays(7))
                            {
                                _requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.HistoryExtraDayCandle);
                                _secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
                                _candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleParser, mdMsg.Arg));

                                var count = mdMsg.Count;

                                if (count == 0)
                                {
                                    count = ExchangeBoard.Associated.GetTimeFrameCount(new Range <DateTimeOffset>(mdMsg.From, mdMsg.To), tf);
                                }

                                _lookupFeed.RequestWeeklyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, count);
                            }
                            else if (tf == TimeSpan.FromDays(1))
                            {
                                _requestsType.Add(mdMsg.TransactionId, ExtendedMessageTypes.HistoryExtraDayCandle);
                                _secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
                                _candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleParser, mdMsg.Arg));

                                if (mdMsg.Count != 0)
                                {
                                    _lookupFeed.RequestDailyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, mdMsg.Count);
                                }
                                else
                                {
                                    _lookupFeed.RequestDailyCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, from, to);
                                }
                            }
                            else if (tf < TimeSpan.FromDays(1))
                            {
                                string strArg, intervalType;
                                GetCandleParams(mdMsg.DataType, mdMsg.Arg, out strArg, out intervalType);

                                _requestsType.Add(mdMsg.TransactionId, mdMsg.DataType.ToCandleMessageType());
                                _secIds.Add(mdMsg.TransactionId, mdMsg.SecurityId);
                                _candleParsers.Add(mdMsg.TransactionId, Tuple.Create(_candleIntradayParser, mdMsg.Arg));

                                //var interval = tf.TotalSeconds.To<int>();

                                if (mdMsg.Count != 0)
                                {
                                    _lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, mdMsg.Count);
                                }
                                else
                                {
                                    _lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, from, to);
                                }
                            }
                            else
                            {
                                throw new InvalidOperationException(LocalizedStrings.Str2139Params.Put(tf));
                            }
                        }
                        else
                        {
                            string strArg, intervalType;
                            GetCandleParams(mdMsg.DataType, mdMsg.Arg, out strArg, out intervalType);

                            if (mdMsg.Count != 0)
                            {
                                _lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, mdMsg.Count);
                            }
                            else
                            {
                                _lookupFeed.RequestCandles(mdMsg.TransactionId, mdMsg.SecurityId.SecurityCode, intervalType, strArg, from, to);
                            }
                        }
                    }
                    else
                    {
                        _derivativeFeed.UnSubscribeCandles(mdMsg.SecurityId.SecurityCode, mdMsg.OriginalTransactionId);
                    }

                    break;
                }

                default:
                {
                    SendOutMarketDataNotSupported(mdMsg.TransactionId);
                    return;
                }
                }

                var reply = (MarketDataMessage)message.Clone();
                reply.OriginalTransactionId = mdMsg.TransactionId;
                SendOutMessage(reply);

                break;
            }

            case MessageTypes.SecurityLookup:
            {
                var lookupMsg = (SecurityLookupMessage)message;

                var securityTypes = new HashSet <SecurityTypes>();

                if (lookupMsg.SecurityTypes != null)
                {
                    securityTypes.AddRange(lookupMsg.SecurityTypes);
                }
                else if (lookupMsg.SecurityType != null)
                {
                    securityTypes.Add(lookupMsg.SecurityType.Value);
                }

                if (_isDownloadSecurityFromSite)
                {
                    _isDownloadSecurityFromSite = false;

                    using (var zip = new ZipArchive(
                               SecuritiesFile.IsEmpty()
                                                                ? IQFeedHelper.DownloadSymbols().To <Stream>()
                                                                : File.OpenRead(SecuritiesFile)))
                    {
                        var entry = zip.GetEntry("mktsymbols_v2.txt");

                        using (var reader = entry.Open())
                        {
                            reader
                            .ReadLines()
                            .Skip(1)
                            .Select(line => line.Split('\t'))
                            .ForEach(parts =>
                                {
                                    if (parts.Length == 9)
                                    {
                                        // mika 2014.09.16
                                        // below line has incorrect tabulation
                                        // CS.17.CB	CREDIT SUISSE NEW YORK 1.375% 05/26/17		NYSE	NYSE	BONDS

                                        var list = parts.ToList();
                                        list.RemoveAt(2);

                                        parts = list.ToArray();
                                    }

                                    var secType = parts[4].ToSecurityType();

                                    if (secType == null)
                                    {
                                        this.AddWarningLog(LocalizedStrings.Str2140Params.Put(parts[4]));
                                    }

                                    if (secType != null && !securityTypes.Contains(secType.Value))
                                    {
                                        return;
                                    }

                                    var secCode   = parts[0];
                                    var secName   = parts[0];
                                    var boardCode = parts[2];

                                    SendOutMessage(new BoardMessage
                                    {
                                        Code         = boardCode,
                                        ExchangeCode = boardCode
                                    });

                                    SendOutMessage(new SecurityMessage
                                    {
                                        SecurityId = new SecurityId
                                        {
                                            SecurityCode = secCode,
                                            BoardCode    = boardCode
                                        },
                                        Name                  = secName,
                                        SecurityType          = secType,
                                        OriginalTransactionId = lookupMsg.TransactionId
                                    });
                                });
                        }
                    }

                    break;
                }

                var requestedTypes = _securityTypes
                                     .Where(t => t.Value != null && securityTypes.Contains(t.Value.Value))
                                     .Select(i => i.Key.To <string>())
                                     .ToArray();

                _requestsType.Add(lookupMsg.TransactionId, MessageTypes.Security);
                _lookupResult.Add(lookupMsg.TransactionId, lookupMsg);

                var code = lookupMsg.SecurityId.SecurityCode;

                if (code.IsEmpty())
                {
                    code = "*";
                }

                _lookupFeed.RequestSecurities(lookupMsg.TransactionId, IQFeedSearchField.Symbol, code, IQFeedFilterType.SecurityType, requestedTypes);
                break;
            }
            }
        }