private Subscription CreateSubscription(Resolution resolution, string symbol = "AAPL", bool isInternalFeed = false, SecurityType type = SecurityType.Equity, TickType tickType = TickType.Trade) { var start = DateTime.UtcNow; var end = start.AddSeconds(10); Security security; Symbol _symbol; if (type == SecurityType.Equity) { _symbol = new Symbol(SecurityIdentifier.GenerateEquity(DateTime.Now, symbol, Market.USA), symbol); security = new Equity( _symbol, SecurityExchangeHours.AlwaysOpen(DateTimeZone.Utc), new Cash("USD", 0, 1), SymbolProperties.GetDefault("USD"), ErrorCurrencyConverter.Instance ); } else if (type == SecurityType.Option) { _symbol = new Symbol(SecurityIdentifier.GenerateOption(DateTime.Now, SecurityIdentifier.GenerateEquity(DateTime.Now, symbol, Market.USA), Market.USA, 0.0m, OptionRight.Call, OptionStyle.American), symbol); security = new Option( _symbol, SecurityExchangeHours.AlwaysOpen(DateTimeZone.Utc), new Cash("USD", 0, 1), new OptionSymbolProperties(SymbolProperties.GetDefault("USD")), ErrorCurrencyConverter.Instance ); } else if (type == SecurityType.Future) { _symbol = new Symbol(SecurityIdentifier.GenerateFuture(DateTime.Now, symbol, Market.USA), symbol); security = new Future( _symbol, SecurityExchangeHours.AlwaysOpen(DateTimeZone.Utc), new Cash("USD", 0, 1), SymbolProperties.GetDefault("USD"), ErrorCurrencyConverter.Instance ); } else { throw new Exception("SecurityType not implemented"); } var config = new SubscriptionDataConfig(typeof(TradeBar), _symbol, resolution, DateTimeZone.Utc, DateTimeZone.Utc, true, false, isInternalFeed, false, tickType); var timeZoneOffsetProvider = new TimeZoneOffsetProvider(DateTimeZone.Utc, start, end); var enumerator = new EnqueueableEnumerator <BaseData>(); var subscriptionDataEnumerator = SubscriptionData.Enumerator(config, security, timeZoneOffsetProvider, enumerator); var subscriptionRequest = new SubscriptionRequest(false, null, security, config, start, end); return(new Subscription(subscriptionRequest, subscriptionDataEnumerator, timeZoneOffsetProvider)); }
/// <summary> /// Creates a subscription to process the history request /// </summary> private static Subscription CreateSubscription(HistoryRequest request, IEnumerable <BaseData> history) { // data reader expects these values in local times var start = request.StartTimeUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var end = request.EndTimeUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var config = new SubscriptionDataConfig(request.DataType, request.Symbol, request.Resolution, request.DataTimeZone, request.ExchangeHours.TimeZone, request.FillForwardResolution.HasValue, request.IncludeExtendedMarketHours, false, request.IsCustomData, request.TickType, true, request.DataNormalizationMode ); var security = new Security( request.ExchangeHours, config, new Cash(Currencies.NullCurrency, 0, 1m), SymbolProperties.GetDefault(Currencies.NullCurrency), ErrorCurrencyConverter.Instance ); var reader = history.GetEnumerator(); // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, security.IsExtendedMarketHours, end, config.Increment, config.DataTimeZone); } var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, start, end); var subscriptionDataEnumerator = SubscriptionData.Enumerator(config, security, timeZoneOffsetProvider, reader); var subscriptionRequest = new SubscriptionRequest(false, null, security, config, start, end); return(new Subscription(subscriptionRequest, subscriptionDataEnumerator, timeZoneOffsetProvider)); }
/// <summary> /// Creates a subscription to process the request /// </summary> private Subscription CreateSubscription(HistoryRequest request, DateTime start, DateTime end) { // data reader expects these values in local times start = start.ConvertFromUtc(request.ExchangeHours.TimeZone); end = end.ConvertFromUtc(request.ExchangeHours.TimeZone); var config = new SubscriptionDataConfig(request.DataType, request.Symbol, request.Resolution, request.DataTimeZone, request.ExchangeHours.TimeZone, request.FillForwardResolution.HasValue, request.IncludeExtendedMarketHours, false, request.IsCustomData, request.TickType, true, request.DataNormalizationMode ); var security = new Security( request.ExchangeHours, config, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency), ErrorCurrencyConverter.Instance ); var dataReader = new SubscriptionDataReader(config, start, end, config.SecurityType == SecurityType.Equity ? _mapFileProvider.Get(config.Market) : MapFileResolver.Empty, _factorFileProvider, Time.EachTradeableDay(request.ExchangeHours, start, end), false, _dataCacheProvider, false ); dataReader.InvalidConfigurationDetected += (sender, args) => { OnInvalidConfigurationDetected(new InvalidConfigurationDetectedEventArgs(args.Message)); }; dataReader.NumericalPrecisionLimited += (sender, args) => { OnNumericalPrecisionLimited(new NumericalPrecisionLimitedEventArgs(args.Message)); }; dataReader.DownloadFailed += (sender, args) => { OnDownloadFailed(new DownloadFailedEventArgs(args.Message, args.StackTrace)); }; dataReader.ReaderErrorDetected += (sender, args) => { OnReaderErrorDetected(new ReaderErrorDetectedEventArgs(args.Message, args.StackTrace)); }; dataReader.Initialize(); IEnumerator <BaseData> reader = dataReader; // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, security.IsExtendedMarketHours, end, config.Increment, config.DataTimeZone); } // since the SubscriptionDataReader performs an any overlap condition on the trade bar's entire // range (time->end time) we can end up passing the incorrect data (too far past, possibly future), // so to combat this we deliberately filter the results from the data reader to fix these cases // which only apply to non-tick data reader = new SubscriptionFilterEnumerator(reader, security, end); reader = new FilterEnumerator <BaseData>(reader, data => { // allow all ticks if (config.Resolution == Resolution.Tick) { return(true); } // filter out future data if (data.EndTime > end) { return(false); } // filter out data before the start return(data.EndTime > start); }); var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, start, end); var subscriptionDataEnumerator = SubscriptionData.Enumerator(config, security, timeZoneOffsetProvider, reader); var subscriptionRequest = new SubscriptionRequest(false, null, security, config, start, end); return(new Subscription(subscriptionRequest, subscriptionDataEnumerator, timeZoneOffsetProvider)); }
public void EnumerationWhileUpdatingDoesNotThrow() { var cts = new CancellationTokenSource(); var subscriptions = new SubscriptionCollection(); var start = DateTime.UtcNow; var end = start.AddSeconds(10); var config = new SubscriptionDataConfig(typeof(TradeBar), Symbols.SPY, Resolution.Minute, DateTimeZone.Utc, DateTimeZone.Utc, true, false, false); var security = new Equity(Symbols.SPY, SecurityExchangeHours.AlwaysOpen(DateTimeZone.Utc), new Cash("USD", 0, 1), SymbolProperties.GetDefault("USD")); var timeZoneOffsetProvider = new TimeZoneOffsetProvider(DateTimeZone.Utc, start, end); var enumerator = new EnqueueableEnumerator <BaseData>(); var subscriptionDataEnumerator = SubscriptionData.Enumerator(config, security, timeZoneOffsetProvider, enumerator); var subscription = new Subscription(null, security, config, subscriptionDataEnumerator, timeZoneOffsetProvider, start, end, false); var addTask = new TaskFactory().StartNew(() => { Console.WriteLine("Add task started"); while (DateTime.UtcNow < end) { if (!subscriptions.Contains(config)) { subscriptions.TryAdd(subscription); } Thread.Sleep(1); } Console.WriteLine("Add task ended"); }, cts.Token); var removeTask = new TaskFactory().StartNew(() => { Console.WriteLine("Remove task started"); while (DateTime.UtcNow < end) { Subscription removed; subscriptions.TryRemove(config, out removed); Thread.Sleep(1); } Console.WriteLine("Remove task ended"); }, cts.Token); var readTask = new TaskFactory().StartNew(() => { Console.WriteLine("Read task started"); while (DateTime.UtcNow < end) { foreach (var sub in subscriptions) { } Thread.Sleep(1); } Console.WriteLine("Read task ended"); }, cts.Token); Task.WaitAll(addTask, removeTask, readTask); }