Exemple #1
0
		private void ProcessMarketDataMessage(MarketDataMessage message)
		{
			_requests.Enqueue(new LuaRequest
			{
				MessageType = message.Type,
				DataType = message.DataType,
				SecurityId = new SecurityId
				{
					SecurityCode = message.SecurityId.SecurityCode,
					BoardCode = _securityClassInfo.GetSecurityClass(message.SecurityId)
				},
				IsSubscribe = message.IsSubscribe,
				TransactionId = message.TransactionId
			});

			var result = (MarketDataMessage)message.Clone();
			result.OriginalTransactionId = message.TransactionId;
			_fixServer.SendInMessage(result);
		}
		private void ProcessMarketData(MarketDataMessage mdMsg)
		{
			var secCode = mdMsg.SecurityId.SecurityCode;
			var boardCode = mdMsg.SecurityId.BoardCode;

			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				{
					if (mdMsg.IsSubscribe)
						_client.SubscribeQuote(secCode, boardCode);
					else
						_client.UnsubsribeQuote(secCode, boardCode);

					break;
				}

				case MarketDataTypes.MarketDepth:
				{
					if (mdMsg.IsSubscribe)
						_client.SubscribeLevel2(secCode, boardCode);
					else
						_client.UnsubsribeLevel2(secCode, boardCode);

					break;
				}

				case MarketDataTypes.Trades:
				{
					if (mdMsg.IsSubscribe)
					{
						_subscribedSecuritiesToTrade.Add(secCode);
						_client.SubscribeQuote(secCode, boardCode);
					}
					else
					{
						_subscribedSecuritiesToTrade.Remove(secCode);
						_client.UnsubsribeQuote(secCode, boardCode);
					}

					break;
				}
				
				case MarketDataTypes.News:
				{
					if (mdMsg.IsSubscribe)
						_client.SubscribeNews();
					else
						_client.UnsubscribeNews();

					break;
				}

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

			var reply = (MarketDataMessage)mdMsg.Clone();
			reply.OriginalTransactionId = mdMsg.TransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketDataMessage(MarketDataMessage mdMsg)
		{
			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				case MarketDataTypes.Trades:
				{
					var key = Tuple.Create(MarketDataTypes.Level1, mdMsg.SecurityId, (object)null);

					if (mdMsg.IsSubscribe)
					{
						_requestIds.Add(key, mdMsg.TransactionId);
						SubscribeMarketData(mdMsg, Fields, false, false);
					}
					else
						UnSubscribeMarketData(_requestIds[key]);

					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					var key = Tuple.Create(mdMsg.DataType, mdMsg.SecurityId, (object)null);

					if (mdMsg.IsSubscribe)
					{
						_requestIds.Add(key, mdMsg.TransactionId);
						SubscribeMarketDepth(mdMsg);
					}
					else
						UnSubscriveMarketDepth(_requestIds[key]);

					break;
				}
				case MarketDataTypes.News:
				{
					if (mdMsg.IsSubscribe)
						SubscribeNewsBulletins(true);
					else
						UnSubscribeNewsBulletins();

					break;
				}
				case MarketDataTypes.CandleTimeFrame:
				{
					var isRealTime = mdMsg.To == null;
					var key = Tuple.Create(mdMsg.DataType, mdMsg.SecurityId, (object)Tuple.Create(mdMsg.Arg, isRealTime));

					if (mdMsg.IsSubscribe)
					{
						_requestIds.Add(key, mdMsg.TransactionId);

						if (isRealTime)
							SubscribeRealTimeCandles(mdMsg);
						else
							SubscribeHistoricalCandles(mdMsg, CandleDataTypes.Trades);
					}
					else
					{
						var requestId = _requestIds[key];

						if (isRealTime)
							UnSubscribeRealTimeCandles(mdMsg, requestId);
						else
						{
							ProcessRequest(RequestMessages.UnSubscribeHistoricalData, 0, ServerVersions.V1,
								socket => socket.Send(requestId));
						}
					}

					break;
				}
				case ExtendedMarketDataTypes.Scanner:
				{
					var scannerMsg = (ScannerMarketDataMessage)mdMsg;

					var key = Tuple.Create(mdMsg.DataType, mdMsg.SecurityId, (object)scannerMsg.Filter);

					if (mdMsg.IsSubscribe)
					{
						_requestIds.Add(key, mdMsg.TransactionId);
						SubscribeScanner(scannerMsg);
					}
					else
						UnSubscribeScanner(_requestIds[key]);

					break;
				}
				case ExtendedMarketDataTypes.FundamentalReport:
				{
					var reportMsg = (FundamentalReportMarketDataMessage)mdMsg;

					var key = Tuple.Create(mdMsg.DataType, mdMsg.SecurityId, (object)reportMsg.Report);

					if (reportMsg.IsSubscribe)
					{
						_requestIds.Add(key, mdMsg.TransactionId);
						SubscribeFundamentalReport(reportMsg);
					}
					else
						UnSubscribeFundamentalReport(_requestIds[key]);

					break;
				}
				case ExtendedMarketDataTypes.OptionCalc:
				{
					var optionMsg = (OptionCalcMarketDataMessage)mdMsg;

					var key = Tuple.Create(mdMsg.DataType, mdMsg.SecurityId, (object)Tuple.Create(optionMsg.OptionPrice, optionMsg.ImpliedVolatility, optionMsg.AssetPrice));

					if (optionMsg.IsSubscribe)
					{
						_requestIds.Add(key, mdMsg.TransactionId);

						SubscribeCalculateOptionPrice(optionMsg);
						SubscribeCalculateImpliedVolatility(optionMsg);
					}
					else
					{
						var requestId = _requestIds[key];

						UnSubscribeCalculateOptionPrice(requestId);
						UnSubscribeCalculateImpliedVolatility(requestId);
					}

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

			var reply = (MarketDataMessage)mdMsg.Clone();
			reply.OriginalTransactionId = mdMsg.OriginalTransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketDataMessage(MarketDataMessage mdMsg)
		{
			if (!mdMsg.IsSubscribe)
				return;

			if (mdMsg.SecurityId.Native == null)
				throw new InvalidOperationException(LocalizedStrings.Str3392Params.Put(mdMsg.SecurityId.SecurityCode));

			var lmaxId = (long)mdMsg.SecurityId.Native;

			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				case MarketDataTypes.Trades:
				{
					_session.Subscribe(new OrderBookStatusSubscriptionRequest(lmaxId), () => { }, CreateErrorHandler("OrderBookStatusSubscriptionRequest"));
					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					_session.Subscribe(new OrderBookSubscriptionRequest(lmaxId), () => { }, CreateErrorHandler("OrderBookSubscriptionRequest"));
					break;
				}
				case MarketDataTypes.CandleTimeFrame:
				{
					IHistoricMarketDataRequest request;

					var tf = (TimeSpan)mdMsg.Arg;
					var from = (mdMsg.From ?? DateTimeOffset.MinValue).UtcDateTime;
					var to = (mdMsg.To ?? DateTimeOffset.MaxValue).UtcDateTime;

					if (tf.Ticks == 1)
						request = new TopOfBookHistoricMarketDataRequest(mdMsg.TransactionId, lmaxId, from, to, Format.Csv);
					else
					{
						Resolution resolution;

						if (tf == TimeSpan.FromMinutes(1))
							resolution = Resolution.Minute;
						else if (tf == TimeSpan.FromDays(1))
							resolution = Resolution.Day;
						else
							throw new InvalidOperationException(LocalizedStrings.Str3393Params.Put(tf));

						request = new AggregateHistoricMarketDataRequest(mdMsg.TransactionId, lmaxId, from, to, resolution, Format.Csv, Option.Bid, Option.Ask);
					}

					if (!_isHistoricalSubscribed)
					{
						_session.Subscribe(new HistoricMarketDataSubscriptionRequest(), () => { }, CreateErrorHandler("HistoricMarketDataSubscriptionRequest"));
						_isHistoricalSubscribed = true;
					}

					_session.RequestHistoricMarketData(request, () => { }, CreateErrorHandler("RequestHistoricMarketData"));
					break;
				}
				default:
				{
					SendOutMarketDataNotSupported(mdMsg.TransactionId);
					return;
				}
			}

			var result = (MarketDataMessage)mdMsg.Clone();
			result.OriginalTransactionId = mdMsg.TransactionId;
			SendOutMessage(result);
		}
		private void ProcessMarketDataMessage(MarketDataMessage mdMsg)
		{
			var smartId = (string)mdMsg.SecurityId.Native;

			if (smartId.IsEmpty())
				throw new InvalidOperationException(LocalizedStrings.Str1853Params.Put(mdMsg.SecurityId));

			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				{
					if (mdMsg.IsSubscribe)
						_wrapper.SubscribeSecurity(smartId);
					else
						_wrapper.UnSubscribeSecurity(smartId);

					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					if (mdMsg.IsSubscribe)
						_wrapper.SubscribeMarketDepth(smartId);
					else
						_wrapper.UnSubscribeMarketDepth(smartId);

					break;
				}
				case MarketDataTypes.Trades:
				{
					if (mdMsg.From.IsDefault())
					{
						if (mdMsg.IsSubscribe)
							_wrapper.SubscribeTrades(smartId);
						else
							_wrapper.UnSubscribeTrades(smartId);
					}
					else
					{
						const int maxTradeCount = 1000000;
						this.AddDebugLog("RequestHistoryTrades SecId = {0} From {1} Count = {2}", smartId, mdMsg.From, maxTradeCount);
						_wrapper.RequestHistoryTrades(smartId, mdMsg.From.ToLocalTime(TimeHelper.Moscow), maxTradeCount);
					}

					break;
				}
				case MarketDataTypes.CandleTimeFrame:
				{
					var count = mdMsg.Count;
					var direction = (SmartComHistoryDirections)mdMsg.ExtensionInfo["Direction"];

					if (direction == SmartComHistoryDirections.Forward)
						count = -count;

					var tf = (TimeSpan)mdMsg.Arg;

					_candleTransactions.SafeAdd(smartId)[tf] = Tuple.Create(mdMsg.TransactionId, new List<CandleMessage>());

					this.AddDebugLog("RequestHistoryBars SecId {0} TF {1} From {2} Count {3}", smartId, tf, mdMsg.From, count);
					_wrapper.RequestHistoryBars(smartId, tf, mdMsg.From.ToLocalTime(TimeHelper.Moscow), (int)count);

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

			var reply = (MarketDataMessage)mdMsg.Clone();
			reply.OriginalTransactionId = mdMsg.TransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketDataMessage(MarketDataMessage mdMsg)
		{
			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				{
					SendCommand(mdMsg.IsSubscribe
									? new SubscribeMessage { Quotations = { mdMsg.SecurityId } }
									: new UnsubscribeMessage { Quotations = { mdMsg.SecurityId } });

					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					SendCommand(mdMsg.IsSubscribe
									? new SubscribeMessage { Quotes = { mdMsg.SecurityId } }
									: new UnsubscribeMessage { Quotes = { mdMsg.SecurityId } });

					break;
				}
				case MarketDataTypes.Trades:
				{
					if (mdMsg.IsSubscribe)
					{
						//Подписаться/отписаться на тики можно двумя способами:
						//SubscribeMessage/UnsubscribeMessage - тики приходят с момента подписки
						//SubscribeTicksMessage - Тики приходят с момента подиски(TradeNo = 0), или с любого номера. При повторном запросе отписка получения тиков по предыдущему запросу.


						//var command = new SubscribeMessage();
						//command.AllTrades.Add(security.GetTransaqId());

						//ApiClient.Send(new Tuple<BaseCommandMessage, Action<BaseResponse>>(command, ProcessResult));

						//---

						_registeredSecurityIds.Add(mdMsg.SecurityId);

						var command = new SubscribeTicksMessage { Filter = true }; //Filter только сделки нормально периода торгов

						foreach (var id in _registeredSecurityIds)
						{
							command.Items.Add(new SubscribeTicksSecurity
							{
								SecId = (int)id.Native,
								// http://stocksharp.com/forum/yaf_postsm35978_Obnovlieniie-Tranzak-do-viersii-2-16-1.aspx#post35978
								//TradeNo = id.Equals(mdMsg.SecurityId) ? 1 : 0,
								TradeNo = 1,
							});
						}

						SendCommand(command);
					}
					else
					{
						//var command = new UnsubscribeMessage();
						//command.AllTrades.Add(security.GetTransaqId());

						//ApiClient.Send(new Tuple<BaseCommandMessage, Action<BaseResponse>>(command, ProcessResult));

						//---

						_registeredSecurityIds.Remove(mdMsg.SecurityId);

						var command = new SubscribeTicksMessage { Filter = true }; //Filter только сделки нормально периода торгов

						foreach (var id in _registeredSecurityIds)
						{
							command.Items.Add(new SubscribeTicksSecurity
							{
								SecId = (int)id.Native,
								TradeNo = 0,
							});
						}

						SendCommand(command);
					}

					break;
				}
				case MarketDataTypes.News:
				{
					if (mdMsg.IsSubscribe)
					{
						if (mdMsg.NewsId.IsEmpty())
						{
							var count = mdMsg.Count;

							if (count == null)
								count = MaxNewsHeaderCount;
							else
							{
								if (count < 0)
									throw new InvalidOperationException(LocalizedStrings.Str3511Params.Put(count));

								if (count > MaxNewsHeaderCount)
									throw new InvalidOperationException(LocalizedStrings.Str3512Params.Put(count, MaxNewsHeaderCount));
							}
							
							SendCommand(new RequestOldNewsMessage { Count = (int)count.Value });
						}
						else
						{
							SendCommand(new RequestNewsBodyMessage { NewsId = mdMsg.NewsId.To<int>() });
						}
					}

					break;
				}
				case MarketDataTypes.CandleTimeFrame:
				{
					if (mdMsg.IsSubscribe)
					{
						var periodId = _candlePeriods.GetKeys((TimeSpan)mdMsg.Arg).First();
						var secId = (int)mdMsg.SecurityId.Native;
						var key = Tuple.Create(secId, periodId);

						_candleTransactions.Add(key, mdMsg.TransactionId);

						var command = new RequestHistoryDataMessage
						{
							SecId = secId,
							Period = periodId,
							Count = mdMsg.Count ?? 0,
							Reset = mdMsg.To == null,
						};

						try
						{
							SendCommand(command);
						}
						catch (Exception)
						{
							_candleTransactions.Remove(key);
							throw;
						}
					}

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

			var reply = (MarketDataMessage)mdMsg.Clone();
			reply.OriginalTransactionId = mdMsg.TransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketDataMessage(MarketDataMessage message)
		{
			switch (message.DataType)
			{
				case MarketDataTypes.Level1:
				{
					var instrument = message.SecurityId.ToOanda();

					if (message.IsSubscribe)
						_streamigClient.SubscribePricesStreaming(GetAccountId(), instrument);
					else
						_streamigClient.UnSubscribePricesStreaming(instrument);

					break;
				}
				//case MarketDataTypes.MarketDepth:
				//	break;
				case MarketDataTypes.News:
				{
					if (message.IsSubscribe)
					{
						var calendar = _restClient.GetCalendar(message.SecurityId.ToOanda(),
							(int)(3600 * (message.Count ?? 1)));

						foreach (var item in calendar)
						{
							SendOutMessage(new NewsMessage
							{
								//OriginalTransactionId = message.TransactionId,
								SecurityId = message.SecurityId,
								ServerTime = TimeHelper.GregorianStart.AddSeconds(item.TimeStamp).ApplyTimeZone(TimeZoneInfo.Utc),
								Headline = item.Title,
								Story = "unit={0} curr={1} market={2} forecast={3} previous={4} actual={5}"
									.Put(item.Unit, item.Currency, item.Market, item.Forecast, item.Previous, item.Actual),
							});
						}
					}

					break;
				}
				case MarketDataTypes.CandleTimeFrame:
				{
					if (message.IsSubscribe)
					{
						var from = message.From;

						while (true)
						{
							var candles = _restClient.GetCandles(message.SecurityId.ToOanda(),
								((TimeSpan)message.Arg).ToOanda(), message.Count ?? 0, (from ?? DateTimeOffset.MinValue).ToOanda());

							var count = 0;

							foreach (var candle in candles)
							{
								count++;

								var time = candle.Time.FromOanda();

								SendOutMessage(new TimeFrameCandleMessage
								{
									OriginalTransactionId = message.TransactionId,
									OpenTime = time,
									SecurityId = message.SecurityId,
									OpenPrice = (decimal)candle.Open,
									HighPrice = (decimal)candle.High,
									LowPrice = (decimal)candle.Low,
									ClosePrice = (decimal)candle.Close,
									TotalVolume = (decimal)candle.Volume,
									State = candle.Complete ? CandleStates.Finished : CandleStates.Active
								});

								from = time;
							}

							if (message.Count == null && count == 500)
								continue;

							break;
						}
					}

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

			var reply = (MarketDataMessage)message.Clone();
			reply.OriginalTransactionId = message.TransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketDataMessage(MarketDataMessage message)
		{
			switch (message.DataType)
			{
				case MarketDataTypes.Level1:
				{
					if (message.SecurityId.Native is int)
					{
						if (message.IsSubscribe)
							Wrapper.RegisterLevel1((int)message.SecurityId.Native);
						else
							Wrapper.UnRegisterLevel1((int)message.SecurityId.Native);
					}
					else
						throw new InvalidOperationException(LocalizedStrings.Str2253Params.Put(message.SecurityId));

					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					if (message.SecurityId.Native is int)
					{
						if (message.IsSubscribe)
							Wrapper.RegisterMarketDepth((int)message.SecurityId.Native);
						else
							Wrapper.UnRegisterMarketDepth((int)message.SecurityId.Native);
					}
					else
						throw new InvalidOperationException(LocalizedStrings.Str2253Params.Put(message.SecurityId));

					break;
				}
				case MarketDataTypes.Trades:
				{
					if (message.SecurityId.Native is int)
					{
						if (message.IsSubscribe)
							Wrapper.RegisterTrades((int)message.SecurityId.Native);
						else
							Wrapper.UnRegisterTrades((int)message.SecurityId.Native);
					}
					else
						throw new InvalidOperationException(LocalizedStrings.Str2253Params.Put(message.SecurityId));

					break;
				}
				case MarketDataTypes.News:
				{
					if (!message.NewsId.IsEmpty())
						throw new NotSupportedException(LocalizedStrings.Str1617);

					if (message.IsSubscribe)
						Wrapper.StartExportNews();
					else
						Wrapper.StopExportNews();

					break;
				}
				case MarketDataTypes.CandleTimeFrame:
				{
					if (message.IsSubscribe)
					{
						Wrapper.LookupCandles(message);
					}

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

			var reply = (MarketDataMessage)message.Clone();
			reply.OriginalTransactionId = message.TransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketData(MarketDataMessage mdMsg)
		{
			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				{
					//if (mdMsg.IsSubscribe)
					//	_subscribedLevel1.Add(secCode);
					//else
					//	_subscribedLevel1.Remove(secCode);

					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					if (mdMsg.IsSubscribe)
					{
						_subscribedDepths.Add(mdMsg.SecurityId, mdMsg.MaxDepth);

						if (_subscribedDepths.Count == 1)
							_pusherClient.SubscribeDepths();
					}
					else
					{
						_subscribedDepths.Remove(mdMsg.SecurityId);

						if (_subscribedDepths.Count == 0)
							_pusherClient.UnSubscribeDepths();
					}

					break;
				}
				case MarketDataTypes.Trades:
				{
					if (mdMsg.IsSubscribe)
					{
						if (mdMsg.From == DateTime.Today)
						{
							_httpClient.RequestTransactions().Select(t => new ExecutionMessage
							{
								ExecutionType = ExecutionTypes.Tick,
								SecurityId = _btcUsd,
								TradeId = t.Id,
								TradePrice = (decimal)t.Price,
								Volume = (decimal)t.Amount,
								ServerTime = t.Time.ApplyTimeZone(TimeZoneInfo.Utc)
							}).ForEach(SendOutMessage);
						}

						_subscribedTicks.Add(mdMsg.SecurityId);

						if (_subscribedTicks.Count == 1)
							_pusherClient.SubscribeTrades();
					}
					else
					{
						_subscribedTicks.Remove(mdMsg.SecurityId);

						if (_subscribedTicks.Count == 0)
							_pusherClient.UnSubscribeTrades();
					}

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

			var reply = (MarketDataMessage)mdMsg.Clone();
			reply.OriginalTransactionId = mdMsg.OriginalTransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketData(MarketDataMessage mdMsg)
		{
			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				{
					if (mdMsg.IsSubscribe)
						_subscribedLevel1.Add(mdMsg.SecurityId);
					else
						_subscribedLevel1.Remove(mdMsg.SecurityId);

					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					if (mdMsg.IsSubscribe)
						_subscribedDepths.Add(mdMsg.SecurityId, mdMsg.MaxDepth ?? MarketDataMessage.DefaultMaxDepth);
					else
						_subscribedDepths.Remove(mdMsg.SecurityId);

					break;
				}
				case MarketDataTypes.Trades:
				{
					if (mdMsg.IsSubscribe)
						_subscribedTicks.Add(mdMsg.SecurityId);
					else
						_subscribedTicks.Remove(mdMsg.SecurityId);

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

			var reply = (MarketDataMessage)mdMsg.Clone();
			reply.OriginalTransactionId = mdMsg.OriginalTransactionId;
			SendOutMessage(reply);
		}
		private void ProcessMarketDataMessage(MarketDataMessage mdMsg)
		{
			var secCode = mdMsg.SecurityId.SecurityCode;
			var boardCode = mdMsg.SecurityId.BoardCode;

			switch (mdMsg.DataType)
			{
				case MarketDataTypes.Level1:
				{
					if (mdMsg.IsSubscribe)
						_client.Session.subscribe(boardCode, secCode, SubscriptionFlags.All & ~(SubscriptionFlags.Prints | SubscriptionFlags.PrintsCond | SubscriptionFlags.Quotes), mdMsg.TransactionId);
					else
						_client.Session.unsubscribe(boardCode, secCode);

					break;
				}
				case MarketDataTypes.MarketDepth:
				{
					if (mdMsg.IsSubscribe)
					{
						_client.Session.rebuildBook(boardCode, secCode, mdMsg.TransactionId);
						_client.Session.subscribe(boardCode, secCode, SubscriptionFlags.Quotes, mdMsg.TransactionId);
					}
					else
						_client.Session.unsubscribe(boardCode, secCode);

					break;
				}
				case MarketDataTypes.Trades:
				{
					if (mdMsg.From == null || mdMsg.To == null)
					{
						if (mdMsg.IsSubscribe)
							_client.Session.subscribe(boardCode, secCode, SubscriptionFlags.Prints | SubscriptionFlags.PrintsCond, mdMsg.TransactionId);
						else
							_client.Session.unsubscribe(boardCode, secCode);
					}
					else
						_client.Session.replayTrades(boardCode, secCode, mdMsg.From.Value.ToSsboe(), mdMsg.To.Value.ToSsboe(), mdMsg.TransactionId);

					break;
				}
				//case MarketDataTypes.OrderLog:
				//	break;
				//case MarketDataTypes.News:
				//	break;
				case MarketDataTypes.CandleTimeFrame:
				{
					if (mdMsg.From == null || mdMsg.To == null)
					{
						if (mdMsg.IsSubscribe)
							_client.Session.subscribeTimeBar(boardCode, secCode, mdMsg.TransactionId);
						else
							_client.Session.unsubscribeTimeBar(boardCode, secCode);
					}
					else
						_client.Session.replayTimeBars(boardCode, secCode, mdMsg.From.Value.ToSsboe(), mdMsg.To.Value.ToSsboe(), mdMsg.TransactionId);

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

			var reply = (MarketDataMessage)mdMsg.Clone();
			reply.OriginalTransactionId = mdMsg.TransactionId;
			SendOutMessage(reply);
		}
		private void RaiseMarketDataMessage(MarketDataMessage message, Exception error)
		{
			var reply = (MarketDataMessage)message.Clone();
			reply.OriginalTransactionId = message.TransactionId;
			reply.Error = error;
			SendOutMessage(reply);
		}