internal async Task <IList <HistoryDataPoint> > FetchHistoryDataBlock( IHistoryDataConsumer consumer, Contract contract, DateTime begin, DateTime end, HistoryProviderSpan span, CancellationToken cancellationToken = new CancellationToken()) { // Формируем параметры запроса ApplyHistoryDataLimits(span, ref begin, ref end); // Ждем, чтобы не превысить лимиты по частоте запросов var request = new IBHistoricalDataRequest( this, consumer, contract: contract, begin: begin, end: end, span: span, whatToShow: "TRADES", useRth: 1, formatDate: 1 ); // Отправляем запрос var points = await request.ExecuteAsync(cancellationToken).ConfigureAwait(false); return(points); }
/// <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); } }
/// <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); }
/// <summary> /// Подписаться на исторические данные /// </summary> /// <param name="consumer"> /// Потребитель исторических данных /// </param> /// <param name="instrument"> /// Инструмент /// </param> /// <param name="begin"> /// Начало диапазона /// </param> /// <param name="span"> /// Интервал свечей для исторических данных /// </param> /// <returns> /// Подписка на исторические данные /// </returns> /// <remarks> /// Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал, /// если он не в состоянии предоставить запрошенные данные. /// </remarks> public async Task <IHistoryDataSubscription> SubscribeToHistoryDataAsync( IHistoryDataConsumer consumer, Instrument instrument, DateTime begin, HistoryProviderSpan span) { var symbol = await adapter.ResolveSymbolAsync(instrument); if (symbol == null) { consumer.Error($"Unable to resolve symbol for {instrument}"); return(new NullHistoryDataSubscription()); } QLAdapter.Log.Debug().Print($"Candles subscription: {symbol}, span {span}, from {begin}"); var subscriptionMessage = new QLHistoryDataSubscription(symbol, begin, span); var subscription = new HistoryDataSubscription(subscriptionMessage.id, instrument, begin, span, adapter, consumer); using (requestsLock.Lock()) { subscriptions[subscription.Id] = subscription; } adapter.SendMessage(subscriptionMessage); return(subscription); }
public IBHistoricalDataRequest( IBAdapter adapter, IHistoryDataConsumer consumer, Contract contract, DateTime begin, DateTime end, HistoryProviderSpan span, string whatToShow, int useRth, int formatDate) { this.adapter = adapter; Consumer = consumer; this.contract = contract; this.begin = begin; this.end = end; this.span = span; this.whatToShow = whatToShow; this.useRth = useRth; this.formatDate = formatDate; TimeSpan?minDuration, maxDuration; IBHistoryDataLimits.GetHistoryDataLimits(span, out minDuration, out maxDuration); var durationTimespan = end - begin; switch (span) { case HistoryProviderSpan.Minute: case HistoryProviderSpan.Minute5: case HistoryProviderSpan.Minute10: case HistoryProviderSpan.Minute15: case HistoryProviderSpan.Minute30: if (durationTimespan >= maxDuration || durationTimespan > IBHistoryDataLimits.MaxBarsPerRequest) { duration = (int)Math.Ceiling(durationTimespan.TotalDays); durationSuffix = " D"; } else { duration = (int)Math.Ceiling(durationTimespan.TotalSeconds); durationSuffix = " S"; } break; case HistoryProviderSpan.Hour: case HistoryProviderSpan.Hour4: case HistoryProviderSpan.Day: case HistoryProviderSpan.Week: case HistoryProviderSpan.Month: duration = (int)Math.Ceiling(durationTimespan.TotalDays); durationSuffix = " D"; break; default: throw new ArgumentOutOfRangeException(nameof(span), span, null); } }
/// <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 Task GetHistoryDataAsync( IHistoryDataConsumer consumer, Instrument instrument, DateTime begin, DateTime end, HistoryProviderSpan span, CancellationToken cancellationToken = new CancellationToken()) => connector.Adapter.GetHistoryDataAsync(consumer, instrument, begin, end, span, cancellationToken);
public HistoryDataSubscription(Guid id, Instrument instrument, DateTime since, HistoryProviderSpan span, QLAdapter adapter, IHistoryDataConsumer consumer) { this.Id = id; this.Instrument = instrument; this.Span = span; this.Since = since; this.adapter = adapter; this.consumer = consumer; }
public HistoryDataSubscription( CQGCInstrumentHistoryProvider provider, HistoryData data, IHistoryDataConsumer consumer, uint contractId, uint requestId) { this.provider = provider; this.data = data; this.consumer = consumer; this.contractId = contractId; this.requestId = requestId; }
public HistoryDataRequest( CQGCInstrumentHistoryProvider provider, IHistoryDataConsumer consumer, Instrument instrument, DateTime begin, DateTime end, HistoryProviderSpan span, TimeBarRequest message) { this.provider = provider; this.consumer = consumer; data = new HistoryData(instrument, begin, end, span); this.message = message; }
public IBHistoryDataSubscription( IBAdapter adapter, IHistoryDataConsumer consumer, Instrument instrument, Contract contract, HistoryProviderSpan span ) { this.adapter = adapter; this.consumer = consumer; this.contract = contract; this.span = span; historyData = new HistoryData(instrument, DateTime.Today, DateTime.Today, span); }
public HistorySubscription( IQFeedGateway gateway, IHistoryDataConsumer consumer, Instrument instrument, string instrumentSymbol, HistoryProviderSpan span) { this.gateway = gateway; this.consumer = consumer; this.instrumentSymbol = instrumentSymbol; this.span = span; data = new HistoryData(instrument, DateTime.Today, DateTime.Today, span); cts = new CancellationTokenSource(); token = cts.Token; }
/// <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="span"> /// Интервал свечей для исторических данных /// </param> /// <returns> /// Подписка на исторические данные /// </returns> /// <remarks> /// Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал, /// если он не в состоянии предоставить запрошенные данные. /// </remarks> public async Task <IHistoryDataSubscription> SubscribeToHistoryDataAsync( IHistoryDataConsumer consumer, Instrument instrument, DateTime begin, HistoryProviderSpan span) { // Получаем контракт по инструменту var contract = await connector.ContractContainer.GetContractAsync(instrument); if (contract == null) { throw new InvalidOperationException($"Can't find instrument \"{instrument}\""); } // Создаем подписку var subscription = new IBHistoryDataSubscription(this, consumer, instrument, contract, span); subscription.StartFetch(begin); return(subscription); }
/// <summary> /// Подписаться на исторические данные /// </summary> /// <param name="consumer"> /// Потребитель исторических данных /// </param> /// <param name="instrument"> /// Инструмент /// </param> /// <param name="begin"> /// Начало диапазона /// </param> /// <param name="span"> /// Интервал свечей для исторических данных /// </param> /// <returns> /// Подписка на исторические данные /// </returns> /// <remarks> /// Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал, /// если он не в состоянии предоставить запрошенные данные. /// </remarks> public async Task <IHistoryDataSubscription> SubscribeToHistoryDataAsync( IHistoryDataConsumer consumer, Instrument instrument, DateTime begin, HistoryProviderSpan span) { var instrumentData = await instrumentConverter.ResolveInstrumentAsync(this, instrument); if (instrumentData == null) { consumer.Error($"Unable to resolve symbol for {instrument}"); return(new NullHistoryDataSubscription()); } // Создаем подписку var subscription = new HistorySubscription(this, consumer, instrument, instrumentData.Symbol, span); subscription.StartFetch(begin); return(subscription); }
/// <summary> /// Подписаться на исторические данные /// </summary> /// <param name="consumer"> /// Потребитель исторических данных /// </param> /// <param name="instrument"> /// Инструмент /// </param> /// <param name="begin"> /// Начало диапазона /// </param> /// <param name="span"> /// Интервал свечей для исторических данных /// </param> /// <returns> /// Подписка на исторические данные /// </returns> /// <remarks> /// Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал, /// если он не в состоянии предоставить запрошенные данные. /// </remarks> public async Task <IHistoryDataSubscription> SubscribeToHistoryDataAsync( IHistoryDataConsumer consumer, Instrument instrument, DateTime begin, HistoryProviderSpan span) { using (LogManager.Scope()) { var message = await PrepareTimeBarRequestAsync(instrument, begin, DateTime.Now, span, TimeBarRequest.RequestType.SUBSCRIBE); if (message == null) { throw new ArgumentException($"Unable to resolve instrument {instrument}"); } message.time_bar_parameters.to_utc_time = 0; var request = new HistoryDataSubscription( this, new HistoryData(instrument, begin, DateTime.Now, span), consumer, message.time_bar_parameters.contract_id, message.request_id); using (requestsLock.Lock()) { requests[message.request_id] = request; } CQGCAdapter.Log.Debug().Print( "Requesting history data stream", LogFields.RequestId(message.request_id), LogFields.ContractId(message.time_bar_parameters.contract_id)); adapter.SendMessage(message); return(request); } }
/// <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); }
/// <summary> /// Подписаться на исторические данные /// </summary> /// <param name="consumer"> /// Потребитель исторических данных /// </param> /// <param name="instrument"> /// Инструмент /// </param> /// <param name="begin"> /// Начало диапазона /// </param> /// <param name="span"> /// Интервал свечей для исторических данных /// </param> /// <returns> /// Подписка на исторические данные /// </returns> /// <remarks> /// Провайдер вправе переопределить параметры исторических графиков - диапазон, интервал, /// если он не в состоянии предоставить запрошенные данные. /// </remarks> public Task <IHistoryDataSubscription> SubscribeToHistoryDataAsync( IHistoryDataConsumer consumer, Instrument instrument, DateTime begin, HistoryProviderSpan span) => connector.Adapter.SubscribeToHistoryDataAsync(consumer, instrument, begin, span);