/// <summary> /// Подписаться на инструмент. /// </summary> /// <param name="instrument"> /// Инструмент для подписки. /// </param> public async Task <SubscriptionResult> Subscribe(Instrument instrument) { var symbol = await adapter.ResolveSymbolAsync(instrument); if (symbol == null) { return(SubscriptionResult.Error(instrument, "Unable to resolve symbol")); } adapter.SendMessage(new QLInstrumentParamsSubscriptionRequest(symbol)); return(SubscriptionResult.OK(instrument)); }
/// <summary> /// Подписаться на инструмент. /// </summary> /// <param name="instrument"> /// Инструмент для подписки. /// </param> public async Task <SubscriptionResult> Subscribe(Instrument instrument) { using (LogManager.Scope()) { var data = await instrumentConverter.ResolveInstrumentAsync(this, instrument); if (data == null) { return(SubscriptionResult.Error(instrument, $"Unable to resolve symbol for {instrument}")); } // Забираем подписку из коллекции или создаем новую InstrumentSubscription subscription; bool isNewSubscription; using (instrumentSubscriptionsLock.Lock()) { if (instrumentSubscriptionsByInstrument.TryGetValue(instrument, out subscription)) { isNewSubscription = false; } else { subscription = new InstrumentSubscription(instrument, data, OnInstrumentSubscriptionTimedOut); instrumentSubscriptionsByInstrument.Add(instrument, subscription); instrumentSubscriptionsByCode[subscription.Code] = subscription; isNewSubscription = true; } } if (isNewSubscription) { // Если подписка уже существовала, то ничего не делаем // В противном случае требуется подписаться // Подписываемся socketL1.Subscribe(subscription.Code); subscription.BeginTimeout(); } return(await subscription.Task); } }
public async Task <SubscriptionResult> Subscribe(Instrument instrument) { var code = await connector.ResolveInstrumentAsync(instrument); if (code == null) { return(SubscriptionResult.Error(instrument, "Unable to resolve instrument symbol")); } using (allInstrumentLock.WriteLock()) { if (allInstruments.Contains(code)) { if (!subscribedInstruments.Contains(code)) { subscribedInstruments.Add(code); InstrumentParams ip; if (instrumentsParams.TryGetValue(code, out ip)) { OnMessageReceived(ip); } else { ip = new InstrumentParams { Instrument = instrument }; instrumentsParams[code] = ip; } return(SubscriptionResult.OK(instrument)); } return(SubscriptionResult.Error(instrument, "Already subscribed.")); } } return(SubscriptionResult.Error(instrument, "Instrument doesn't exist.")); }
private async Task <SubscriptionResult> SubscribeAsync(Instrument instrument, SubscriptionFlags flags) { using (LogManager.Scope()) { InstrumentSubscription subscription = null; ContractMetadata metadata = null; var hasSubscriptionLock = false; try { // Получаем параметры подписки на инструмент using (subscriptionsLock.Lock()) { subscriptionsByInstrument.TryGetValue(instrument, out subscription); } if (subscription == null) { // Получаем ID инструмента var contractId = await instrumentResolver.GetContractIdAsync(instrument); if (contractId == uint.MaxValue) { return(SubscriptionResult.Error(instrument, "Symbol is not resolved in tree node for CQG")); } using (subscriptionsLock.Lock()) { if (!subscriptionsByInstrument.TryGetValue(instrument, out subscription)) { if (!subscriptionsByContractId.TryGetValue(contractId, out subscription)) { subscription = new InstrumentSubscription(instrumentResolver, instrument, contractId); // Сразу захватываем блокировку subscription.AcquireFlagsLock(); hasSubscriptionLock = true; subscriptionsByContractId.Add(contractId, subscription); contractMetadatas.TryGetValue(contractId, out metadata); } subscriptionsByInstrument.Add(instrument, subscription); } } } else { // Захватываем блокировку subscription.AcquireFlagsLock(); hasSubscriptionLock = true; } // Подписываемся на инструмент с учетом флагов подписки if ((subscription.Flags & flags) != flags) { // Нужные флаги подписки не проставлены, требуется доподписаться MarketDataSubscription.Level?level = null; switch (subscription.Flags | flags) { case SubscriptionFlags.InstrumentParams: level = MarketDataSubscription.Level.TRADES_BBA_VOLUMES; break; case SubscriptionFlags.OrderBook: level = MarketDataSubscription.Level.TRADES_BBA_DOM; break; case SubscriptionFlags.InstrumentParams | SubscriptionFlags.OrderBook: level = MarketDataSubscription.Level.TRADES_BBA_DOM; break; } if (level != null) { subscription.Flags |= flags; RequestMarketDataSubscription(subscription, level.Value); } } // При необходимости обрабатываем метаданные и выбрасываем события if (metadata != null) { Process(subscription, metadata, (s, data) => s.Handle(data)); } // Готово var result = SubscriptionResult.OK(instrument); return(result); } catch (OperationCanceledException) { _Log.Warn().Print($"Unable to subscribe to {instrument} (operation has been cancelled)"); return(SubscriptionResult.Error(instrument, "Operation has been cancelled")); } catch (Exception e) { _Log.Error().Print(e, $"Unable to subscribe to {instrument}"); return(SubscriptionResult.Error(instrument, e.Message)); } finally { if (subscription != null && hasSubscriptionLock) { subscription.ReleaseFlagsLock(); } } } }
/// <summary> /// Обработка входящего сообщения /// </summary> private void Connection_MessageReceived(object sender, StompMessageReceivedEventArgs e) { TaskCompletionSource <SubscriptionResult> tcs; Instrument instrument; switch (e.Message.Command) { case StompCommands.CONNECTED: ChangeConnectionStatus(ConnectionStatus.Connected); //var request = new Request( // destination: "SEARCH.ticker", // id: Guid.NewGuid().ToString(), // selector: "pattern=\"*BR*\"" // //selector: "pattern=\"\"" // ); //connection.Send(request); break; case StompCommands.ERROR: var error = new Error(e.Message); var sub = error.ReceiptId ?? e.Message.GetHeader("subscription"); if (ipSubscriptionResults.TryGetValue(sub, out tcs) && ipIdToInstrument.TryGetValue(sub, out instrument)) { ipSubscriptionResults.Remove(sub); tcs.SetResult(SubscriptionResult.Error(instrument, error.Message)); } break; case StompCommands.RECEIPT: var reci = new Receipt(e.Message); if (ipSubscriptionResults.TryGetValue(reci.ReceiptId, out tcs) && ipIdToInstrument.TryGetValue(reci.ReceiptId, out instrument)) { ipSubscriptionResults.Remove(reci.ReceiptId); tcs.SetResult(SubscriptionResult.OK(instrument)); } break; case StompCommands.MESSAGE: var subscription = e.Message.GetHeader("subscription", isRequired: false); var destination = e.Message.GetHeader("destination", isRequired: false); if (destination == Securities) { if (subscription != null && ipSubscriptionResults.TryGetValue(subscription, out tcs) && ipIdToInstrument.TryGetValue(subscription, out instrument)) { ipSubscriptionResults.Remove(subscription); tcs.SetResult(SubscriptionResult.OK(instrument)); } try { ParseParams(e.Message, subscription); } catch { } } else if (destination == Orderbooks) { try { ParseBook(e.Message, subscription); } catch { } } break; case "REPLY": break; default: return; } }