Esempio n. 1
0
        /// <summary>
        ///     Получить исторические данные
        /// </summary>
        /// <param name="consumer">
        ///     Потребитель исторических данных
        /// </param>
        /// <param name="instrument">
        ///     Инструмент
        /// </param>
        /// <param name="begin">
        ///     Начало диапазона
        /// </param>
        /// <param name="end">
        ///     Конец диапазона
        /// </param>
        /// <param name="span">
        ///     Интервал свечей для исторических данных
        /// </param>
        /// <param name="cancellationToken">
        ///     Токен отмены
        /// </param>
        /// <returns>
        ///     Исторические данные
        /// </returns>
        /// <remarks>
        ///     Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал,
        ///     если он не в состоянии предоставить запрошенные данные.
        /// </remarks>
        /// <exception cref="NoHistoryDataException">
        ///     Бросается, если исторические данные за указанный период недоступны
        /// </exception>
        public async Task GetHistoryDataAsync(
            IHistoryDataConsumer consumer,
            Instrument instrument,
            DateTime begin,
            DateTime end,
            HistoryProviderSpan span,
            CancellationToken cancellationToken = new CancellationToken())
        {
            var symbol = await adapter.ResolveSymbolAsync(instrument);

            if (symbol == null)
            {
                consumer.Error($"Unable to resolve symbol for {instrument}");
                return;
            }

            QLAdapter.Log.Debug().Print($"Candles request: {symbol}, span {span}, from {begin} to {end}");
            var dataRequestMessage = new QLHistoryDataRequest(symbol, span);
            var request            = new HistoryDataRequest(dataRequestMessage.id, instrument, begin, end, span);

            using (requestsLock.Lock())
            {
                requests[request.Id] = request;
            }

            // Поддержка отмены запроса
            cancellationToken.RegisterSafe(() => request.TrySetCanceled());

            adapter.SendMessage(dataRequestMessage);

            var data = await request.Task;

            QLAdapter.Log.Debug().Print("Push candles to consumer. ", LogFields.RequestId(request.Id));
            consumer.Update(data, HistoryDataUpdateType.Batch);
        }
Esempio n. 2
0
        /// <summary>
        ///     Получить исторические данные
        /// </summary>
        /// <param name="consumer">
        ///     Потребитель исторических данных
        /// </param>
        /// <param name="instrument">
        ///     Инструмент
        /// </param>
        /// <param name="begin">
        ///     Начало диапазона
        /// </param>
        /// <param name="end">
        ///     Конец диапазона
        /// </param>
        /// <param name="span">
        ///     Интервал свечей для исторических данных
        /// </param>
        /// <param name="cancellationToken">
        ///     Токен отмены
        /// </param>
        /// <returns>
        ///     Исторические данные
        /// </returns>
        /// <remarks>
        ///     Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал,
        ///     если он не в состоянии предоставить запрошенные данные.
        /// </remarks>
        /// <exception cref="NoHistoryDataException">
        ///     Бросается, если исторические данные за указанный период недоступны
        /// </exception>
        public async Task GetHistoryDataAsync(
            IHistoryDataConsumer consumer,
            Instrument instrument,
            DateTime begin,
            DateTime end,
            HistoryProviderSpan span,
            CancellationToken cancellationToken = new CancellationToken())
        {
            using (LogManager.Scope())
            {
                var instrumentData = await instrumentConverter.ResolveInstrumentAsync(this, instrument);

                if (instrumentData == null)
                {
                    consumer.Error($"Unable to resolve symbol for {instrument}");
                    return;
                }

                // Выгружаем список точек
                var points = await FetchHistoryDataAsync(instrumentData.Symbol, begin, end, span, cancellationToken);

                // Собираем результат
                var data = new HistoryData(instrument, begin, end, span);
                foreach (var p in points.OrderBy(_ => _.Point))
                {
                    data.Points.Add(p);
                }

                // Передаем результат потребителю
                consumer.Update(data, HistoryDataUpdateType.Batch);
            }
        }
        public void ProcessUpdate(QLHistoryDataUpdate update)
        {
            var hd = new HistoryData(Instrument, update.begin, update.end, Span);

            foreach (var candle in update.candles)
            {
                hd.Points.Add(new HistoryDataPoint(candle.Time, candle.h, candle.l, candle.o, candle.c, 0, 0));
            }

            consumer.Update(hd, update.update_type == "added" ? HistoryDataUpdateType.OnePointAdded : update.update_type == "updated" ? HistoryDataUpdateType.OnePointUpdated : HistoryDataUpdateType.Batch);
        }
