/// <summary> /// Creates a new PaperTradingDataFeed for the algorithm/job /// </summary> /// <param name="algorithm">The algorithm to receive the data, used for a complete listing of active securities</param> /// <param name="dataSource">Queable Source of the data</param> /// <param name="job">The job being run</param> public PaperTradingDataFeed(IAlgorithm algorithm, IDataQueueHandler dataSource, LiveNodePacket job) : base(algorithm, dataSource) { _job = job; _queue = dataSource; // create a lookup keyed by SecurityType var symbols = new Dictionary <SecurityType, List <string> >(); // Only subscribe equities and forex symbols foreach (var security in algorithm.Securities.Values) { if (security.Type == SecurityType.Equity || security.Type == SecurityType.Forex) { if (!symbols.ContainsKey(security.Type)) { symbols.Add(security.Type, new List <string>()); } symbols[security.Type].Add(security.Symbol); } } // request for data from these symbols _queue.Subscribe(job, symbols); }
/// <summary> /// Creates a new instance /// </summary> public LiveDataBasedDelistingEventProvider(SubscriptionDataConfig dataConfig, IDataQueueHandler dataQueueHandler) { _dataConfig = new SubscriptionDataConfig(dataConfig, typeof(Delisting)); _dataQueueHandler = dataQueueHandler; _delistingEnumerator = dataQueueHandler.Subscribe(_dataConfig, (sender, args) => { if (_delistingEnumerator != null && _delistingEnumerator.MoveNext()) { var delisting = _delistingEnumerator.Current as Delisting; if (delisting != null) { // we set the delisting date! DelistingDate = new ReferenceWrapper <DateTime>(delisting.Time); } else { Log.Error($"LiveDataBasedDelistingEventProvider(): Current is null or not a {nameof(Delisting)} event: {_delistingEnumerator.Current?.GetType()}"); } } else { Log.Error("LiveDataBasedDelistingEventProvider(): new data available triggered with no data"); } }); }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } if (algorithm.SubscriptionManager.Subscriptions.Count == 0 && algorithm.Universes.IsNullOrEmpty()) { throw new Exception("No subscriptions registered and no universe defined."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket)job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange", GetNextTicksEnumerator()) { SleepInterval = 0 }; _subscriptions = new ConcurrentDictionary <SymbolSecurityType, Subscription>(); Bridge = new BusyBlockingCollection <TimeSlice>(); // run the exchanges _exchange.Start(); _customExchange.Start(); // this value will be modified via calls to AddSubscription/RemoveSubscription var ffres = Time.OneSecond; _fillForwardResolution = Ref.Create(() => ffres, v => ffres = v); ffres = ResolveFillForwardResolution(algorithm); // add subscriptions var start = _timeProvider.GetUtcNow(); foreach (var universe in _algorithm.Universes) { var subscription = CreateUniverseSubscription(universe, start, Time.EndOfTime); _subscriptions[new SymbolSecurityType(subscription)] = subscription; } }
private IEnumerator <BaseData> Subscribe(IDataQueueHandler dataQueueHandler, SubscriptionDataConfig dataConfig, EventHandler newDataAvailableHandler) { var enumerator = dataQueueHandler.Subscribe(dataConfig, newDataAvailableHandler); if (enumerator != null) { return(enumerator); } return(Enumerable.Empty <BaseData>().GetEnumerator()); }
private static IEnumerator <BaseData> GetNextTicksEnumerator(IDataQueueHandler dataQueueHandler) { while (true) { int ticks = 0; foreach (var data in dataQueueHandler.GetNextTicks()) { ticks++; yield return(data); } if (ticks == 0) { Thread.Sleep(1); } } }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, IDataProvider dataProvider, IDataFeedSubscriptionManager subscriptionManager, IDataFeedTimeProvider dataFeedTimeProvider, IDataChannelProvider dataChannelProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _job = (LiveNodePacket)job; _timeProvider = dataFeedTimeProvider.TimeProvider; _dataProvider = dataProvider; _mapFileProvider = mapFileProvider; _factorFileProvider = factorFileProvider; _channelProvider = dataChannelProvider; _frontierTimeProvider = dataFeedTimeProvider.FrontierTimeProvider; _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; _subscriptions = subscriptionManager.DataFeedSubscriptions; _dataQueueHandler = GetDataQueueHandler(); _dataQueueHandler?.SetJob(_job); // run the custom data exchange var manualEvent = new ManualResetEventSlim(false); Task.Factory.StartNew(() => { manualEvent.Set(); _customExchange.Start(_cancellationTokenSource.Token); }, TaskCreationOptions.LongRunning); manualEvent.Wait(); manualEvent.DisposeSafely(); IsActive = true; }
private void SetupImpl(IDataQueueHandler dataQueueHandler, Synchronizer synchronizer, IDataAggregator dataAggregator) { _dataFeed = new TestableLiveTradingDataFeed(dataQueueHandler ?? new FakeDataQueue(dataAggregator ?? new AggregationManager())); _algorithm = new AlgorithmStub(createDataManager: false); _synchronizer = synchronizer ?? new LiveSynchronizer(); var registeredTypesProvider = new RegisteredSecurityDataTypesProvider(); var securityService = new SecurityService(_algorithm.Portfolio.CashBook, MarketHoursDatabase.FromDataFolder(), SymbolPropertiesDatabase.FromDataFolder(), _algorithm, registeredTypesProvider, new SecurityCacheProvider(_algorithm.Portfolio)); var universeSelection = new UniverseSelection( _algorithm, securityService, new DataPermissionManager(), TestGlobals.DataProvider, Resolution.Second); _dataManager = new DataManager(_dataFeed, universeSelection, _algorithm, new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork), MarketHoursDatabase.FromDataFolder(), true, new RegisteredSecurityDataTypesProvider(), new DataPermissionManager()); _resultHandler = new TestResultHandler(); _synchronizer.Initialize(_algorithm, _dataManager); _dataFeed.Initialize(_algorithm, new LiveNodePacket(), _resultHandler, TestGlobals.MapFileProvider, TestGlobals.FactorFileProvider, TestGlobals.DataProvider, _dataManager, _synchronizer, new DataChannelProvider()); _algorithm.SubscriptionManager.SetDataManager(_dataManager); _algorithm.Securities.SetSecurityService(securityService); _algorithm.SetFinishedWarmingUp(); var backtestingTransactionHandler = new BacktestingTransactionHandler(); backtestingTransactionHandler.Initialize(_algorithm, new PaperBrokerage(_algorithm, new LiveNodePacket()), _resultHandler); _algorithm.Transactions.SetOrderProcessor(backtestingTransactionHandler); _algorithm.PostInitialize(); }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, IDataProvider dataProvider, IDataFeedSubscriptionManager subscriptionManager, IDataFeedTimeProvider dataFeedTimeProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket)job; _timeProvider = dataFeedTimeProvider.TimeProvider; _dataQueueHandler = GetDataQueueHandler(); _dataProvider = dataProvider; _channelProvider = GetDataChannelProvider(); _frontierTimeProvider = dataFeedTimeProvider.FrontierTimeProvider; _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange") { SleepInterval = 0 }; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = subscriptionManager.DataFeedSubscriptions; _universeSelection = subscriptionManager.UniverseSelection; // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); IsActive = true; }
/// <summary> /// Creates a new instance /// </summary> public LiveSubscriptionEnumerator(SubscriptionDataConfig dataConfig, IDataQueueHandler dataQueueHandler, EventHandler handler) { _requestedSymbol = dataConfig.Symbol; _underlyingEnumerator = dataQueueHandler.SubscribeWithMapping(dataConfig, handler, out _currentConfig); // for any mapping event we will re subscribe dataConfig.NewSymbol += (_, _) => { dataQueueHandler.Unsubscribe(_currentConfig); _previousEnumerator = _underlyingEnumerator; var oldSymbol = _currentConfig.Symbol; _underlyingEnumerator = dataQueueHandler.SubscribeWithMapping(dataConfig, handler, out _currentConfig); Log.Trace($"LiveSubscriptionEnumerator({_requestedSymbol}): " + $"resubscribing old: '{oldSymbol.Value}' new '{_currentConfig.Symbol.Value}'"); }; }
/// <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)); }
/// <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)); }
/// <summary> /// Creates a new instance /// </summary> public LiveSubscriptionEnumerator(SubscriptionDataConfig dataConfig, IDataQueueHandler dataQueueHandler, EventHandler handler) { _requestedSymbol = dataConfig.Symbol; // we adjust the requested config symbol before sending it to the data queue handler _currentConfig = new SubscriptionDataConfig(dataConfig, symbol: dataConfig.Symbol.GetLiveSubscriptionSymbol()); _underlyingEnumerator = Subscribe(dataQueueHandler, _currentConfig, handler); // for any mapping event we will re subscribe dataConfig.NewSymbol += (_, _) => { dataQueueHandler.Unsubscribe(_currentConfig); _previousEnumerator = _underlyingEnumerator; var oldSymbol = _currentConfig.Symbol; _currentConfig = new SubscriptionDataConfig(dataConfig, symbol: dataConfig.Symbol.GetLiveSubscriptionSymbol()); _underlyingEnumerator = Subscribe(dataQueueHandler, _currentConfig, handler); Log.Trace($"LiveSubscriptionEnumerator({_requestedSymbol}): " + $"resubscribing old: '{oldSymbol.Value}' new '{_currentConfig.Symbol.Value}'"); }; }
/// <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) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _job = (LiveNodePacket)job; _isActive = true; _algorithm = algorithm; _resultHandler = resultHandler; _cancellationTokenSource = new CancellationTokenSource(); _universeSelection = new UniverseSelection(this, algorithm, true); _dataQueue = Composer.Instance.GetExportedValueByTypeName <IDataQueueHandler>(Configuration.Config.Get("data-queue-handler", "LiveDataQueue")); Bridge = new BusyBlockingCollection <TimeSlice>(); _subscriptions = new ConcurrentDictionary <SymbolSecurityType, LiveSubscription>(); var periodStart = DateTime.UtcNow.ConvertFromUtc(algorithm.TimeZone).AddDays(-7); var periodEnd = Time.EndOfTime; foreach (var security in algorithm.Securities.Values) { var subscription = CreateSubscription(algorithm, resultHandler, security, periodStart, periodEnd); _subscriptions.AddOrUpdate(new SymbolSecurityType(subscription), subscription); } // request for data from these symbols var symbols = BuildTypeSymbolList(algorithm.Securities.Values); 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); } }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public override void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, IDataProvider dataProvider, IDataFeedSubscriptionManager subscriptionManager, IDataFeedTimeProvider dataFeedTimeProvider, IDataChannelProvider dataChannelProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _algorithm = algorithm; _job = (LiveNodePacket)job; _timeProvider = dataFeedTimeProvider.TimeProvider; _dataProvider = dataProvider; _mapFileProvider = mapFileProvider; _factorFileProvider = factorFileProvider; _channelProvider = dataChannelProvider; _frontierTimeProvider = dataFeedTimeProvider.FrontierTimeProvider; _customExchange = GetBaseDataExchange(); _subscriptions = subscriptionManager.DataFeedSubscriptions; _dataQueueHandler = GetDataQueueHandler(); _dataQueueHandler?.SetJob(_job); // run the custom data exchange _customExchange.Start(); IsActive = true; base.Initialize(algorithm, job, resultHandler, mapFileProvider, factorFileProvider, dataProvider, subscriptionManager, dataFeedTimeProvider, dataChannelProvider); }
public TestableLiveTradingDataFeed(IDataQueueHandler dataQueueHandler, ITimeProvider timeProvider = null) { _dataQueueHandler = dataQueueHandler; _timeProvider = timeProvider ?? new RealTimeProvider(); }
/// <summary> /// Helper method to create a new instance. /// Knows which security types should create one and determines the appropriate delisting event provider to use /// </summary> public static bool TryCreate(SubscriptionDataConfig dataConfig, ITimeProvider timeProvider, IDataQueueHandler dataQueueHandler, SecurityCache securityCache, IMapFileProvider mapFileProvider, IFactorFileProvider fileProvider, DateTime startTime, out IEnumerator <BaseData> enumerator) { enumerator = null; var securityType = dataConfig.SecurityType; if (securityType.IsOption() || securityType == SecurityType.Future || securityType == SecurityType.Equity) { var providers = new List <ITradableDateEventProvider> { securityType == SecurityType.Equity ? new LiveDataBasedDelistingEventProvider(dataConfig, dataQueueHandler) : new DelistingEventProvider() }; if (dataConfig.TickerShouldBeMapped()) { providers.Add(new LiveMappingEventProvider()); } enumerator = new LiveAuxiliaryDataEnumerator(dataConfig, fileProvider, mapFileProvider, providers.ToArray(), startTime, timeProvider, securityCache); } return(enumerator != null); }
/// <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); } }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket) job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") {SleepInterval = 10}; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange", GetNextTicksEnumerator()){SleepInterval = 0}; _subscriptions = new ConcurrentDictionary<SymbolSecurityType, Subscription>(); Bridge = new BusyBlockingCollection<TimeSlice>(); // run the exchanges _exchange.Start(); _customExchange.Start(); // find the minimum resolution, ignoring ticks _fillForwardResolution = algorithm.SubscriptionManager.Subscriptions .Where(x => x.Resolution != Resolution.Tick) .Select(x => x.Resolution) .Union(algorithm.Universes.Select(x => x.SubscriptionSettings.Resolution)) .DefaultIfEmpty(algorithm.UniverseSettings.Resolution) .Min(); // add user defined subscriptions var start = _timeProvider.GetUtcNow(); foreach (var kvp in _algorithm.Securities.OrderBy(x => x.Key.ToString())) { var security = kvp.Value; AddSubscription(security, start, Time.EndOfTime, true); } // add universe subscriptions foreach (var universe in _algorithm.Universes) { var subscription = CreateUniverseSubscription(universe, start, Time.EndOfTime); _subscriptions[new SymbolSecurityType(subscription)] = subscription; } }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, IDataProvider dataProvider, IDataFeedSubscriptionManager subscriptionManager) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket)job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _dataProvider = dataProvider; _dataCacheProvider = new SingleEntryDataCacheProvider(dataProvider); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange") { SleepInterval = 0 }; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = subscriptionManager.DataFeedSubscriptions; _bridge = new BusyBlockingCollection <TimeSlice>(); _universeSelection = subscriptionManager.UniverseSelection; // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); // wire ourselves up to receive notifications when universes are added/removed var start = _timeProvider.GetUtcNow(); algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType <Universe>()) { var config = universe.Configuration; var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var exchangeHours = marketHoursDatabase.GetExchangeHours(config); Security security; if (!_algorithm.Securities.TryGetValue(config.Symbol, out security)) { // create a canonical security object security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency)); } AddSubscription(new SubscriptionRequest(true, universe, security, config, start, Time.EndOfTime)); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType <Universe>()) { RemoveSubscription(universe.Configuration); } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
public TestableLiveTradingDataFeed(IDataQueueHandler dataQueueHandler = null) { DataQueueHandler = dataQueueHandler; }
/// <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) { _cancellationTokenSource = new CancellationTokenSource(); //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, periodStart, DateTime.MaxValue, resultHandler, Time.EachTradeableDay(algorithm.Securities, periodStart, DateTime.MaxValue), true, DateTime.Today ); // 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 TestableLiveTradingDataFeed(IDataQueueHandler dataQueueHandler = null, ITimeProvider timeProvider = null) { DataQueueHandler = dataQueueHandler; _timeProvider = timeProvider ?? new RealTimeProvider(); }
/// <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) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _job = (LiveNodePacket)job; _isActive = true; _algorithm = algorithm; _resultHandler = resultHandler; _cancellationTokenSource = new CancellationTokenSource(); _universeSelection = new UniverseSelection(this, algorithm, true); _dataQueue = Composer.Instance.GetExportedValueByTypeName<IDataQueueHandler>(Configuration.Config.Get("data-queue-handler", "LiveDataQueue")); Bridge = new BusyBlockingCollection<TimeSlice>(); _subscriptions = new ConcurrentDictionary<SymbolSecurityType, LiveSubscription>(); var periodStart = DateTime.UtcNow.ConvertFromUtc(algorithm.TimeZone).AddDays(-7); var periodEnd = Time.EndOfTime; foreach (var security in algorithm.Securities.Values) { var subscription = CreateSubscription(algorithm, resultHandler, security, periodStart, periodEnd); _subscriptions.AddOrUpdate(new SymbolSecurityType(subscription), subscription); } // request for data from these symbols var symbols = BuildTypeSymbolList(algorithm.Securities.Values); 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); } }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket)job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange") { SleepInterval = 0 }; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = new ConcurrentDictionary <Symbol, Subscription>(); _bridge = new BusyBlockingCollection <TimeSlice>(); _universeSelection = new UniverseSelection(this, algorithm, job.Controls); // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); // this value will be modified via calls to AddSubscription/RemoveSubscription var ffres = Time.OneSecond; _fillForwardResolution = Ref.Create(() => ffres, v => ffres = v); ffres = ResolveFillForwardResolution(algorithm); // wire ourselves up to receive notifications when universes are added/removed var start = _timeProvider.GetUtcNow(); algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType <Universe>()) { _subscriptions[universe.Configuration.Symbol] = CreateUniverseSubscription(universe, start, Time.EndOfTime); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType <Universe>()) { Subscription subscription; if (_subscriptions.TryGetValue(universe.Configuration.Symbol, out subscription)) { RemoveSubscription(subscription); } } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
private static IEnumerator<BaseData> GetNextTicksEnumerator(IDataQueueHandler dataQueueHandler) { while (true) { int ticks = 0; foreach (var data in dataQueueHandler.GetNextTicks()) { ticks++; yield return data; } if (ticks == 0) Thread.Sleep(1); } }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket)job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange") { SleepInterval = 0 }; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = new SubscriptionCollection(); _bridge = new BusyBlockingCollection <TimeSlice>(); _universeSelection = new UniverseSelection(this, algorithm, job.Controls); // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); // this value will be modified via calls to AddSubscription/RemoveSubscription var ffres = Time.OneMinute; _fillForwardResolution = Ref.Create(() => ffres, v => ffres = v); // wire ourselves up to receive notifications when universes are added/removed var start = _timeProvider.GetUtcNow(); algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType <Universe>()) { if (!_subscriptions.Contains(universe.Configuration)) { _subscriptions.TryAdd(CreateUniverseSubscription(universe, start, Time.EndOfTime)); } // Not sure if this is needed but left here because of this: // https://github.com/VigiothCapital.QuantTrader.commit/029d70bde6ca83a1eb0c667bb5cc4444bea05678 UpdateFillForwardResolution(); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType <Universe>()) { RemoveSubscription(universe.Configuration); } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } if (algorithm.SubscriptionManager.Subscriptions.Count == 0 && algorithm.Universes.IsNullOrEmpty()) { throw new Exception("No subscriptions registered and no universe defined."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket) job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") {SleepInterval = 10}; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange", GetNextTicksEnumerator()){SleepInterval = 0}; _subscriptions = new ConcurrentDictionary<Symbol, Subscription>(); Bridge = new BusyBlockingCollection<TimeSlice>(); // run the exchanges _exchange.Start(); _customExchange.Start(); // this value will be modified via calls to AddSubscription/RemoveSubscription var ffres = Time.OneSecond; _fillForwardResolution = Ref.Create(() => ffres, v => ffres = v); ffres = ResolveFillForwardResolution(algorithm); // add subscriptions var start = _timeProvider.GetUtcNow(); foreach (var universe in _algorithm.Universes) { var subscription = CreateUniverseSubscription(universe, start, Time.EndOfTime); _subscriptions[subscription.Security.Symbol] = subscription; } }
/// <summary> /// Helper method to create a new instance. /// Knows which security types should create one and determines the appropriate delisting event provider to use /// </summary> public static bool TryCreate(SubscriptionDataConfig dataConfig, ITimeProvider timeProvider, IDataQueueHandler dataQueueHandler, SecurityCache securityCache, IMapFileProvider mapFileProvider, out IEnumerator <BaseData> enumerator) { enumerator = null; var securityType = dataConfig.SecurityType; if (securityType == SecurityType.FutureOption || securityType == SecurityType.Future || securityType == SecurityType.Option || securityType == SecurityType.Equity) { var mapfile = mapFileProvider.Get(dataConfig.Symbol.ID.Market).ResolveMapFile(dataConfig.Symbol, dataConfig.Type); var delistingEventProvider = new DelistingEventProvider(); if (securityType == SecurityType.Equity) { delistingEventProvider = new LiveDataBasedDelistingEventProvider(dataConfig, dataQueueHandler); } enumerator = new LiveDelistingEventProviderEnumerator(timeProvider, dataConfig, securityCache, delistingEventProvider, mapfile); return(true); } return(false); }
/// <summary> /// Creates a new instance /// </summary> public LiveDataBasedDelistingEventProvider(SubscriptionDataConfig dataConfig, IDataQueueHandler dataQueueHandler) { _dataConfig = new SubscriptionDataConfig(dataConfig, typeof(Delisting)); _dataQueueHandler = dataQueueHandler; }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket) job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") {SleepInterval = 10}; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange"){SleepInterval = 0}; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = new SubscriptionCollection(); _bridge = new BusyBlockingCollection<TimeSlice>(); _universeSelection = new UniverseSelection(this, algorithm, job.Controls); // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); // this value will be modified via calls to AddSubscription/RemoveSubscription var ffres = Time.OneMinute; _fillForwardResolution = Ref.Create(() => ffres, v => ffres = v); // wire ourselves up to receive notifications when universes are added/removed var start = _timeProvider.GetUtcNow(); algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType<Universe>()) { var config = universe.Configuration; var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var exchangeHours = marketHoursDatabase.GetExchangeHours(config); Security security; if (!_algorithm.Securities.TryGetValue(config.Symbol, out security)) { // create a canonical security object security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency)); } AddSubscription(new SubscriptionRequest(true, universe, security, config, start, Time.EndOfTime)); // Not sure if this is needed but left here because of this: // https://github.com/QuantConnect/Lean/commit/029d70bde6ca83a1eb0c667bb5cc4444bea05678 UpdateFillForwardResolution(); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType<Universe>()) { RemoveSubscription(universe.Configuration); } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket) job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") {SleepInterval = 10}; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange"){SleepInterval = 0}; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = new ConcurrentDictionary<Symbol, List<Subscription>>(); _bridge = new BusyBlockingCollection<TimeSlice>(); _universeSelection = new UniverseSelection(this, algorithm, job.Controls); // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); // this value will be modified via calls to AddSubscription/RemoveSubscription var ffres = Time.OneMinute; _fillForwardResolution = Ref.Create(() => ffres, v => ffres = v); // wire ourselves up to receive notifications when universes are added/removed var start = _timeProvider.GetUtcNow(); algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType<Universe>()) { _subscriptions.Add(universe.Configuration.Symbol, CreateUniverseSubscription(universe, start, Time.EndOfTime)); UpdateFillForwardResolution(); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType<Universe>()) { RemoveSubscription(universe.Configuration.Symbol); } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, IDataFileProvider dataFileProvider) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket)job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _dataFileProvider = dataFileProvider; _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange") { SleepInterval = 0 }; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = new SubscriptionCollection(); _bridge = new BusyBlockingCollection <TimeSlice>(); _universeSelection = new UniverseSelection(this, algorithm, job.Controls); // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); // this value will be modified via calls to AddSubscription/RemoveSubscription var ffres = Time.OneMinute; _fillForwardResolution = Ref.Create(() => ffres, v => ffres = v); // wire ourselves up to receive notifications when universes are added/removed var start = _timeProvider.GetUtcNow(); algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType <Universe>()) { var config = universe.Configuration; var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var exchangeHours = marketHoursDatabase.GetExchangeHours(config); Security security; if (!_algorithm.Securities.TryGetValue(config.Symbol, out security)) { // create a canonical security object security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency)); } AddSubscription(new SubscriptionRequest(true, universe, security, config, start, Time.EndOfTime)); // Not sure if this is needed but left here because of this: // https://github.com/QuantConnect/Lean/commit/029d70bde6ca83a1eb0c667bb5cc4444bea05678 UpdateFillForwardResolution(); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType <Universe>()) { RemoveSubscription(universe.Configuration); } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
/// <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; //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 = 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; _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, resultHandler); //Set up the source file for today: _subscriptionManagers[i].RefreshSource(DateTime.Now.Date); _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); } }