Example #1
0
        /// <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));
        }
Example #2
0
        /// <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);
            }
        }
Example #3
0
        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."));
        }
Example #4
0
        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();
                    }
                }
            }
        }
Example #5
0
        /// <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;
            }
        }