private void ProcessMissingDayFillForward(SubscriptionDataReader manager, int i, TimeSpan increment, DateTime dateToFill) { // we'll copy the current into the next day var subscription = Subscriptions[i]; if (!subscription.FillDataForward || manager.Current == null) { return; } var start = dateToFill.Date + manager.Exchange.MarketOpen; if (subscription.ExtendedMarketHours) { // we need to loop to find the extended market open start = dateToFill.Date; while (!manager.Exchange.DateTimeIsExtendedOpen(start)) { start += increment; } } var current = manager.Current; for (var date = start; date.Date == dateToFill.Date; date = date + increment) { if (manager.IsMarketOpen(date) || (subscription.ExtendedMarketHours && manager.IsExtendedMarketOpen(date))) { var cache = new List <BaseData>(1); var fillforward = current.Clone(true); fillforward.Time = date; FillForwardFrontiers[i] = date; cache.Add(fillforward); Bridge[i].Enqueue(cache); } else { // stop fill forwarding when we're no longer open break; } } }
/// <summary> /// If this is a fillforward subscription, look at the previous time, and current time, and add new /// objects to queue until current time to fill up the gaps. /// </summary> /// <param name="manager">Subscription to process</param> /// <param name="i">Subscription position in the bridge ( which queue are we pushing data to )</param> /// <param name="increment">Timespan increment to jump the fillforward results</param> private void ProcessFillForward(SubscriptionDataReader manager, int i, TimeSpan increment) { // If previous == null cannot fill forward nothing there to move forward (e.g. cases where file not found on first file). if (!Subscriptions[i].FillDataForward || manager.Previous == null) { return; } //Last tradebar and the current one we're about to add to queue: var previous = manager.Previous; var current = manager.Current; //Initialize the frontier: if (FillForwardFrontiers[i].Ticks == 0) { FillForwardFrontiers[i] = previous.Time; } //Data ended before the market closed: premature ending flag - continue filling forward until market close. if (manager.EndOfStream && manager.IsMarketOpen(current.Time)) { //Make sure we only fill forward to end of *today* -- don't fill forward tomorrow just because its also open. var processingDate = FillForwardFrontiers[i].Date; //Premature end of stream: fill manually until market closed. for (var date = FillForwardFrontiers[i] + increment; (manager.IsMarketOpen(date) && date.Date == processingDate); date = date + increment) { var cache = new List <BaseData>(1); var fillforward = current.Clone(true); fillforward.Time = date; FillForwardFrontiers[i] = date; cache.Add(fillforward); Bridge[i].Enqueue(cache); } return; } //Once per increment, add a new cache to the Bridge: //If the current.Time is before market close, (e.g. suspended trading at 2pm) the date is always greater than currentTime and fillforward never runs. //In this circumstance we need to keep looping till market/extended hours close even if no data. for (var date = FillForwardFrontiers[i] + increment; (date < current.Time); date = date + increment) { //If we don't want aftermarket data, rewind it backwards until the market closes. if (!Subscriptions[i].ExtendedMarketHours) { if (!manager.IsMarketOpen(date)) { // Move fill forward so we don't waste time in this tight loop. //Question is where to shuffle the date? // --> If BEFORE market open, shuffle forward. // --> If AFTER market close, and current.Time after market close, quit loop. date = current.Time; do { date = date - increment; } while (manager.IsMarketOpen(date)); continue; } } else { //If we've asked for extended hours, and the security is no longer inside extended market hours, skip: if (!manager.IsExtendedMarketOpen(date)) { continue; } } var cache = new List <BaseData>(1); var fillforward = previous.Clone(true); fillforward.Time = date; FillForwardFrontiers[i] = date; cache.Add(fillforward); Bridge[i].Enqueue(cache); } }