public void UnsubscribeCandles(CandleSeries series) { var tuple = _subscriptionDates.TryGetValue(series.Security.Id); if(tuple == null) return; var msg = new MarketDataMessage().FillSecurityInfo(this, series.Security); msg.TransactionId = TransactionIdGenerator.GetNextId(); msg.OriginalTransactionId = tuple.Item2; msg.SecurityId = GetSecurityId(series.Security); msg.DataType = MarketDataTypes.CandleTimeFrame; msg.IsSubscribe = false; msg.From = tuple.Item1; msg.Arg = series.Arg; SendInMessage(msg); UnSubscribeMarketData(series.Security, MarketDataTypes.CandleTimeFrame); }
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); }
public void SubscribeCandles(CandleSeries series) { var transId = TransactionIdGenerator.GetNextId(); _subscriptionDates[series.Security.Id] = Tuple.Create(series.From, transId); var msg = new MarketDataMessage().FillSecurityInfo(this, series.Security); msg.TransactionId = transId; msg.SecurityId = GetSecurityId(series.Security); msg.DataType = MarketDataTypes.CandleTimeFrame; msg.IsSubscribe = true; msg.From = series.From; msg.Arg = (TimeSpan)series.Arg; _lastCandles.Remove(Tuple.Create(msg.SecurityId, msg.Arg)); SendInMessage(msg); SubscribeMarketData(series.Security, MarketDataTypes.CandleTimeFrame); }
public void SubscribeCandles(CandleSeries series) { if (!IsConnected) { _subscribersBuffer.Add(series); return; } var key = new SubscriptionKey(series.Security.Id, (TimeSpan) series.Arg); var transId = TransactionIdGenerator.GetNextId(); var subscription = _candleSubscriptions.TryGetValue(key); if (subscription != null) { Candles?.Invoke(series, subscription.CandleBuilder.AllCandles); subscription.AddSubscriber(series); return; } subscription = new CandleSubscription(series.Security, series.From, (TimeSpan) series.Arg, transId); subscription.AddSubscriber(series); _candleSubscriptions.Add(key, subscription); subscription.CandleBuilder.Candle += CandleBuilderOnCandle; var msg = new MarketDataMessage().FillSecurityInfo(this, series.Security); msg.TransactionId = transId; msg.SecurityId = GetSecurityId(series.Security); msg.DataType = MarketDataTypes.CandleTimeFrame; msg.IsSubscribe = true; msg.From = series.From; msg.Arg = series.Arg; SendInMessage(msg); SubscribeMarketData(series.Security, MarketDataTypes.CandleTimeFrame); }
private void SubscribeCandles(CandleSeries series, DateTimeOffset from, DateTimeOffset to, long transactionId) { var mdMsg = new MarketDataMessage { DataType = GetCandleType(series.CandleType), TransactionId = transactionId, From = from, To = to, Arg = series.Arg, IsSubscribe = true, }.FillSecurityInfo(this, series.Security); _candleSeries.Add(transactionId, series); SendInMessage(mdMsg); }
/// <summary> /// Create a copy of <see cref="MarketDataMessage"/>. /// </summary> /// <returns>Copy.</returns> public override Message Clone() { var clone = new MarketDataMessage { Arg = Arg, DataType = DataType, Error = Error, From = From, To = To, IsSubscribe = IsSubscribe, TransactionId = TransactionId, Count = Count, MaxDepth = MaxDepth, NewsId = NewsId, LocalTime = LocalTime, IsNotSupported = IsNotSupported }; CopyTo(clone); return clone; }
/// <summary> /// Call this method to request market depth for a specific contract. The market depth will be returned by the updateMktDepth() and updateMktDepthL2() methods. /// </summary> /// <param name="message">this structure contains a description of the contract for which market depth data is being requested.</param> private void SubscribeMarketDepth(MarketDataMessage message) { if (message == null) throw new ArgumentNullException("message"); //var security = SessionHolder.Securities[message.SecurityId]; ProcessRequest(RequestMessages.SubscribeMarketDepth, ServerVersions.V6, ServerVersions.V5, socket => socket .Send(message.TransactionId) .SendIf(ServerVersions.V68, s => socket.SendContractId(message.SecurityId)) .SendSecurity(message, false) .SendIf(ServerVersions.V68, s => socket.Send(message.Class)) .SendIf(ServerVersions.V19, s => socket.Send(message.MaxDepth ?? MarketDataMessage.DefaultMaxDepth)) .SendIf(ServerVersions.V70, s => { //StringBuilder realTimeBarsOptionsStr = new StringBuilder(); //int realTimeBarsOptionsCount = realTimeBarsOptions == null ? 0 : realTimeBarsOptions.size(); //if (realTimeBarsOptionsCount > 0) //{ // for (int i = 0; i < realTimeBarsOptionsCount; ++i) // { // TagValue tagValue = (TagValue)realTimeBarsOptions.get(i); // realTimeBarsOptionsStr.append(tagValue.m_tag); // realTimeBarsOptionsStr.append("="); // realTimeBarsOptionsStr.append(tagValue.m_value); // realTimeBarsOptionsStr.append(";"); // } //} //send(realTimeBarsOptionsStr.toString()); socket.Send(string.Empty); })); }
/// <summary> /// Подписаться на получение свечек реального времени. /// </summary> /// <param name="message"></param> /// <param name="field">Поля маркет-данных, на основе которых будут строяться свечи. Поддерживаются следующие значения: /// <list type="number"> /// <item> /// <description><see cref="CandleDataTypes.Trades"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.Bid"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.Ask"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.Midpoint"/>.</description> /// </item> /// </list> /// </param> /// <param name="useRth">Строить свечи только по торговому времени. По-умолчанию используется торговое время.</param> private void SubscribeRealTimeCandles(MarketDataMessage message, Level1Fields field = CandleDataTypes.Trades, bool useRth = true) { if (message == null) throw new ArgumentNullException("message"); //var security = SessionHolder.Securities[message.SecurityId]; ProcessRequest(RequestMessages.SubscribeRealTimeCandles, ServerVersions.V34, ServerVersions.V3, socket => socket .Send(message.TransactionId) .SendIf(ServerVersions.V68, s => socket.SendContractId(message.SecurityId)) .SendSecurity(message) .SendIf(ServerVersions.V68, s => socket.Send(message.Class)) .Send(5) // Поддерживается только 5 секундный тайм-фрейм. .SendLevel1Field(field) .Send(useRth) .SendIf(ServerVersions.V70, s => { //StringBuilder realTimeBarsOptionsStr = new StringBuilder(); //int realTimeBarsOptionsCount = realTimeBarsOptions == null ? 0 : realTimeBarsOptions.size(); //if (realTimeBarsOptionsCount > 0) //{ // for (int i = 0; i < realTimeBarsOptionsCount; ++i) // { // TagValue tagValue = (TagValue)realTimeBarsOptions.get(i); // realTimeBarsOptionsStr.append(tagValue.m_tag); // realTimeBarsOptionsStr.append("="); // realTimeBarsOptionsStr.append(tagValue.m_value); // realTimeBarsOptionsStr.append(";"); // } //} //send(realTimeBarsOptionsStr.toString()); socket.Send(string.Empty); })); }
/// <summary> /// Call this method to request market data. The market data will be returned by the tickPrice, tickSize, tickOptionComputation(), tickGeneric(), tickString() and tickEFP() methods. /// </summary> /// <param name="message">this structure contains a description of the contract for which market data is being requested.</param> /// <param name="genericFields">comma delimited list of generic tick types. Tick types can be found here: (new Generic Tick Types page) </param> /// <param name="snapshot">Allows client to request snapshot market data.</param> /// <param name="marketDataOff">Market Data Off - used in conjunction with RTVolume Generic tick type causes only volume data to be sent.</param> private void SubscribeMarketData(MarketDataMessage message, IEnumerable<GenericFieldTypes> genericFields, bool snapshot, bool marketDataOff) { if (message == null) throw new ArgumentNullException("message"); //var security = SessionHolder.Securities[message.SecurityId]; ProcessRequest(RequestMessages.SubscribeMarketData, ServerVersions.V47, ServerVersions.V11, socket => { socket .Send(message.TransactionId) .SendContractId(message.SecurityId) .SendSecurity(message) .SendIf(ServerVersions.V68, s => socket.Send(message.Class)); if (socket.ServerVersion >= ServerVersions.V8 && message is WeightedIndexSecurity) { // TODO //socket.SendCombo((WeightedIndexSecurity)security); } if (socket.ServerVersion >= ServerVersions.V40) { //if (contract.UnderlyingComponent != null) //{ // UnderlyingComponent underComp = contract.UnderlyingComponent; // send(true); // send(underComp.ContractId); // send(underComp.Delta); // send(underComp.Price); //} //else //{ socket.Send(false); //} } if (socket.ServerVersion >= ServerVersions.V31) { /* * Even though SHORTABLE tick type supported only * starting server version 33 it would be relatively * expensive to expose this restriction here. * * Therefore we are relying on TWS doing validation. */ var genList = new StringBuilder(); genList.Append(genericFields.Select(t => ((int)t).To<string>()).Join(",")); if (marketDataOff) { if (genList.Length > 0) genList.Append(","); genList.Append("mdoff"); } socket.Send(genList.ToString()); } if (socket.ServerVersion >= ServerVersions.V35) { socket.Send(snapshot); } if (socket.ServerVersion >= ServerVersions.V70) { //StringBuilder mktDataOptionsStr = new StringBuilder(); //int mktDataOptionsCount = mktDataOptions == null ? 0 : mktDataOptions.size(); //if( mktDataOptionsCount > 0) { // for( int i = 0; i < mktDataOptionsCount; ++i) { // TagValue tagValue = (TagValue)mktDataOptions.get(i); // mktDataOptionsStr.append( tagValue.m_tag); // mktDataOptionsStr.append( "="); // mktDataOptionsStr.append( tagValue.m_value); // mktDataOptionsStr.append( ";"); // } //} //send( mktDataOptionsStr.toString()); socket.Send(string.Empty); } }); }
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 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 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 SubscribeCandles(CandleSeries series, DateTimeOffset from, DateTimeOffset to, long transactionId) { var mdMsg = new MarketDataMessage { //SecurityId = GetSecurityId(series.Security), DataType = GetCandleType(series.CandleType), TransactionId = transactionId, From = from, To = to, Arg = series.Arg, IsSubscribe = true, }.FillSecurityInfo(this, series.Security); //var timeFrame = (TimeSpan)series.Arg; //if (timeFrame == TimeSpan.FromDays(7)) // mdMsg.Count = (to - from).TotalWeeks().To<int>(); //else if (timeFrame.Ticks == TimeHelper.TicksPerMonth) // mdMsg.Count = (to - from).TotalMonths().To<int>(); _candleSeries.Add(transactionId, series); SendInMessage(mdMsg); }
private void RaiseMarketDataMessage(MarketDataMessage message, Exception error) { var reply = (MarketDataMessage)message.Clone(); reply.OriginalTransactionId = message.TransactionId; reply.Error = error; SendOutMessage(reply); }
private void ProcessMarketDataMessage(MarketDataMessage message) { var securityId = message.SecurityId; var security = SecurityProvider.LookupById(securityId.ToStringId()); if (security == null) { RaiseMarketDataMessage(message, new InvalidOperationException(LocalizedStrings.Str704Params.Put(securityId))); return; } if (StorageRegistry == null) { RaiseMarketDataMessage(message, new InvalidOperationException(LocalizedStrings.Str1117Params.Put(message.DataType, securityId))); return; } var history = message as HistorySourceMessage; Exception error = null; switch (message.DataType) { case MarketDataTypes.Level1: { if (message.IsSubscribe) { if (history == null) { BasketStorage.AddStorage(StorageRegistry.GetLevel1MessageStorage(security, Drive, StorageFormat)); BasketStorage.AddStorage(new InMemoryMarketDataStorage<ClearingMessage>(security, null, date => new[] { new ClearingMessage { LocalTime = date.Date + security.Board.ExpiryTime, SecurityId = securityId, ClearMarketDepth = true } })); } else { BasketStorage.AddStorage(new InMemoryMarketDataStorage<Level1ChangeMessage>(security, null, history.GetMessages)); } } else { BasketStorage.RemoveStorage<IMarketDataStorage<Level1ChangeMessage>>(security, MessageTypes.Level1Change, null); BasketStorage.RemoveStorage<InMemoryMarketDataStorage<ClearingMessage>>(security, ExtendedMessageTypes.Clearing, null); } break; } case MarketDataTypes.MarketDepth: { if (message.IsSubscribe) { if (history == null) BasketStorage.AddStorage((IMarketDataStorage<QuoteChangeMessage>)StorageRegistry.GetMarketDepthStorage(security, Drive, StorageFormat)); else BasketStorage.AddStorage(new InMemoryMarketDataStorage<QuoteChangeMessage>(security, null, history.GetMessages)); } else BasketStorage.RemoveStorage<IMarketDataStorage<QuoteChangeMessage>>(security, MessageTypes.QuoteChange, null); break; } case MarketDataTypes.Trades: { if (message.IsSubscribe) { if (history == null) BasketStorage.AddStorage((IMarketDataStorage<ExecutionMessage>)StorageRegistry.GetTradeStorage(security, Drive, StorageFormat)); else BasketStorage.AddStorage(new InMemoryMarketDataStorage<ExecutionMessage>(security, null, history.GetMessages)); } else BasketStorage.RemoveStorage<IMarketDataStorage<ExecutionMessage>>(security, MessageTypes.Execution, ExecutionTypes.Tick); break; } case MarketDataTypes.OrderLog: { if (message.IsSubscribe) { if (history == null) BasketStorage.AddStorage((IMarketDataStorage<ExecutionMessage>)StorageRegistry.GetOrderLogStorage(security, Drive, StorageFormat)); else BasketStorage.AddStorage(new InMemoryMarketDataStorage<ExecutionMessage>(security, null, history.GetMessages)); } else BasketStorage.RemoveStorage<IMarketDataStorage<ExecutionMessage>>(security, MessageTypes.Execution, ExecutionTypes.OrderLog); break; } case MarketDataTypes.CandleTimeFrame: case MarketDataTypes.CandleTick: case MarketDataTypes.CandleVolume: case MarketDataTypes.CandleRange: case MarketDataTypes.CandlePnF: case MarketDataTypes.CandleRenko: { var msgType = message.DataType.ToCandleMessageType(); if (message.IsSubscribe) { var candleType = message.DataType.ToCandleMessage(); if (history == null) BasketStorage.AddStorage(StorageRegistry.GetCandleMessageStorage(candleType, security, message.Arg, Drive, StorageFormat)); else BasketStorage.AddStorage(new InMemoryMarketDataStorage<CandleMessage>(security, message.Arg, history.GetMessages, candleType)); } else BasketStorage.RemoveStorage<IMarketDataStorage<CandleMessage>>(security, msgType, message.Arg); break; } default: error = new InvalidOperationException(LocalizedStrings.Str1118Params.Put(message.DataType)); break; } RaiseMarketDataMessage(message, error); }
public void LookupCandles(MarketDataMessage message) { if (message.From == null || message.To == null) throw new ArgumentException("message"); var placeCode = _adapter.SecurityClassInfo.GetSecurityClass(message.SecurityType, message.SecurityId.BoardCode); _adapter.AddDebugLog("Candles SC={0} PC={1} TF={2} F={3} T={4}", message.SecurityId.SecurityCode, placeCode, message.Arg, message.From, message.To); if (placeCode == null) throw new InvalidOperationException(LocalizedStrings.Str2279); var timeFrame = (AlfaTimeFrames)(TimeSpan)message.Arg; //to = timeFrame.GetCandleBounds(series.Security).Min; var data = _ad.GetArchiveFinInfoFromDB(placeCode, message.SecurityId.SecurityCode, timeFrame.Interval, message.From.Value.ToLocalTime(TimeHelper.Moscow), message.To.Value.ToLocalTime(TimeHelper.Moscow)); if (_ad.LastResult != StateCodes.stcSuccess) ThrowInError((tagStateCodes)_ad.LastResult); _adapter.AddDebugLog("Candles DT={0}", data); DoInSysCulture(() => ProcessCandles.SafeInvoke(message, data.ToRows())); }
/// <summary> /// Subscribe to receive new candles. /// </summary> /// <param name="series">Candles series.</param> /// <param name="from">The initial date from which you need to get data.</param> /// <param name="to">The final date by which you need to get data.</param> public void SubscribeCandles(CandleSeries series, DateTimeOffset from, DateTimeOffset to) { var transactionId = TransactionIdGenerator.GetNextId(); var mdMsg = new MarketDataMessage { //SecurityId = GetSecurityId(series.Security), DataType = MarketDataTypes.CandleTimeFrame, TransactionId = transactionId, From = from, To = to, Arg = series.Arg, IsSubscribe = true, }.FillSecurityInfo(this, series.Security); _candleSeries.Add(transactionId, series); SendInMessage(mdMsg); }
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 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 OnProcessCandles(MarketDataMessage mdMsg, string[] data) { var index = 0; foreach (var candle in data) { var details = candle.ToColumns(); var closeTime = details[0].To<DateTime>().ApplyTimeZone(TimeHelper.Moscow); SendOutMessage(new TimeFrameCandleMessage { SecurityId = mdMsg.SecurityId, OpenPrice = details[1].To<decimal>(), HighPrice = details[2].To<decimal>(), LowPrice = details[3].To<decimal>(), ClosePrice = details[4].To<decimal>(), TotalVolume = details[5].To<decimal>(), // из терминала приходит время закрытия свечи OpenTime = closeTime - mdMsg.Arg.To<TimeSpan>(), CloseTime = closeTime, OriginalTransactionId = mdMsg.TransactionId, State = CandleStates.Finished, IsFinished = ++index != data.Length }); } }
/// <summary> /// Подписаться на получение исторических значений инструмента с заданной периодичностью. /// </summary> /// <param name="message">Сообщение о подписке или отписки на маркет-данные.</param> /// <param name="field">Поле маркет-данных. Поддерживаются следующие значения: /// <list type="number"> /// <item> /// <description><see cref="CandleDataTypes.Trades"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.Bid"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.Ask"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.Midpoint"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.BidAsk"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.ImpliedVolatility"/>.</description> /// </item> /// <item> /// <description><see cref="CandleDataTypes.HistoricalVolatility"/>.</description> /// </item> /// </list></param> /// <param name="useRth">Получать данные только по торговому времени. По-умолчанию используется торговое время.</param> private void SubscribeHistoricalCandles(MarketDataMessage message, Level1Fields field, bool useRth = true) { if (message == null) throw new ArgumentNullException("message"); //if (message.CandleType != typeof(TimeFrameCandle)) // throw new ArgumentException("Interactive Brokers не поддерживает свечи типа {0}.".Put(series.CandleType), "series"); if (!(message.Arg is TimeSpan)) throw new ArgumentException(LocalizedStrings.WrongCandleArg.Put(message.Arg), "message"); var timeFrame = (TimeSpan)message.Arg; //var security = SessionHolder.Securities[message.SecurityId]; ProcessRequest(RequestMessages.SubscribeHistoricalData, ServerVersions.V16, ServerVersions.V6, socket => { socket .Send(message.TransactionId) .SendIf(ServerVersions.V68, s => socket.SendContractId(message.SecurityId)) .SendSecurity(message) .SendIf(ServerVersions.V68, s => socket.Send(message.Class)) .SendIncludeExpired(message.ExpiryDate) .SendEndDate(message.To ?? DateTimeOffset.MaxValue) .SendTimeFrame(timeFrame) .Send(ConvertPeriodtoIb(message.From ?? DateTimeOffset.MinValue, message.To ?? DateTimeOffset.MaxValue)) .Send(useRth) .SendLevel1Field(field); if (socket.ServerVersion > ServerVersions.V16) { //Send date times as seconds since 1970 socket.Send(2); } // TODO WeightedIndexSecurity indexSecurity = null;//security as WeightedIndexSecurity; if (indexSecurity != null) socket.SendCombo(indexSecurity); if (socket.ServerVersion >= ServerVersions.V70) { //StringBuilder chartOptionsStr = new StringBuilder(); //int chartOptionsCount = chartOptions == null ? 0 : chartOptions.size(); //if (chartOptionsCount > 0) //{ // for (int i = 0; i < chartOptionsCount; ++i) // { // TagValue tagValue = (TagValue)chartOptions.get(i); // chartOptionsStr.append(tagValue.m_tag); // chartOptionsStr.append("="); // chartOptionsStr.append(tagValue.m_value); // chartOptionsStr.append(";"); // } //} //send(chartOptionsStr.toString()); socket.Send(string.Empty); } }); }
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); }
/// <summary> /// Остановить подписку получения свечек, ранее созданную через <see cref="SubscribeRealTimeCandles"/>. /// </summary> /// <param name="message"></param> /// <param name="requestId"></param> private void UnSubscribeRealTimeCandles(MarketDataMessage message, long requestId) { if (message == null) throw new ArgumentNullException("message"); ProcessRequest(RequestMessages.UnSubscribeRealTimeCandles, ServerVersions.V34, ServerVersions.V1, socket => socket.Send(requestId)); }
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) { var key = Tuple.Create(message.SecurityId, message.DataType); switch (message.DataType) { case MarketDataTypes.Level1: { var contract = _client.Contracts[message.SecurityId.SecurityCode]; if (message.IsSubscribe) _client.Subscribe(contract); else _client.Unsubscribe(contract); break; } case MarketDataTypes.MarketDepth: { var contract = _client.Contracts[message.SecurityId.SecurityCode]; if (message.IsSubscribe) _client.SubscribeDOM(contract); else _client.UnsubscribeDOM(contract); break; } case MarketDataTypes.Trades: { var contract = _client.Contracts[message.SecurityId.SecurityCode]; if (message.IsSubscribe) { var subscription = _client.SubscribeTicks(contract, message.From.UtcDateTime); _subscriptions.Add(key, subscription); } else _client.CancelSubscription(_subscriptions[key]); break; } case MarketDataTypes.News: { break; } case MarketDataTypes.CandleTimeFrame: case MarketDataTypes.CandleTick: case MarketDataTypes.CandleVolume: case MarketDataTypes.CandleRange: { var contract = _client.Contracts[message.SecurityId.SecurityCode]; if (message.IsSubscribe) { SubscriptionType subscriptionType; int interval; switch (message.DataType) { case MarketDataTypes.CandleTimeFrame: { var tf = (TimeSpan)message.Arg; if (tf < TimeSpan.FromMinutes(1)) { subscriptionType = SubscriptionType.SecondBar; interval = (int)tf.TotalSeconds; } else if (tf < TimeSpan.FromHours(1)) { subscriptionType = SubscriptionType.Bar; interval = (int)tf.TotalMinutes; } else if (tf.Ticks < TimeHelper.TicksPerWeek) { subscriptionType = SubscriptionType.DayBar; interval = (int)tf.TotalDays; } else if (tf.Ticks < TimeHelper.TicksPerMonth) { subscriptionType = SubscriptionType.WeeklyBar; interval = (int)tf.TotalDays; } else { subscriptionType = SubscriptionType.MonthlyBar; interval = (int)(tf.Ticks / TimeHelper.TicksPerMonth); } break; } case MarketDataTypes.CandleTick: { subscriptionType = SubscriptionType.TickBar; interval = message.Arg.To<int>(); break; } case MarketDataTypes.CandleVolume: { subscriptionType = SubscriptionType.VolumeBar; interval = message.Arg.To<int>(); break; } case MarketDataTypes.CandleRange: { subscriptionType = SubscriptionType.RangeBar; interval = message.Arg.To<int>(); break; } default: throw new InvalidOperationException(); } var subscription = message.Count == 0 ? _client.SubscribeBars(contract, message.From.UtcDateTime, subscriptionType, interval) : _client.SubscribeBars(contract, (int)message.Count, subscriptionType, interval, false); _subscriptions.Add(key, subscription); } else _client.CancelSubscription(_subscriptions[key]); break; } default: throw new ArgumentOutOfRangeException(); } SendOutMessage(new MarketDataMessage { OriginalTransactionId = message.TransactionId }); }
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); }
/// <summary> /// To get historical candles. /// </summary> /// <param name="security">The instrument for which you need to get candles.</param> /// <param name="candleType">The candle type.</param> /// <param name="arg">The candle parameter (for example, time-frame).</param> /// <param name="count">Maximum ticks count.</param> /// <param name="isSuccess">Whether all data were obtained successfully or the download process has been interrupted.</param> /// <returns>Historical candles.</returns> public IEnumerable<CandleMessage> GetHistoricalCandles(Security security, Type candleType, object arg, long count, out bool isSuccess) { if (security == null) throw new ArgumentNullException(nameof(security)); //if (timeFrame <= TimeSpan.Zero) // throw new ArgumentException("Тайм-фрейм должен быть больше 0."); var transactionId = TransactionIdGenerator.GetNextId(); var series = new CandleSeries(candleType, security, arg); this.AddInfoLog(LocalizedStrings.Str2146Params, series, count); var info = RefTuple.Create(new List<CandleMessage>(), new SyncObject(), false, series, false); _candleInfo.Add(transactionId, info); var mdMsg = new MarketDataMessage { //SecurityId = GetSecurityId(series.Security), DataType = GetCandleType(series.CandleType), TransactionId = transactionId, Count = count, Arg = arg, IsSubscribe = true, }.FillSecurityInfo(this, series.Security); _candleSeries.Add(transactionId, series); SendInMessage(mdMsg); lock (info.Second) { if (!info.Third) info.Second.Wait(); } isSuccess = info.Fifth; return info.First; }
private void RaiseMarketDataSubscriptionSucceeded(Security security, MarketDataMessage message) { var msg = LocalizedStrings.Str690Params.Put(security.Id, message.DataType); if (message.From != null && message.To != null) msg += LocalizedStrings.Str691Params.Put(message.From.Value, message.To.Value); this.AddInfoLog(msg + "."); MarketDataSubscriptionSucceeded.SafeInvoke(security, message.DataType); }
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 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); }