Esempio n. 4
0
        /// <summary>
        ///     Получить исторические данные
        /// </summary>
        /// <param name="consumer">
        ///     Потребитель исторических данных
        /// </param>
        /// <param name="instrument">
        ///     Инструмент
        /// </param>
        /// <param name="begin">
        ///     Начало диапазона
        /// </param>
        /// <param name="end">
        ///     Конец диапазона
        /// </param>
        /// <param name="span">
        ///     Интервал свечей для исторических данных
        /// </param>
        /// <param name="cancellationToken">
        ///     Токен отмены
        /// </param>
        /// <returns>
        ///     Исторические данные
        /// </returns>
        /// <remarks>
        ///     Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал,
        ///     если он не в состоянии предоставить запрошенные данные.
        /// </remarks>
        /// <exception cref="NoHistoryDataException">
        ///     Бросается, если исторические данные за указанный период недоступны
        /// </exception>
        public async Task GetHistoryDataAsync(
            IHistoryDataConsumer consumer,
            Instrument instrument,
            DateTime begin,
            DateTime end,
            HistoryProviderSpan span,
            CancellationToken cancellationToken = new CancellationToken())
        {
            using (LogManager.Scope())
            {
                // Получаем контракт по инструменту
                var contract = await connector.ContractContainer.GetContractAsync(instrument, cancellationToken : cancellationToken);

                if (contract == null)
                {
                    throw new InvalidOperationException($"Can't find instrument \"{instrument}\"");
                }

                // Загружаем блок исторических данных
                var points = await FetchHistoryDataBlock(consumer, contract, begin, end, span, cancellationToken);

                // Собираем объект HistoryData
                var minDate = DateTime.MaxValue;
                var maxDate = DateTime.MinValue;
                var data    = new HistoryData(instrument, begin, end, span);
                foreach (var point in points.OrderBy(_ => _.Point))
                {
                    data.Points.Add(point);

                    if (minDate > point.Point)
                    {
                        minDate = point.Point;
                    }

                    if (maxDate < point.Point)
                    {
                        maxDate = point.Point;
                    }
                }

                data.Begin = minDate;
                data.End   = maxDate;

                consumer.Update(data, HistoryDataUpdateType.Batch);
            }
        }
        /// <summary>
        ///     Получить исторические данные
        /// </summary>
        /// <param name="consumer">
        ///     Потребитель исторических данных
        /// </param>
        /// <param name="instrument">
        ///     Инструмент
        /// </param>
        /// <param name="begin">
        ///     Начало диапазона
        /// </param>
        /// <param name="end">
        ///     Конец диапазона
        /// </param>
        /// <param name="span">
        ///     Интервал свечей для исторических данных
        /// </param>
        /// <param name="cancellationToken">
        ///     Токен отмены
        /// </param>
        /// <returns>
        ///     Исторические данные
        /// </returns>
        /// <remarks>
        ///     Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал,
        ///     если он не в состоянии предоставить запрошенные данные.
        /// </remarks>
        /// <exception cref="NoHistoryDataException">
        ///     Бросается, если исторические данные за указанный период недоступны
        /// </exception>
        public async Task GetHistoryDataAsync(
            IHistoryDataConsumer consumer,
            Instrument instrument,
            DateTime begin,
            DateTime end,
            HistoryProviderSpan span,
            CancellationToken cancellationToken = new CancellationToken())
        {
            var message =
                await PrepareTimeBarRequestAsync(instrument, begin, end, span, TimeBarRequest.RequestType.GET);

            if (message == null)
            {
                throw new ArgumentException($"Unable to resolve instrument {instrument}");
            }

            var request = new HistoryDataRequest(this, consumer, instrument, begin, end, span, message);

            using (requestsLock.Lock())
            {
                requests[message.request_id] = request;
            }

            CQGCAdapter.Log.Debug().Print(
                "Requesting history data block",
                LogFields.RequestId(message.request_id),
                LogFields.ContractId(message.time_bar_parameters.contract_id));
            adapter.SendMessage(message);

            // Поддержка отмены запроса
            cancellationToken.RegisterSafe(() => request.TrySetCanceled());

            var data = await request.Task;

            consumer.Update(data, HistoryDataUpdateType.Batch);
        }
Esempio n. 6
0
        private async Task UpdateLoopAsync(DateTime begin)
        {
            using (LogManager.Scope())
            {
                try
                {
                    while (true)
                    {
                        // Загружаем блок исторических данных
                        var end = DateTime.Now;
                        // TODO handle OperationCanceledException
                        var fetchedPoints = await gateway.FetchHistoryDataAsync(instrumentSymbol, begin, end, span, token);

                        // Обновляем точку старта на последнюю свечу, чтобы не грузить повторно
                        if (fetchedPoints.Any())
                        {
                            begin = fetchedPoints.Select(_ => _.Point).OrderByDescending(_ => _).First();
                        }

                        using (syncRoot.Lock())
                        {
                            // Объединяем с набором данных
                            int added, updated;
                            MergePoints(fetchedPoints, out added, out updated);

                            // Оповещаем потребителя
                            if (added > 0 || updated > 0)
                            {
                                begin = data.End;

                                if (added == 1 && updated == 0)
                                {
                                    consumer.Update(data, HistoryDataUpdateType.OnePointAdded);
                                }
                                else if (added == 0 && updated == 1)
                                {
                                    consumer.Update(data, HistoryDataUpdateType.OnePointUpdated);
                                }
                                else
                                {
                                    consumer.Update(data, HistoryDataUpdateType.Batch);
                                }
                            }
                            else
                            {
                                begin = end;
                            }
                        }

                        // Ждем до следущего обновления
                        await Task.Delay(FetchInterval, token);
                    }
                }
                catch (OperationCanceledException) { }
                catch (NoHistoryDataException)
                {
                    _Log.Debug().Print($"No more historical data is available", LogFields.Symbol(instrumentSymbol));
                }
                catch (Exception e)
                {
                    HandleException(e, e.Message);
                }
            }
        }
