/******************************************************** * CLASS CONSTRUCTOR *********************************************************/ /// <summary> /// Live trading datafeed handler provides a base implementation of a live trading datafeed. Derived types /// need only implement the GetNextTicks() function to return unprocessed ticks from a data source. /// This creates a new data feed with a DataFeedEndpoint of LiveTrading. /// </summary> /// <param name="algorithm">Algorithm requesting data</param> protected LiveTradingDataFeed(IAlgorithm algorithm) { //Subscription Count: _subscriptions = algorithm.SubscriptionManager.Subscriptions; //Set Properties: _dataFeed = DataFeedEndpoint.LiveTrading; _isActive = true; _bridge = new ConcurrentQueue <List <BaseData> > [Subscriptions.Count]; _endOfBridge = new bool[Subscriptions.Count]; _subscriptionManagers = new SubscriptionDataReader[Subscriptions.Count]; _realtimePrices = new List <decimal>(); //Class Privates: _algorithm = algorithm; //Setup the arrays: for (var i = 0; i < Subscriptions.Count; i++) { _endOfBridge[i] = false; _bridge[i] = new ConcurrentQueue <List <BaseData> >(); //This is quantconnect data source, store here for speed/ease of access _isDynamicallyLoadedData.Add(algorithm.Securities[_subscriptions[i].Symbol].IsDynamicallyLoadedData); //Subscription managers for downloading user data: _subscriptionManagers[i] = new SubscriptionDataReader(_subscriptions[i], algorithm.Securities[_subscriptions[i].Symbol], DataFeedEndpoint.LiveTrading, DateTime.MinValue, DateTime.MaxValue); //Set up the source file for today: _subscriptionManagers[i].RefreshSource(DateTime.Now.Date); _realtimePrices.Add(0); } }
private Subscription CreateSubscription(Universe universe, IResultHandler resultHandler, Security security, DateTime startTimeUtc, DateTime endTimeUtc, IReadOnlyRef <TimeSpan> fillForwardResolution) { var config = security.SubscriptionDataConfig; var localStartTime = startTimeUtc.ConvertFromUtc(config.TimeZone); var localEndTime = endTimeUtc.ConvertFromUtc(config.TimeZone); var tradeableDates = Time.EachTradeableDay(security, localStartTime, localEndTime); // ReSharper disable once PossibleMultipleEnumeration if (!tradeableDates.Any()) { _algorithm.Error(string.Format("No data loaded for {0} because there were no tradeable dates for this security.", security.Symbol)); return(null); } // ReSharper disable once PossibleMultipleEnumeration IEnumerator <BaseData> enumerator = new SubscriptionDataReader(config, localStartTime, localEndTime, resultHandler, tradeableDates, false); // optionally apply fill forward logic, but never for tick data if (config.FillDataForward && config.Resolution != Resolution.Tick) { enumerator = new FillForwardEnumerator(enumerator, security.Exchange, fillForwardResolution, security.IsExtendedMarketHours, localEndTime, config.Resolution.ToTimeSpan()); } // finally apply exchange/user filters enumerator = SubscriptionFilterEnumerator.WrapForDataFeed(resultHandler, enumerator, security, localEndTime); var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.SubscriptionDataConfig.TimeZone, startTimeUtc, endTimeUtc); var subscription = new Subscription(universe, security, enumerator, timeZoneOffsetProvider, startTimeUtc, endTimeUtc, false); return(subscription); }
private static LiveSubscription CreateSubscription(IAlgorithm algorithm, IResultHandler resultHandler, Security security, DateTime periodStart, DateTime periodEnd) { IEnumerator <BaseData> enumerator = null; if (security.SubscriptionDataConfig.IsCustomData) { //Subscription managers for downloading user data: // TODO: Update this when warmup comes in, we back up so we can get data that should have emitted at midnight today var subscriptionDataReader = new SubscriptionDataReader( security.SubscriptionDataConfig, periodStart, Time.EndOfTime, resultHandler, Time.EachTradeableDay(algorithm.Securities.Values, periodStart, periodEnd), true ); // wrap the subscription data reader with a filter enumerator enumerator = SubscriptionFilterEnumerator.WrapForDataFeed(resultHandler, subscriptionDataReader, security, periodEnd); } return(new LiveSubscription(security, enumerator, periodStart, periodEnd, true, false)); }
/// <summary> /// Prepare and create the new MySQL Database connection datafeed. /// </summary> /// <param name="algorithm"></param> /// <param name="job"></param> /// <param name="resultHandler"></param> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler) { Bridge = new BlockingCollection <TimeSlice>(); //Save the data subscriptions Subscriptions = algorithm.SubscriptionManager.Subscriptions; _subscriptions = Subscriptions.Count; //Public Properties: IsActive = true; EndOfBridge = new bool[_subscriptions]; _subscriptionReaderManagers = new SubscriptionDataReader[_subscriptions]; RealtimePrices = new List <decimal>(_subscriptions); _mySQLBridgeTime = new DateTime[_subscriptions]; //Class Privates: _endTime = algorithm.EndDate; //Initialize arrays: for (var i = 0; i < _subscriptions; i++) { _mySQLBridgeTime[i] = algorithm.StartDate; EndOfBridge[i] = false; _subscriptionReaderManagers[i] = new SubscriptionDataReader( Subscriptions[i], algorithm.Securities[Subscriptions[i].Symbol], DataFeedEndpoint.Database, algorithm.StartDate, algorithm.EndDate, resultHandler, Time.EachTradeableDay(algorithm.Securities, algorithm.StartDate, algorithm.EndDate) ); } }
/******************************************************** * CLASS CONSTRUCTOR *********************************************************/ /// <summary> /// Create a new backtesting data feed. /// </summary> /// <param name="algorithm">Instance of the algorithm</param> /// <param name="job">Algorithm work task</param> public FileSystemDataFeed(IAlgorithm algorithm, BacktestNodePacket job) { Subscriptions = algorithm.SubscriptionManager.Subscriptions; _subscriptions = Subscriptions.Count; //Public Properties: DataFeed = DataFeedEndpoint.FileSystem; IsActive = true; Bridge = new ConcurrentQueue <List <BaseData> > [_subscriptions]; EndOfBridge = new bool[_subscriptions]; SubscriptionReaders = new SubscriptionDataReader[_subscriptions]; FillForwardFrontiers = new DateTime[_subscriptions]; RealtimePrices = new List <decimal>(_subscriptions); //Class Privates: _job = job; _algorithm = algorithm; _endOfStreams = false; _bridgeMax = _bridgeMax / _subscriptions; //Set the bridge maximum count: for (var i = 0; i < _subscriptions; i++) { //Create a new instance in the dictionary: Bridge[i] = new ConcurrentQueue <List <BaseData> >(); EndOfBridge[i] = false; SubscriptionReaders[i] = new SubscriptionDataReader(Subscriptions[i], _algorithm.Securities[Subscriptions[i].Symbol], DataFeed, _job.PeriodStart, _job.PeriodFinish); FillForwardFrontiers[i] = new DateTime(); } }
private Subscription CreateSubscription(IResultHandler resultHandler, Security security, DateTime start, DateTime end, Resolution fillForwardResolution, bool userDefined) { var config = security.SubscriptionDataConfig; var tradeableDates = Time.EachTradeableDay(security, start.Date, end.Date); // ReSharper disable once PossibleMultipleEnumeration if (!tradeableDates.Any()) { if (userDefined) { _algorithm.Error(string.Format("No data loaded for {0} because there were no tradeable dates for this security.", security.Symbol)); } return(null); } var symbolResolutionDate = userDefined ? (DateTime?)null : start; // ReSharper disable once PossibleMultipleEnumeration IEnumerator <BaseData> enumerator = new SubscriptionDataReader(config, security, start, end, resultHandler, tradeableDates, false, symbolResolutionDate); // optionally apply fill forward logic, but never for tick data if (config.FillDataForward && config.Resolution != Resolution.Tick) { enumerator = new FillForwardEnumerator(enumerator, security.Exchange, fillForwardResolution.ToTimeSpan(), security.IsExtendedMarketHours, end, config.Resolution.ToTimeSpan()); } // finally apply exchange/user filters enumerator = SubscriptionFilterEnumerator.WrapForDataFeed(resultHandler, enumerator, security, end); var subscription = new Subscription(security, enumerator, start, end, userDefined, false); return(subscription); }
/******************************************************** * CLASS CONSTRUCTOR *********************************************************/ /// <summary> /// Prepare and create the new MySQL Database connection datafeed. /// </summary> /// <param name="algorithm"></param> /// <param name="job"></param> public DatabaseDataFeed(IAlgorithm algorithm, BacktestNodePacket job) { //Save the data subscriptions Subscriptions = algorithm.SubscriptionManager.Subscriptions; _subscriptions = Subscriptions.Count; //Public Properties: IsActive = true; DataFeed = DataFeedEndpoint.FileSystem; Bridge = new ConcurrentQueue <List <BaseData> > [_subscriptions]; EndOfBridge = new bool[_subscriptions]; SubscriptionReaderManagers = new SubscriptionDataReader[_subscriptions]; RealtimePrices = new List <decimal>(_subscriptions); _mySQLBridgeTime = new DateTime[_subscriptions]; //Class Privates: _job = job; _algorithm = algorithm; _endOfStreams = false; _bridgeMax = _bridgeMax / _subscriptions; //Set the bridge maximum count: _endTime = job.PeriodFinish; //Initialize arrays: for (var i = 0; i < _subscriptions; i++) { _mySQLBridgeTime[i] = job.PeriodStart; EndOfBridge[i] = false; Bridge[i] = new ConcurrentQueue <List <BaseData> >(); SubscriptionReaderManagers[i] = new SubscriptionDataReader(Subscriptions[i], algorithm.Securities[Subscriptions[i].Symbol], DataFeedEndpoint.Database, job.PeriodStart, job.PeriodFinish); } }
/******************************************************** * CLASS METHODS *********************************************************/ /// <summary> /// Initialize activators to invoke types in the algorithm /// </summary> private void ResetActivators() { for (var i = 0; i < _subscriptions; i++) { //Create a new instance in the dictionary: Bridge[i] = new ConcurrentQueue <List <BaseData> >(); EndOfBridge[i] = false; SubscriptionReaderManagers[i] = new SubscriptionDataReader(Subscriptions[i], _algorithm.Securities[Subscriptions[i].Symbol], DataFeed, _job.PeriodStart, _job.PeriodFinish); FillForwardFrontiers[i] = new DateTime(); } }
/// <summary> /// Adds a new subscription for universe selection /// </summary> /// <param name="universe">The universe to add a subscription for</param> /// <param name="startTimeUtc">The start time of the subscription in utc</param> /// <param name="endTimeUtc">The end time of the subscription in utc</param> public void AddUniverseSubscription(Universe universe, DateTime startTimeUtc, DateTime endTimeUtc) { // TODO : Consider moving the creating of universe subscriptions to a separate, testable class // grab the relevant exchange hours var config = universe.Configuration; var exchangeHours = SecurityExchangeHoursProvider.FromDataFolder().GetExchangeHours(config); // create a canonical security object var security = new Security(exchangeHours, config, universe.SubscriptionSettings.Leverage); var localStartTime = startTimeUtc.ConvertFromUtc(config.TimeZone); var localEndTime = endTimeUtc.ConvertFromUtc(config.TimeZone); // define our data enumerator IEnumerator <BaseData> enumerator; var tradeableDates = Time.EachTradeableDay(security, localStartTime, localEndTime); var userDefined = universe as UserDefinedUniverse; if (userDefined != null) { // spoof a tick on the requested interval to trigger the universe selection function enumerator = LinqExtensions.Range(localStartTime, localEndTime, dt => dt + userDefined.Interval) .Where(dt => security.Exchange.IsOpenDuringBar(dt, dt + userDefined.Interval, config.ExtendedMarketHours)) .Select(dt => new Tick { Time = dt }).GetEnumerator(); } else { // normal reader for all others enumerator = new SubscriptionDataReader(config, localStartTime, localEndTime, _resultHandler, tradeableDates, false); } // create the subscription var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.SubscriptionDataConfig.TimeZone, startTimeUtc, endTimeUtc); var subscription = new Subscription(universe, security, enumerator, timeZoneOffsetProvider, startTimeUtc, endTimeUtc, true); // only message the user if it's one of their universe types var messageUser = subscription.Configuration.Type != typeof(CoarseFundamental); PrimeSubscriptionPump(subscription, messageUser); _subscriptions.AddOrUpdate(new SymbolSecurityType(subscription), subscription); }
/// <summary> /// Creates an enumerator for the specified security/configuration /// </summary> private IEnumerator <BaseData> CreateSubscriptionEnumerator(Security security, SubscriptionDataConfig config, DateTime localStartTime, DateTime localEndTime, MapFileResolver mapFileResolver, IEnumerable <DateTime> tradeableDates, bool useSubscriptionDataReader, bool aggregate) { IEnumerator <BaseData> enumerator; if (useSubscriptionDataReader) { enumerator = new SubscriptionDataReader(config, localStartTime, localEndTime, _resultHandler, mapFileResolver, _factorFileProvider, tradeableDates, false); } else { var sourceFactory = (BaseData)Activator.CreateInstance(config.Type); enumerator = (from date in tradeableDates let source = sourceFactory.GetSource(config, date, false) let factory = SubscriptionDataSourceReader.ForSource(source, config, date, false) let entriesForDate = factory.Read(source) from entry in entriesForDate select entry).GetEnumerator(); } if (aggregate) { enumerator = new BaseDataCollectionAggregatorEnumerator(enumerator, config.Symbol); } // optionally apply fill forward logic, but never for tick data if (config.FillDataForward && config.Resolution != Resolution.Tick) { enumerator = new FillForwardEnumerator(enumerator, security.Exchange, _fillForwardResolution, security.IsExtendedMarketHours, localEndTime, config.Resolution.ToTimeSpan()); } // optionally apply exchange/user filters if (config.IsFilteredSubscription) { enumerator = SubscriptionFilterEnumerator.WrapForDataFeed(_resultHandler, enumerator, security, localEndTime); } return(enumerator); }
/******************************************************** * CLASS CONSTRUCTOR *********************************************************/ /// <summary> /// Create a new backtesting data feed. /// </summary> /// <param name="algorithm">Instance of the algorithm</param> /// <param name="job">Algorithm work task</param> public FileSystemDataFeed(IAlgorithm algorithm, BacktestNodePacket job) { Subscriptions = algorithm.SubscriptionManager.Subscriptions; _subscriptions = Subscriptions.Count; //Public Properties: DataFeed = DataFeedEndpoint.FileSystem; IsActive = true; Bridge = new ConcurrentQueue <List <BaseData> > [_subscriptions]; EndOfBridge = new bool[_subscriptions]; SubscriptionReaderManagers = new SubscriptionDataReader[_subscriptions]; FillForwardFrontiers = new DateTime[_subscriptions]; //Class Privates: _job = job; _algorithm = algorithm; _endOfStreams = false; _bridgeMax = _bridgeMax / _subscriptions; //Set the bridge maximum count: }
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> /// Live trading datafeed handler provides a base implementation of a live trading datafeed. Derived types /// need only implement the GetNextTicks() function to return unprocessed ticks from a data source. /// This creates a new data feed with a DataFeedEndpoint of LiveTrading. /// </summary> public LiveTradingDataFeed(IAlgorithm algorithm, LiveNodePacket job, IDataQueueHandler dataSource) { //Subscription Count: _subscriptions = algorithm.SubscriptionManager.Subscriptions; //Set Properties: _isActive = true; _dataFeed = DataFeedEndpoint.LiveTrading; _bridge = new ConcurrentQueue <List <BaseData> > [Subscriptions.Count]; _endOfBridge = new bool[Subscriptions.Count]; _subscriptionManagers = new SubscriptionDataReader[Subscriptions.Count]; _realtimePrices = new List <decimal>(); //Set the source of the live data: _dataQueue = dataSource; //Class Privates: _algorithm = algorithm; _job = job; //Setup the arrays: for (var i = 0; i < Subscriptions.Count; i++) { _endOfBridge[i] = false; _bridge[i] = new ConcurrentQueue <List <BaseData> >(); //This is quantconnect data source, store here for speed/ease of access _isDynamicallyLoadedData.Add(algorithm.Securities[_subscriptions[i].Symbol].IsDynamicallyLoadedData); //Subscription managers for downloading user data: _subscriptionManagers[i] = new SubscriptionDataReader(_subscriptions[i], algorithm.Securities[_subscriptions[i].Symbol], DataFeedEndpoint.LiveTrading, DateTime.MinValue, DateTime.MaxValue); //Set up the source file for today: _subscriptionManagers[i].RefreshSource(DateTime.Now.Date); _realtimePrices.Add(0); } // request for data from these symbols _dataQueue.Subscribe(job, BuildTypeSymbolList(algorithm)); }
/******************************************************** * CLASS CONSTRUCTOR *********************************************************/ /// <summary> /// Tradier datafeed handler for getting free data from the tradier brokerage api. /// </summary> /// <param name="algorithm">Algorithm requesting data</param> /// <param name="job">Job packet requesting data</param> /// <param name="brokerage">Brokerage instance to avoid access token duplication.</param> public TradierDataFeed(IAlgorithm algorithm, IBrokerage brokerage, LiveNodePacket job) { //Subscription Count: _subscriptions = algorithm.SubscriptionManager.Subscriptions; _subscriptionCount = Subscriptions.Count; //Set Properties: _dataFeed = DataFeedEndpoint.Tradier; _isActive = true; _bridge = new ConcurrentQueue <List <BaseData> > [_subscriptionCount]; _endOfBridge = new bool[_subscriptionCount]; _subscriptionManagers = new SubscriptionDataReader[_subscriptionCount]; //Class Privates: _job = job; _algorithm = algorithm; //Setup the arrays: for (var i = 0; i < _subscriptionCount; i++) { _endOfBridge[i] = false; _bridge[i] = new ConcurrentQueue <List <BaseData> >(); //This is quantconnect data source, store here for speed/ease of access _isQuantConnectData.Add(algorithm.Securities[_subscriptions[i].Symbol].IsQuantConnectData); //Subscription managers for downloading user data: _subscriptionManagers[i] = new SubscriptionDataReader(_subscriptions[i], algorithm.Securities[_subscriptions[i].Symbol], DataFeedEndpoint.LiveTrading, new DateTime(), new DateTime(9999, 12, 12)); //Set up the source file for today: _subscriptionManagers[i].RefreshSource(DateTime.Now.Date); } //Setup Brokerage Access: _tradier = (TradierBrokerage)brokerage; }
/// <summary> /// Creates an enumerator for the specified security/configuration /// </summary> private IEnumerator <BaseData> CreateSubscriptionEnumerator(Security security, SubscriptionDataConfig config, DateTime localStartTime, DateTime localEndTime, MapFileResolver mapFileResolver, IEnumerable <DateTime> tradeableDates) { IEnumerator <BaseData> enumerator = new SubscriptionDataReader(config, localStartTime, localEndTime, _resultHandler, mapFileResolver, _factorFileProvider, tradeableDates, false); // optionally apply fill forward logic, but never for tick data if (config.FillDataForward && config.Resolution != Resolution.Tick) { enumerator = new FillForwardEnumerator(enumerator, security.Exchange, _fillForwardResolution, security.IsExtendedMarketHours, localEndTime, config.Resolution.ToTimeSpan()); } // optionally apply exchange/user filters if (config.IsFilteredSubscription) { enumerator = SubscriptionFilterEnumerator.WrapForDataFeed(_resultHandler, enumerator, security, localEndTime); } return(enumerator); }
/// <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> 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.MarketOpen(current.Time)) { //Premature end of stream: fill manually until market closed. for (var date = FillForwardFrontiers[i] + increment; manager.MarketOpen(date); 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.MarketOpen(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.MarketOpen(date)); continue; } } else { //If we've asked for extended hours, and the security is no longer inside extended market hours, skip: if (!manager.ExtendedMarketOpen(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); } }
/// <summary> /// Adds a new subscription for universe selection /// </summary> /// <param name="universe">The universe to add a subscription for</param> /// <param name="startTimeUtc">The start time of the subscription in utc</param> /// <param name="endTimeUtc">The end time of the subscription in utc</param> public void AddUniverseSubscription(Universe universe, DateTime startTimeUtc, DateTime endTimeUtc) { // TODO : Consider moving the creating of universe subscriptions to a separate, testable class // grab the relevant exchange hours var config = universe.Configuration; var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var exchangeHours = marketHoursDatabase.GetExchangeHours(config); // create a canonical security object var security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency)); var localStartTime = startTimeUtc.ConvertFromUtc(security.Exchange.TimeZone); var localEndTime = endTimeUtc.ConvertFromUtc(security.Exchange.TimeZone); // define our data enumerator IEnumerator <BaseData> enumerator; var tradeableDates = Time.EachTradeableDay(security, localStartTime, localEndTime); var userDefined = universe as UserDefinedUniverse; if (userDefined != null) { // spoof a tick on the requested interval to trigger the universe selection function enumerator = userDefined.GetTriggerTimes(startTimeUtc, endTimeUtc, marketHoursDatabase) .Select(x => new Tick { Time = x, Symbol = config.Symbol }).GetEnumerator(); // route these custom subscriptions through the exchange for buffering var enqueueable = new EnqueueableEnumerator <BaseData>(true); // add this enumerator to our exchange ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution)); enumerator = enqueueable; } else if (config.Type == typeof(CoarseFundamental)) { var cf = new CoarseFundamental(); var enqueueable = new EnqueueableEnumerator <BaseData>(true); // load coarse data day by day var coarse = from date in Time.EachTradeableDay(security, _algorithm.StartDate, _algorithm.EndDate) let dateInDataTimeZone = date.ConvertTo(config.ExchangeTimeZone, config.DataTimeZone).Date let source = cf.GetSource(config, dateInDataTimeZone, false) let factory = SubscriptionFactory.ForSource(source, config, dateInDataTimeZone, false) let coarseFundamentalForDate = factory.Read(source) select new BaseDataCollection(date, config.Symbol, coarseFundamentalForDate); ScheduleEnumerator(coarse.GetEnumerator(), enqueueable, 5, 100000, 2); enumerator = enqueueable; } else { // normal reader for all others enumerator = new SubscriptionDataReader(config, localStartTime, localEndTime, _resultHandler, MapFileResolver.Empty, _factorFileProvider, tradeableDates, false); // route these custom subscriptions through the exchange for buffering var enqueueable = new EnqueueableEnumerator <BaseData>(true); // add this enumerator to our exchange ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution)); enumerator = enqueueable; } // create the subscription var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, startTimeUtc, endTimeUtc); var subscription = new Subscription(universe, security, enumerator, timeZoneOffsetProvider, startTimeUtc, endTimeUtc, true); _subscriptions.AddOrUpdate(subscription.Security.Symbol, subscription); }
/// <summary> /// Live trading datafeed handler provides a base implementation of a live trading datafeed. Derived types /// need only implement the GetNextTicks() function to return unprocessed ticks from a data source. /// This creates a new data feed with a DataFeedEndpoint of LiveTrading. /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler) { //Subscription Count: _subscriptions = algorithm.SubscriptionManager.Subscriptions; Bridge = new BlockingCollection <TimeSlice>(); //Set Properties: _isActive = true; _endOfBridge = new bool[Subscriptions.Count]; _subscriptionManagers = new IEnumerator <BaseData> [Subscriptions.Count]; _realtimePrices = new List <decimal>(); //Set the source of the live data: _dataQueue = Composer.Instance.GetExportedValueByTypeName <IDataQueueHandler>(Configuration.Config.Get("data-queue-handler", "LiveDataQueue")); //Class Privates: _algorithm = algorithm; if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _job = (LiveNodePacket)job; //Setup the arrays: for (var i = 0; i < Subscriptions.Count; i++) { _endOfBridge[i] = false; //This is quantconnect data source, store here for speed/ease of access var security = algorithm.Securities[_subscriptions[i].Symbol]; _isDynamicallyLoadedData.Add(security.IsDynamicallyLoadedData); // only make readers for custom data, live data will come through data queue handler if (_isDynamicallyLoadedData[i]) { //Subscription managers for downloading user data: // TODO: Update this when warmup comes in, we back up so we can get data that should have emitted at midnight today var periodStart = DateTime.Today.AddDays(-7); var subscriptionDataReader = new SubscriptionDataReader( _subscriptions[i], security, DataFeedEndpoint.LiveTrading, periodStart, DateTime.MaxValue, resultHandler, Time.EachTradeableDay(algorithm.Securities, periodStart, DateTime.MaxValue) ); // wrap the subscription data reader with a filter enumerator _subscriptionManagers[i] = SubscriptionFilterEnumerator.WrapForDataFeed(resultHandler, subscriptionDataReader, security, DateTime.MaxValue); } _realtimePrices.Add(0); } // request for data from these symbols var symbols = BuildTypeSymbolList(algorithm); if (symbols.Any()) { // don't subscribe if there's nothing there, this allows custom data to // work without an IDataQueueHandler implementation by specifying LiveDataQueue // in the configuration, that implementation throws on every method, but we actually // don't need it if we're only doing custom data _dataQueue.Subscribe(_job, symbols); } }
public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler) { _cancellationTokenSource = new CancellationTokenSource(); Subscriptions = algorithm.SubscriptionManager.Subscriptions; _subscriptions = Subscriptions.Count; //Public Properties: IsActive = true; _endOfBridge = new bool[_subscriptions]; SubscriptionReaders = new IEnumerator <BaseData> [_subscriptions]; FillForwardFrontiers = new DateTime[_subscriptions]; RealtimePrices = new List <decimal>(_subscriptions); //Class Privates: _algorithm = algorithm; // find the minimum resolution, ignoring ticks var fillForwardResolution = Subscriptions .Where(x => x.Resolution != Resolution.Tick) .Select(x => x.Resolution.ToTimeSpan()) .DefaultIfEmpty(TimeSpan.FromSeconds(1)) .Min(); // figure out how many subscriptions are at the minimum resolution var subscriptionsAtMinimumResolution = (from sub in Subscriptions where sub.Resolution == Subscriptions.Min(x => x.Resolution) select sub).Count(); Bridge = new BlockingCollection <TimeSlice>(Math.Min(1000, 50000 / subscriptionsAtMinimumResolution)); for (var i = 0; i < _subscriptions; i++) { _endOfBridge[i] = false; var config = Subscriptions[i]; var start = algorithm.StartDate; var end = algorithm.EndDate; var security = _algorithm.Securities[Subscriptions[i].Symbol]; var tradeableDates = Time.EachTradeableDay(security, start.Date, end.Date); IEnumerator <BaseData> enumerator = new SubscriptionDataReader(config, security, DataFeedEndpoint.FileSystem, start, end, resultHandler, tradeableDates); // optionally apply fill forward logic, but never for tick data if (config.FillDataForward && config.Resolution != Resolution.Tick) { enumerator = new FillForwardEnumerator(enumerator, security.Exchange, fillForwardResolution, security.IsExtendedMarketHours, end, config.Resolution.ToTimeSpan()); } // finally apply exchange/user filters SubscriptionReaders[i] = SubscriptionFilterEnumerator.WrapForDataFeed(resultHandler, enumerator, security, end); FillForwardFrontiers[i] = new DateTime(); // prime the pump for iteration in Run _endOfBridge[i] = !SubscriptionReaders[i].MoveNext(); if (_endOfBridge[i]) { Log.Trace("FileSystemDataFeed.Run(): Failed to load subscription: " + Subscriptions[i].Symbol); } } }