I wrote a .Net C# wrapper to request and return historical time series data via Eikon .Net API. I can connect to Reuters servers, and can request 2, sometimes 3 time series but then the application hangs indefinitely (the problem 100% does not originate from the request content itself as I only request each time 1 day worth of 1 minute compressed fx data).
One complication is that I must access the Reuters API from within a console app thread and hence had to run a separate message pump. Please see below code :
Helper Methods:
private void PushDispatcherFrame(Action action) { _dispatcher.Invoke(() => { //execute action action(); //push frame _frame = new DispatcherFrame(); Dispatcher.PushFrame(_frame); }); } private void ReleaseFrame(bool isContinue) { _dispatcher.Invoke(() => { _frame.Continue = isContinue; }); }
Connection code:
PushDispatcherFrame(() => { _dataServices = DataServices.Instance; _dataServices.StateChanged += DataServicesOnStateChanged; _dataServices.Initialize("ReutersMarketDataPlugin"); }); //wait until service state changes (with timeout) var startDt = DateTime.UtcNow; var timeoutDt = startDt + TimeSpan.FromSeconds(40); while (DateTime.UtcNow < timeoutDt && _serviceState != DataServicesState.Up) { Task.Delay(200).Wait(); } if (_serviceState == DataServicesState.Up) return true; else return false; } private void DataServicesOnStateChanged(object sender, DataServicesStateChangedEventArgs args) { _serviceState = args.State; ReleaseFrame(false); }
Here is the data request (and after 2-3 successful requests the app hangs after executing "request.CreateAndSend();"
//structure request PushDispatcherFrame(() => { var subscription = new TaggableTimeseriesSubscription(dto, OnSubscriptionDataReceived, OnSubscriptionDataUpdated); _historicalSubscriptions.Add(subscription.SubscriptionId, subscription); ITimeSeriesDataRequestSetup request = _dataServices.TimeSeries.SetupDataRequest(); request.WithRic(GetRic(dto.SymbolId)); request.From(dto.DateTimeFrom); request.To(dto.DateTimeTo); request.WithFields(GetHistoricalDataRequestFields(dto.QuoteType)); request.WithTimeZone(TimezoneType.GMT); request.WithInterval(GetTimeSeriesInterval(dto.Compression)); request.OnDataReceived(subscription.RegisterDataReceivedCallback); request.OnStatusUpdated(status => { //error captured SendSystemMessage(new SystemMessage(SystemMessageType.Info, _properties.PluginName, dto.SubscriberId, "Status: " + status.State + " - Message: " + status.Error)); //return request _historicalDataCallback(subscription.HistoricalRequest); }); //create and send subscription.ReutersHistoricalTimeSeriesRequest = request.CreateAndSend(); });
And here the callback:
private void OnSubscriptionDataReceived(string subscriptionId, DataChunk chunk) { // chunk.Records provides access to a dictionary of field -> value, so that // developpers can access values from field names and cast them in the proper type like in: // double open = (double) chunk.Records.First()["OPEN"]; // In addition, for convenience Time Series API exposes shortcuts that allow developers // to code against strongly typed accessors. This is done through conversion methods // such as ToBarRecords(), ToQuoteRecords(), ToTickRecords(), ToTradeRecords() and ToTradeAndQuoteRecords(). // The full dictionary is still exposed in the resulting strongly-typed classes. // In this sample we know that records are typical "bar" records (open, close, high, low, volume) // because we ask for a daily interval. So we can use ToBarRecords() helper method: if (_historicalSubscriptions.ContainsKey(subscriptionId)) { //add quotes to request var request = _historicalSubscriptions[subscriptionId].HistoricalRequest; var quotes = RecordsToQuotes(request, chunk.Records); request.Quotes.AddRange(quotes); //return data if request is completed if (chunk.IsLast) { //filter and sort quotes and update request request.Quotes = request.Quotes.Where(x => x.TimeStamp >= request.DateTimeFrom && x.TimeStamp <= request.DateTimeTo).OrderBy(x => x.TimeStamp).Distinct().ToList(); //remove request _historicalSubscriptions.Remove(subscriptionId); //ReleaseFromMessagePump(); //return data if (_historicalDataCallback != null) { _historicalDataCallback(request); } ReleaseFrame(false); } else { ReleaseFrame(true); } } }