Esempio n. 7
0
        private async Task UpdateLoopAsync(DateTime begin)
        {
            using (LogManager.Scope())
            {
                try
                {
                    while (true)
                    {
                        // Ждем до следущего обновления
                        await Task.Delay(FetchInterval);

                        if (terminated.IsSet)
                        {
                            return;
                        }

                        // Загружаем блок исторических данных
                        var end = DateTime.Now;
                        // TODO handle OperationCanceledException
                        var fetchedPoints = await adapter.FetchHistoryDataBlock(consumer, contract, begin, end, span);

                        using (syncRoot.Lock())
                        {
                            // Объединяем с набором данных
                            int added, updated;
                            MergePoints(fetchedPoints, out added, out updated);

                            // Оповещаем потребителя
                            if (added > 0 || updated > 0)
                            {
                                begin = historyData.End;

                                if (added == 1 && updated == 0)
                                {
                                    consumer.Update(historyData, HistoryDataUpdateType.OnePointAdded);
                                }
                                else if (added == 0 && updated == 1)
                                {
                                    consumer.Update(historyData, HistoryDataUpdateType.OnePointUpdated);
                                }
                                else
                                {
                                    consumer.Update(historyData, HistoryDataUpdateType.Batch);
                                }
                            }
                            else
                            {
                                begin = end;
                            }
                        }
                    }
                }
                //catch (OperationCanceledException) { }
                catch (NoHistoryDataException)
                {
                    _Log.Debug().Print($"No more historical data is available", LogFields.Instrument(historyData.Instrument));
                }
                catch (Exception e)
                {
                    HandleException(e, e.Message);
                }
            }
        }
Esempio n. 8
0
        public void Process(TimeBarReport report, out bool shouldRemoveHandler)
        {
            shouldRemoveHandler = false;

            // Проверяем статус отчета
            var status = (TimeBarReport.StatusCode)report.status_code;

            switch (status)
            {
            case TimeBarReport.StatusCode.SUCCESS:
            case TimeBarReport.StatusCode.SUBSCRIBED:
            case TimeBarReport.StatusCode.UPDATE:
                break;

            case TimeBarReport.StatusCode.DISCONNECTED:
            case TimeBarReport.StatusCode.DROPPED:
                shouldRemoveHandler = true;
                return;

            default:
                shouldRemoveHandler = true;
                consumer.Error(report.text_message);
                return;
            }

            // Складываем точки в словарь
            var dataPoints = provider.PrepareDataPoints(contractId, report)
                             .Where(p => p.High != 0 && p.Low != 0 && p.Open != 0 && p.Close != 0); // иногда нули приходят

            foreach (var point in dataPoints)
            {
                HistoryDataPoint p;
                if (!points.TryGetValue(point.Point, out p))
                {
                    points.Add(point.Point, point);
                    newPoints++;
                    continue;
                }

                if (p != point)
                {
                    // TODO это неоптимально, в data.Points уже есть точка для этой даты, надо ее обновить
                    points[point.Point] = point;
                    updatedPoints++;
                }
            }

            // Если хотя бы одна точка изменилась - перестраиваем набор данных
            if (newPoints >= 0 || updatedPoints > 0)
            {
                var minDate = DateTime.MaxValue;
                var maxDate = DateTime.MinValue;

                data.Points.Clear();
                foreach (var p in points.OrderBy(_ => _.Key))
                {
                    data.Points.Add(p.Value);

                    if (p.Key > maxDate)
                    {
                        maxDate = p.Key;
                    }

                    if (p.Key < minDate)
                    {
                        minDate = p.Key;
                    }
                }

                data.Begin = minDate;
                data.End   = maxDate;
            }

            // Если еще не все данные пришли - выходим
            if (!report.is_report_complete)
            {
                CQGCAdapter.Log.Debug().Print(
                    $"Got a {nameof(TimeBarReport)} but it's incomplete",
                    LogFields.Instrument(data.Instrument),
                    LogFields.Span(data.Span));
                return;
            }

            if (newPoints > 0 || updatedPoints > 0)
            {
                if (newPoints == 1 && updatedPoints == 0)
                {
                    // Пришла одна новая свечка
                    consumer.Update(data, HistoryDataUpdateType.OnePointAdded);
                }
                else if (newPoints == 0 && updatedPoints == 1)
                {
                    // Одна свечка обновилась
                    consumer.Update(data, HistoryDataUpdateType.OnePointUpdated);
                }
                else
                {
                    // Свалилась пачка новых данных
                    consumer.Update(data, HistoryDataUpdateType.Batch);
                }

                newPoints     = 0;
                updatedPoints = 0;
            }
        }