/// <summary> /// Processes incoming historical data requests. /// </summary> private void AcceptHistoricalDataRequest(string requesterIdentity) { lock (_socketLock) { if (_socket != null) { // Third: a serialized HistoricalDataRequest object which contains the details of the request bool hasMore; var buffer = _socket.ReceiveFrameBytes(out hasMore); using (var ms = new MemoryStream()) { ms.Write(buffer, 0, buffer.Length); ms.Position = 0; var request = Serializer.Deserialize <HistoricalDataRequest>(ms); _logger.Info( "Historical Data Request from client {0}: {7} {1} @ {2} from {3} to {4} Location: {5} {6:;;SaveToLocal}", requesterIdentity, request.Instrument.Symbol, Enum.GetName(typeof(BarSize), request.Frequency), request.StartingDate, request.EndingDate, request.DataLocation, request.SaveDataToStorage ? 0 : 1, request.Instrument.Datasource.Name); request.RequesterIdentity = requesterIdentity; try { _broker.RequestHistoricalData(request); } catch (Exception ex) { // There's some sort of problem with fulfilling the request. Inform the client. SendErrorReply(requesterIdentity, request.RequestID, ex.Message); } } } } }
/// <summary> /// Processes incoming historical data requests. /// </summary> private void AcceptHistoricalDataRequest(string requesterIdentity, NetMQSocket socket) { //third: a serialized HistoricalDataRequest object which contains the details of the request bool hasMore; byte[] buffer = socket.Receive(out hasMore); var ms = new MemoryStream(); ms.Write(buffer, 0, buffer.Length); ms.Position = 0; HistoricalDataRequest request = Serializer.Deserialize <HistoricalDataRequest>(ms); //log the request Log(LogLevel.Info, string.Format("Historical Data Request from client {0}: {7} {1} @ {2} from {3} to {4} Location: {5} {6:;;SaveToLocal}", requesterIdentity, request.Instrument.Symbol, Enum.GetName(typeof(BarSize), request.Frequency), request.StartingDate, request.EndingDate, request.DataLocation, request.SaveDataToStorage ? 0 : 1, request.Instrument.Datasource.Name)); request.RequesterIdentity = requesterIdentity; try { _broker.RequestHistoricalData(request); } catch (Exception ex) //there's some sort of problem with fulfilling the request. Inform the client. { SendErrorReply(requesterIdentity, request.RequestID, ex.Message); } }
/// <summary> /// Called by the <see cref="T:Quartz.IScheduler"/> when a <see cref="T:Quartz.ITrigger"/> /// fires that is associated with the <see cref="T:Quartz.IJob"/>. /// </summary> /// <remarks> /// The implementation may wish to set a result object on the /// JobExecutionContext before this method exits. The result itself /// is meaningless to Quartz, but may be informative to /// <see cref="T:Quartz.IJobListener"/>s or /// <see cref="T:Quartz.ITriggerListener"/>s that are watching the job's /// execution. /// </remarks> /// <param name="context">The execution context.</param> public void Execute(IJobExecutionContext context) { _logger = LogManager.GetCurrentClassLogger(); if (_broker == null) { Log(LogLevel.Error, "Data Update Job failed: broker not set."); return; } JobDataMap dataMap = context.JobDetail.JobDataMap; DataUpdateJobSettings settings; try { settings = JsonConvert.DeserializeObject <DataUpdateJobSettings>((string)dataMap["settings"]); } catch (Exception e) { _logger.Error(e, "Failed to deserialize data update job settings"); return; } Log(LogLevel.Info, string.Format("Data Update job {0} triggered.", settings.Name)); //Multiple jobs may be called simultaneously, so what we do is seed the Random based on the job name byte[] bytes = new byte[settings.Name.Length * sizeof(char)]; Buffer.BlockCopy(settings.Name.ToCharArray(), 0, bytes, 0, bytes.Length); Random r = new Random((int)DateTime.Now.TimeOfDay.TotalSeconds ^ BitConverter.ToInt32(bytes, 0)); _requesterID = "DataUpdateJob" + r.Next(); //we use this ID to identify this particular data update job List <Instrument> instruments = settings.UseTag ? _instrumentManager.FindInstruments(x => x.Tags.Any(y => y.ID == settings.TagID)).Result : _instrumentManager.FindInstruments(x => x.ID == settings.InstrumentID).Result; if (instruments.Count == 0) { Log(LogLevel.Error, string.Format("Aborting data update job {0}: no instruments found.", settings.Name)); return; } _broker.HistoricalDataArrived += _broker_HistoricalDataArrived; _broker.Error += _broker_Error; int counter = 1; //What we do here: we check what we have available locally.. //If there is something, we send a query to grab data between the last stored time and "now" //Otherwise we send a query to grab everything since 1900 foreach (Instrument i in instruments) { if (!i.ID.HasValue) { continue; } //don't request data on expired securities unless the expiration was recent if (i.Expiration.HasValue && (DateTime.Now - i.Expiration.Value).TotalDays > 15) { Log(LogLevel.Trace, string.Format("Data update job {0}: ignored instrument w/ ID {1} due to expiration date.", settings.Name, i.ID)); continue; } DateTime startingDT = new DateTime(1900, 1, 1); var storageInfo = _localStorage.GetStorageInfo(i.ID.Value); if (storageInfo.Any(x => x.Frequency == settings.Frequency)) { var relevantStorageInfo = storageInfo.First(x => x.Frequency == settings.Frequency); startingDT = relevantStorageInfo.LatestDate; } DateTime endDt = DateTime.Now; //try to get the current time in the instrument's exchange timezone string timeZone = i?.Exchange?.Timezone; if (!string.IsNullOrEmpty(timeZone)) { try { var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZone); endDt = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz); } catch (Exception e) { _logger.Error(e, "Could not find timezone " + timeZone); } } var req = new HistoricalDataRequest( i, settings.Frequency, startingDT, endDt, dataLocation: DataLocation.ExternalOnly, saveToLocalStorage: true, rthOnly: true, requestID: counter) { RequesterIdentity = _requesterID }; try { _broker.RequestHistoricalData(req); lock (_reqIDLock) { _pendingRequests.Add(req); } } catch (Exception ex) { _errors.Add(ex.Message); } counter++; } Stopwatch sw = new Stopwatch(); sw.Start(); //loop until time runs out or all requests are completed while (_pendingRequests.Count > 0 && sw.ElapsedMilliseconds < _settings.Timeout * 1000) { Thread.Sleep(100); } JobComplete(); Log(LogLevel.Info, string.Format("Data Update job {0} completed.", settings.Name)); }