public void SecurityManagerCanCreate_CustomSecurities_WithCorrectSubscriptions() { var equitySymbol = new Symbol(SecurityIdentifier.GenerateBase("BTC", Market.USA), "BTC"); var equityMarketHoursDbEntry = _marketHoursDatabase.SetEntryAlwaysOpen(Market.USA, "BTC", SecurityType.Base, TimeZones.NewYork); var equitySymbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(equitySymbol.ID.Market, equitySymbol, equitySymbol.ID.SecurityType, CashBook.AccountCurrency); var equity = SecurityManager.CreateSecurity(typeof(Bitcoin), _securityPortfolioManager, _subscriptionManager, equityMarketHoursDbEntry.ExchangeHours, equityMarketHoursDbEntry.DataTimeZone, equitySymbolProperties, _securityInitializer, equitySymbol, Resolution.Second, false, 1.0m, false, false, false, false); Assert.AreEqual(equity.Subscriptions.Count(), 1); Assert.AreEqual(equity.Subscriptions.First().Type, typeof(Bitcoin)); Assert.AreEqual(equity.Subscriptions.First().TickType, TickType.Trade); }
public void SecurityManagerCanCreate_Cfd_WithCorrectSubscriptions() { var symbol = Symbol.Create("abc", SecurityType.Cfd, Market.USA); var marketHoursDbEntry = _marketHoursDatabase.SetEntryAlwaysOpen(Market.USA, "abc", SecurityType.Cfd, TimeZones.NewYork); var defaultQuoteCurrency = CashBook.AccountCurrency; var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(symbol.ID.Market, symbol, symbol.ID.SecurityType, defaultQuoteCurrency); var subscriptions = SecurityManager.CreateSecurity(typeof(QuoteBar), _securityPortfolioManager, _subscriptionManager, marketHoursDbEntry.ExchangeHours, marketHoursDbEntry.DataTimeZone, symbolProperties, _securityInitializer, symbol, Resolution.Second, false, 1.0m, false, false, false, false); Assert.AreEqual(subscriptions.Subscriptions.Count(), 1); Assert.AreEqual(subscriptions.Subscriptions.First().Type, typeof(QuoteBar)); Assert.AreEqual(subscriptions.Subscriptions.First().TickType, TickType.Quote); }
public void CanCreate_Cfd_WithCorrectSubscriptions() { var symbol = Symbol.Create("abc", SecurityType.Cfd, Market.USA); _marketHoursDatabase.SetEntryAlwaysOpen(Market.USA, "abc", SecurityType.Cfd, TimeZones.NewYork); var configs = _subscriptionManager.SubscriptionDataConfigService.Add(typeof(QuoteBar), symbol, Resolution.Second, false, false, false); var cfd = _securityService.CreateSecurity(symbol, configs, 1.0m, false); Assert.AreEqual(cfd.Subscriptions.Count(), 1); Assert.AreEqual(cfd.Subscriptions.First().Type, typeof(QuoteBar)); Assert.AreEqual(cfd.Subscriptions.First().TickType, TickType.Quote); }
/// <summary> /// AddData a new user defined data source, requiring only the minimum config options. /// </summary> /// <param name="dataType">Data source type</param> /// <param name="symbol">Key/Symbol for data</param> /// <param name="resolution">Resolution of the Data Required</param> /// <param name="timeZone">Specifies the time zone of the raw data</param> /// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param> /// <param name="leverage">Custom leverage per security</param> /// <returns>The new <see cref="Security"/></returns> public Security AddData(Type dataType, string symbol, Resolution resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m) { var marketHoursDbEntry = MarketHoursDatabase.SetEntryAlwaysOpen(Market.USA, symbol, SecurityType.Base, timeZone); //Add this to the data-feed subscriptions var symbolObject = new Symbol(SecurityIdentifier.GenerateBase(symbol, Market.USA), symbol); var symbolProperties = _symbolPropertiesDatabase.GetSymbolProperties(Market.USA, symbol, SecurityType.Base, CashBook.AccountCurrency); //Add this new generic data as a tradeable security: var security = SecurityManager.CreateSecurity(dataType, Portfolio, SubscriptionManager, marketHoursDbEntry.ExchangeHours, marketHoursDbEntry.DataTimeZone, symbolProperties, SecurityInitializer, symbolObject, resolution, fillDataForward, leverage, true, false, true, LiveMode); AddToUserDefinedUniverse(security); return(security); }
/// <summary> /// Creates and adds a list of <see cref="SubscriptionDataConfig" /> for a given symbol and configuration. /// Can optionally pass in desired subscription data types to use. /// If the config already existed will return existing instance instead /// </summary> public List <SubscriptionDataConfig> Add( Symbol symbol, Resolution?resolution = null, bool fillForward = true, bool extendedMarketHours = false, bool isFilteredSubscription = true, bool isInternalFeed = false, bool isCustomData = false, List <Tuple <Type, TickType> > subscriptionDataTypes = null, DataNormalizationMode dataNormalizationMode = DataNormalizationMode.Adjusted ) { var dataTypes = subscriptionDataTypes ?? LookupSubscriptionConfigDataTypes(symbol.SecurityType, resolution ?? Resolution.Minute, symbol.IsCanonical()); if (!dataTypes.Any()) { throw new ArgumentNullException(nameof(dataTypes), "At least one type needed to create new subscriptions"); } var resolutionWasProvided = resolution.HasValue; foreach (var typeTuple in dataTypes) { var baseInstance = typeTuple.Item1.GetBaseDataInstance(); baseInstance.Symbol = symbol; if (!resolutionWasProvided) { var defaultResolution = baseInstance.DefaultResolution(); if (resolution.HasValue && resolution != defaultResolution) { // we are here because there are multiple 'dataTypes'. // if we get different default resolutions lets throw, this shouldn't happen throw new InvalidOperationException( $"Different data types ({string.Join(",", dataTypes.Select(tuple => tuple.Item1))})" + $" provided different default resolutions {defaultResolution} and {resolution}, this is an unexpected invalid operation."); } resolution = defaultResolution; } else { // only assert resolution in backtesting, live can use other data source // for example daily data for options if (!_liveMode) { var supportedResolutions = baseInstance.SupportedResolutions(); if (supportedResolutions.Contains(resolution.Value)) { continue; } throw new ArgumentException($"Sorry {resolution.ToStringInvariant()} is not a supported resolution for {typeTuple.Item1.Name}" + $" and SecurityType.{symbol.SecurityType.ToStringInvariant()}." + $" Please change your AddData to use one of the supported resolutions ({string.Join(",", supportedResolutions)})."); } } } MarketHoursDatabase.Entry marketHoursDbEntry; if (!_marketHoursDatabase.TryGetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType, out marketHoursDbEntry)) { if (symbol.SecurityType == SecurityType.Base) { var baseInstance = dataTypes.Single().Item1.GetBaseDataInstance(); baseInstance.Symbol = symbol; _marketHoursDatabase.SetEntryAlwaysOpen(symbol.ID.Market, null, SecurityType.Base, baseInstance.DataTimeZone()); } marketHoursDbEntry = _marketHoursDatabase.GetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType); } var exchangeHours = marketHoursDbEntry.ExchangeHours; if (symbol.ID.SecurityType.IsOption() || symbol.ID.SecurityType == SecurityType.Future || symbol.ID.SecurityType == SecurityType.Index) { dataNormalizationMode = DataNormalizationMode.Raw; } if (marketHoursDbEntry.DataTimeZone == null) { throw new ArgumentNullException(nameof(marketHoursDbEntry.DataTimeZone), "DataTimeZone is a required parameter for new subscriptions. Set to the time zone the raw data is time stamped in."); } if (exchangeHours.TimeZone == null) { throw new ArgumentNullException(nameof(exchangeHours.TimeZone), "ExchangeTimeZone is a required parameter for new subscriptions. Set to the time zone the security exchange resides in."); } var result = (from subscriptionDataType in dataTypes let dataType = subscriptionDataType.Item1 let tickType = subscriptionDataType.Item2 select new SubscriptionDataConfig( dataType, symbol, resolution.Value, marketHoursDbEntry.DataTimeZone, exchangeHours.TimeZone, fillForward, extendedMarketHours, // if the subscription data types were not provided and the tick type is OpenInterest we make it internal subscriptionDataTypes == null && tickType == TickType.OpenInterest || isInternalFeed, isCustomData, isFilteredSubscription: isFilteredSubscription, tickType: tickType, dataNormalizationMode: dataNormalizationMode)).ToList(); for (int i = 0; i < result.Count; i++) { result[i] = SubscriptionManagerGetOrAdd(result[i]); // track all registered data types _registeredTypesProvider.RegisterType(result[i].Type); } return(result); }