internal IEnumerable <HistoryDataPoint> PrepareDataPoints(uint contractId, TimeBarReport report)
        {
            if (report.time_bar == null)
            {
                yield break;
            }

            foreach (var bar in report.time_bar)
            {
                var dataPoint = new HistoryDataPoint(
                    adapter.ResolveDateTime(bar.bar_utc_time),
                    instrumentResolver.ConvertPriceBack(contractId, bar.high_price),
                    instrumentResolver.ConvertPriceBack(contractId, bar.low_price),
                    instrumentResolver.ConvertPriceBack(contractId, bar.open_price),
                    instrumentResolver.ConvertPriceBack(contractId, bar.close_price),
                    (int)bar.volume,
                    (int)bar.open_interest);
                yield return(dataPoint);
            }
        }
Ejemplo n.º 2
0
        public void Process(TimeBarReport report, out bool shouldRemoveHandler)
        {
            shouldRemoveHandler = true;

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

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

            case TimeBarReport.StatusCode.DISCONNECTED:
                TrySetCanceled();
                return;

            case TimeBarReport.StatusCode.OUTSIDE_ALLOWED_RANGE:
                // Мы зашли слишком глубоко в прошлое
                CQGCAdapter.Log.Debug().Print(
                    "Historical data depth limit has been reached",
                    LogFields.Instrument(data.Instrument),
                    LogFields.Span(data.Span));
                TrySetException(new NoHistoryDataException(nameof(TimeBarReport.StatusCode.OUTSIDE_ALLOWED_RANGE)));
                return;

            default:
                TrySetException(new Exception($"Request ended with {status:G} status code. {report.text_message}"));
                return;
            }

            // Складываем точки данных в пакет
            var dataPoints = provider.PrepareDataPoints(message.time_bar_parameters.contract_id, 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);
                    continue;
                }

                if (p != point)
                {
                    points[point.Point] = point;
                }
            }

            // Если отчет не полон, то ожидаем прихода следующей пачки данных
            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));
                shouldRemoveHandler = false;
                consumer.Warning("This operation might take some time...");
                return;
            }

            // Если все данные пришли, то собираем ответ и выставляем его потребителю
            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;

            TrySetResult(data);
        }
Ejemplo n.º 3
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;
            }
        }