コード例 #1
0
 /// <summary>
 /// Creates a new instance of the SecurityService class
 /// </summary>
 public SecurityService(CashBook cashBook,
                        MarketHoursDatabase marketHoursDatabase,
                        SymbolPropertiesDatabase symbolPropertiesDatabase,
                        ISecurityInitializerProvider securityInitializerProvider,
                        IRegisteredSecurityDataTypesProvider registeredTypes)
 {
     _cashBook                    = cashBook;
     _registeredTypes             = registeredTypes;
     _marketHoursDatabase         = marketHoursDatabase;
     _symbolPropertiesDatabase    = symbolPropertiesDatabase;
     _securityInitializerProvider = securityInitializerProvider;
 }
コード例 #2
0
 /// <summary>
 /// Gets the instance of the <see cref="SymbolPropertiesDatabase"/> class produced by reading in the symbol properties
 /// data found in /Data/symbol-properties/
 /// </summary>
 /// <returns>A <see cref="SymbolPropertiesDatabase"/> class that represents the data in the symbol-properties folder</returns>
 public static SymbolPropertiesDatabase FromDataFolder()
 {
     lock (DataFolderSymbolPropertiesDatabaseLock)
     {
         if (_dataFolderSymbolPropertiesDatabase == null)
         {
             var directory = Path.Combine(Globals.DataFolder, "symbol-properties");
             _dataFolderSymbolPropertiesDatabase = FromCsvFile(Path.Combine(directory, "symbol-properties-database.csv"));
         }
     }
     return(_dataFolderSymbolPropertiesDatabase);
 }
コード例 #3
0
 /// <summary>
 /// Gets the instance of the <see cref="SymbolPropertiesDatabase"/> class produced by reading in the symbol properties
 /// data found in /Data/symbol-properties/
 /// </summary>
 /// <returns>A <see cref="SymbolPropertiesDatabase"/> class that represents the data in the symbol-properties folder</returns>
 public static SymbolPropertiesDatabase FromDataFolder()
 {
     lock (DataFolderSymbolPropertiesDatabaseLock)
     {
         if (_dataFolderSymbolPropertiesDatabase == null)
         {
             var directory = Path.Combine(Globals.DataFolder, "symbol-properties");
             _dataFolderSymbolPropertiesDatabase = FromCsvFile(Path.Combine(directory, "symbol-properties-database.csv"));
         }
     }
     return _dataFolderSymbolPropertiesDatabase;
 }
コード例 #4
0
 /// <summary>
 /// Creates a new instance of the SecurityService class
 /// </summary>
 public SecurityService(CashBook cashBook,
                        MarketHoursDatabase marketHoursDatabase,
                        SymbolPropertiesDatabase symbolPropertiesDatabase,
                        ISecurityInitializerProvider securityInitializerProvider,
                        IRegisteredSecurityDataTypesProvider registeredTypes,
                        SecurityCacheProvider cacheProvider,
                        IPrimaryExchangeProvider primaryExchangeProvider = null)
 {
     _cashBook                    = cashBook;
     _registeredTypes             = registeredTypes;
     _marketHoursDatabase         = marketHoursDatabase;
     _symbolPropertiesDatabase    = symbolPropertiesDatabase;
     _securityInitializerProvider = securityInitializerProvider;
     _cacheProvider               = cacheProvider;
     _primaryExchangeProvider     = primaryExchangeProvider;
 }
コード例 #5
0
        private static IEnumerable <KeyValuePair <SecurityDatabaseKey, SymbolProperties> > GetAvailableSymbolPropertiesDatabaseEntries(
            SecurityType securityType,
            IReadOnlyDictionary <SecurityType, string> marketMap,
            IReadOnlyDictionary <SecurityType, string> markets
            )
        {
            var marketJoin = new HashSet <string>();

            {
                string market;
                if (marketMap.TryGetValue(securityType, out market))
                {
                    marketJoin.Add(market);
                }
                if (markets.TryGetValue(securityType, out market))
                {
                    marketJoin.Add(market);
                }
            }

            return(marketJoin.SelectMany(market => SymbolPropertiesDatabase.FromDataFolder()
                                         .GetSymbolPropertiesList(market, securityType)));
        }
コード例 #6
0
        private static IEnumerable <Symbol> GetAvailableSymbols(
            SecurityType securityType,
            IReadOnlyDictionary <SecurityType, string> marketMap,
            IReadOnlyDictionary <SecurityType, string> markets
            )
        {
            var marketJoin = new HashSet <string>();

            {
                string market;
                if (marketMap.TryGetValue(securityType, out market))
                {
                    marketJoin.Add(market);
                }
                if (markets.TryGetValue(securityType, out market))
                {
                    marketJoin.Add(market);
                }
            }

            return(marketJoin.SelectMany(market => SymbolPropertiesDatabase.FromDataFolder()
                                         .GetSymbolPropertiesList(market, securityType)
                                         .Select(x => QuantConnect.Symbol.Create(x.Key.Symbol, securityType, market))));
        }
コード例 #7
0
ファイル: SecurityManager.cs プロジェクト: xhxuciedu/Lean
        /// <summary>
        /// Creates a security and matching configuration. This applies the default leverage if
        /// leverage is less than or equal to zero.
        /// This method also add the new symbol mapping to the <see cref="SymbolCache"/>
        /// </summary>
        public static Security CreateSecurity(SecurityPortfolioManager securityPortfolioManager,
                                              SubscriptionManager subscriptionManager,
                                              MarketHoursDatabase marketHoursDatabase,
                                              SymbolPropertiesDatabase symbolPropertiesDatabase,
                                              ISecurityInitializer securityInitializer,
                                              Symbol symbol,
                                              Resolution resolution,
                                              bool fillDataForward,
                                              decimal leverage,
                                              bool extendedMarketHours,
                                              bool isInternalFeed,
                                              bool isCustomData,
                                              bool isLiveMode,
                                              bool addToSymbolCache = true
                                              )
        {
            var marketHoursDbEntry = marketHoursDatabase.GetEntry(symbol.ID.Market, symbol.Value, symbol.ID.SecurityType);
            var exchangeHours      = marketHoursDbEntry.ExchangeHours;

            var defaultQuoteCurrency = CashBook.AccountCurrency;

            if (symbol.ID.SecurityType == SecurityType.Forex)
            {
                defaultQuoteCurrency = symbol.Value.Substring(3);
            }
            var symbolProperties = symbolPropertiesDatabase.GetSymbolProperties(symbol.ID.Market, symbol.Value, symbol.ID.SecurityType, defaultQuoteCurrency);

            var type = resolution == Resolution.Tick ? typeof(Tick) : typeof(TradeBar);

            if (symbol.ID.SecurityType == SecurityType.Option && resolution != Resolution.Tick)
            {
                type = typeof(QuoteBar);
            }
            return(CreateSecurity(type, securityPortfolioManager, subscriptionManager, exchangeHours, marketHoursDbEntry.DataTimeZone, symbolProperties, securityInitializer, symbol, resolution,
                                  fillDataForward, leverage, extendedMarketHours, isInternalFeed, isCustomData, isLiveMode, addToSymbolCache));
        }
コード例 #8
0
ファイル: CashBook.cs プロジェクト: scotb/Lean
        /// <summary>
        /// Checks the current subscriptions and adds necessary currency pair feeds to provide real time conversion data
        /// </summary>
        /// <param name="securities">The SecurityManager for the algorithm</param>
        /// <param name="subscriptions">The SubscriptionManager for the algorithm</param>
        /// <param name="marketHoursDatabase">A security exchange hours provider instance used to resolve exchange hours for new subscriptions</param>
        /// <param name="symbolPropertiesDatabase">A symbol properties database instance</param>
        /// <param name="marketMap">The market map that decides which market the new security should be in</param>
        /// <returns>Returns a list of added currency securities</returns>
        public List <Security> EnsureCurrencyDataFeeds(SecurityManager securities, SubscriptionManager subscriptions, MarketHoursDatabase marketHoursDatabase, SymbolPropertiesDatabase symbolPropertiesDatabase, IReadOnlyDictionary <SecurityType, string> marketMap, SecurityChanges changes)
        {
            var addedSecurities = new List <Security>();

            foreach (var kvp in _currencies)
            {
                var cash = kvp.Value;

                var security = cash.EnsureCurrencyDataFeed(securities, subscriptions, marketHoursDatabase, symbolPropertiesDatabase, marketMap, this, changes);
                if (security != null)
                {
                    addedSecurities.Add(security);
                }
            }
            return(addedSecurities);
        }
コード例 #9
0
ファイル: Cash.cs プロジェクト: won21kr/Lean
        /// <summary>
        /// Ensures that we have a data feed to convert this currency into the base currency.
        /// This will add a subscription at the lowest resolution if one is not found.
        /// </summary>
        /// <param name="securities">The security manager</param>
        /// <param name="subscriptions">The subscription manager used for searching and adding subscriptions</param>
        /// <param name="marketHoursDatabase">A security exchange hours provider instance used to resolve exchange hours for new subscriptions</param>
        /// <param name="symbolPropertiesDatabase">A symbol properties database instance</param>
        /// <param name="marketMap">The market map that decides which market the new security should be in</param>
        /// <param name="cashBook">The cash book - used for resolving quote currencies for created conversion securities</param>
        /// <returns>Returns the added currency security if needed, otherwise null</returns>
        public Security EnsureCurrencyDataFeed(SecurityManager securities, SubscriptionManager subscriptions, MarketHoursDatabase marketHoursDatabase, SymbolPropertiesDatabase symbolPropertiesDatabase, IReadOnlyDictionary <SecurityType, string> marketMap, CashBook cashBook)
        {
            if (Symbol == CashBook.AccountCurrency)
            {
                SecuritySymbol  = QuantConnect.Symbol.Empty;
                _isBaseCurrency = true;
                ConversionRate  = 1.0m;
                return(null);
            }

            if (subscriptions.Count == 0)
            {
                throw new InvalidOperationException("Unable to add cash when no subscriptions are present. Please add subscriptions in the Initialize() method.");
            }

            // we require a subscription that converts this into the base currency
            string normal = Symbol + CashBook.AccountCurrency;
            string invert = CashBook.AccountCurrency + Symbol;

            foreach (var config in subscriptions.Subscriptions.Where(config => config.SecurityType == SecurityType.Forex || config.SecurityType == SecurityType.Cfd))
            {
                if (config.Symbol.Value == normal)
                {
                    SecuritySymbol = config.Symbol;
                    return(null);
                }
                if (config.Symbol.Value == invert)
                {
                    SecuritySymbol       = config.Symbol;
                    _invertRealTimePrice = true;
                    return(null);
                }
            }
            // if we've made it here we didn't find a subscription, so we'll need to add one
            var currencyPairs = Currencies.CurrencyPairs.Select(x =>
            {
                // allow XAU or XAG to be used as quote currencies, but pairs including them are CFDs
                var securityType = Symbol.StartsWith("X") ? SecurityType.Cfd : SecurityType.Forex;
                var market       = marketMap[securityType];
                return(QuantConnect.Symbol.Create(x, securityType, market));
            });
            var minimumResolution = subscriptions.Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(Resolution.Minute).Min();
            var objectType        = minimumResolution == Resolution.Tick ? typeof(Tick) : typeof(TradeBar);

            foreach (var symbol in currencyPairs)
            {
                if (symbol.Value == normal || symbol.Value == invert)
                {
                    _invertRealTimePrice = symbol.Value == invert;
                    var  securityType     = symbol.ID.SecurityType;
                    var  symbolProperties = symbolPropertiesDatabase.GetSymbolProperties(symbol.ID.Market, symbol.Value, securityType, Symbol);
                    Cash quoteCash;
                    if (!cashBook.TryGetValue(symbolProperties.QuoteCurrency, out quoteCash))
                    {
                        throw new Exception("Unable to resolve quote cash: " + symbolProperties.QuoteCurrency + ". This is required to add conversion feed: " + symbol.ToString());
                    }
                    var marketHoursDbEntry = marketHoursDatabase.GetEntry(symbol.ID.Market, symbol.Value, symbol.ID.SecurityType);
                    var exchangeHours      = marketHoursDbEntry.ExchangeHours;
                    // set this as an internal feed so that the data doesn't get sent into the algorithm's OnData events
                    var config = subscriptions.Add(objectType, symbol, minimumResolution, marketHoursDbEntry.DataTimeZone, exchangeHours.TimeZone, false, true, false, true);
                    SecuritySymbol = config.Symbol;

                    Security security;
                    if (securityType == SecurityType.Cfd)
                    {
                        security = new Cfd.Cfd(exchangeHours, quoteCash, config, symbolProperties);
                    }
                    else
                    {
                        security = new Forex.Forex(exchangeHours, quoteCash, config, symbolProperties);
                    }
                    securities.Add(config.Symbol, security);
                    Log.Trace("Cash.EnsureCurrencyDataFeed(): Adding " + symbol.Value + " for cash " + Symbol + " currency feed");
                    return(security);
                }
            }

            // if this still hasn't been set then it's an error condition
            throw new ArgumentException(string.Format("In order to maintain cash in {0} you are required to add a subscription for Forex pair {0}{1} or {1}{0}", Symbol, CashBook.AccountCurrency));
        }
コード例 #10
0
ファイル: Cash.cs プロジェクト: pmerrill/Lean
        /// <summary>
        /// Ensures that we have a data feed to convert this currency into the base currency.
        /// This will add a subscription at the lowest resolution if one is not found.
        /// </summary>
        /// <param name="securities">The security manager</param>
        /// <param name="subscriptions">The subscription manager used for searching and adding subscriptions</param>
        /// <param name="marketHoursDatabase">A security exchange hours provider instance used to resolve exchange hours for new subscriptions</param>
        /// <param name="symbolPropertiesDatabase">A symbol properties database instance</param>
        /// <param name="marketMap">The market map that decides which market the new security should be in</param>
        /// <param name="cashBook">The cash book - used for resolving quote currencies for created conversion securities</param>
        /// <returns>Returns the added currency security if needed, otherwise null</returns>
        public Security EnsureCurrencyDataFeed(SecurityManager securities, SubscriptionManager subscriptions, MarketHoursDatabase marketHoursDatabase, SymbolPropertiesDatabase symbolPropertiesDatabase, IReadOnlyDictionary<SecurityType, string> marketMap, CashBook cashBook)
        {
            if (Symbol == CashBook.AccountCurrency)
            {
                SecuritySymbol = QuantConnect.Symbol.Empty;
                _isBaseCurrency = true;
                ConversionRate = 1.0m;
                return null;
            }

            if (subscriptions.Count == 0)
            {
                throw new InvalidOperationException("Unable to add cash when no subscriptions are present. Please add subscriptions in the Initialize() method.");
            }

            // we require a subscription that converts this into the base currency
            string normal = Symbol + CashBook.AccountCurrency;
            string invert = CashBook.AccountCurrency + Symbol;
            foreach (var config in subscriptions.Subscriptions.Where(config => config.SecurityType == SecurityType.Forex || config.SecurityType == SecurityType.Cfd))
            {
                if (config.Symbol.Value == normal)
                {
                    SecuritySymbol = config.Symbol;
                    return null;
                }
                if (config.Symbol.Value == invert)
                {
                    SecuritySymbol = config.Symbol;
                    _invertRealTimePrice = true;
                    return null;
                }
            }
            // if we've made it here we didn't find a subscription, so we'll need to add one
            var currencyPairs = Currencies.CurrencyPairs.Select(x =>
            {
                // allow XAU or XAG to be used as quote currencies, but pairs including them are CFDs
                var securityType = Symbol.StartsWith("X") ? SecurityType.Cfd : SecurityType.Forex;
                var market = marketMap[securityType];
                return QuantConnect.Symbol.Create(x, securityType, market);
            });
            var minimumResolution = subscriptions.Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(Resolution.Minute).Min();
            var objectType = minimumResolution == Resolution.Tick ? typeof (Tick) : typeof (TradeBar);
            foreach (var symbol in currencyPairs)
            {
                if (symbol.Value == normal || symbol.Value == invert)
                {
                    _invertRealTimePrice = symbol.Value == invert;
                    var marketHoursDbEntry = marketHoursDatabase.GetEntry(symbol.ID.Market, symbol.Value, symbol.ID.SecurityType);
                    var exchangeHours = marketHoursDbEntry.ExchangeHours;
                    // set this as an internal feed so that the data doesn't get sent into the algorithm's OnData events
                    var config = subscriptions.Add(objectType, symbol, minimumResolution, marketHoursDbEntry.DataTimeZone, exchangeHours.TimeZone, false, true, false, true);
                    SecuritySymbol = config.Symbol;

                    var securityType = symbol.ID.SecurityType;
                    Security security;
                    if (securityType == SecurityType.Cfd)
                    {
                        var symbolProperties = symbolPropertiesDatabase.GetSymbolProperties(symbol.ID.Market, symbol.Value, securityType);
                        Cash quoteCash;
                        if (!cashBook.TryGetValue(symbolProperties.QuoteCurrency, out quoteCash))
                        {
                            throw new Exception("Unable to resolve quote cash: " + symbolProperties.QuoteCurrency + ". This is required to add conversion feed: " + symbol.ToString());
                        }
                        security = new Cfd.Cfd(exchangeHours, quoteCash, config, symbolProperties);
                    }
                    else
                    {
                        security = new Forex.Forex(exchangeHours, this, config);
                    }
                    securities.Add(config.Symbol, security);
                    Log.Trace("Cash.EnsureCurrencyDataFeed(): Adding " + symbol.Value + " for cash " + Symbol + " currency feed");
                    return security;
                }
            }

            // if this still hasn't been set then it's an error condition
            throw new ArgumentException(string.Format("In order to maintain cash in {0} you are required to add a subscription for Forex pair {0}{1} or {1}{0}", Symbol, CashBook.AccountCurrency));
        }
コード例 #11
0
ファイル: Cash.cs プロジェクト: beezy3601/lean2
        /// <summary>
        /// Ensures that we have a data feed to convert this currency into the base currency.
        /// This will add a subscription at the lowest resolution if one is not found.
        /// </summary>
        /// <param name="securities">The security manager</param>
        /// <param name="subscriptions">The subscription manager used for searching and adding subscriptions</param>
        /// <param name="marketHoursDatabase">A security exchange hours provider instance used to resolve exchange hours for new subscriptions</param>
        /// <param name="symbolPropertiesDatabase">A symbol properties database instance</param>
        /// <param name="marketMap">The market map that decides which market the new security should be in</param>
        /// <param name="cashBook">The cash book - used for resolving quote currencies for created conversion securities</param>
        /// <param name="changes"></param>
        /// <returns>Returns the added currency security if needed, otherwise null</returns>
        public Security EnsureCurrencyDataFeed(SecurityManager securities,
                                               SubscriptionManager subscriptions,
                                               MarketHoursDatabase marketHoursDatabase,
                                               SymbolPropertiesDatabase symbolPropertiesDatabase,
                                               IReadOnlyDictionary <SecurityType, string> marketMap,
                                               CashBook cashBook,
                                               SecurityChanges changes
                                               )
        {
            // this gets called every time we add securities using universe selection,
            // so must of the time we've already resolved the value and don't need to again
            if (ConversionRateSecurity != null)
            {
                return(null);
            }

            if (Symbol == CashBook.AccountCurrency)
            {
                ConversionRateSecurity = null;
                _isBaseCurrency        = true;
                ConversionRate         = 1.0m;
                return(null);
            }

            // we require a security that converts this into the base currency
            string normal             = Symbol + CashBook.AccountCurrency;
            string invert             = CashBook.AccountCurrency + Symbol;
            var    securitiesToSearch = securities.Select(kvp => kvp.Value)
                                        .Concat(changes.AddedSecurities)
                                        .Where(s => s.Type == SecurityType.Forex || s.Type == SecurityType.Cfd || s.Type == SecurityType.Crypto);

            foreach (var security in securitiesToSearch)
            {
                if (security.Symbol.Value == normal)
                {
                    ConversionRateSecurity = security;
                    return(null);
                }
                if (security.Symbol.Value == invert)
                {
                    ConversionRateSecurity = security;
                    _invertRealTimePrice   = true;
                    return(null);
                }
            }
            // if we've made it here we didn't find a security, so we'll need to add one

            // Create a SecurityType to Market mapping with the markets from SecurityManager members
            var markets = securities.Select(x => x.Key).GroupBy(x => x.SecurityType).ToDictionary(x => x.Key, y => y.First().ID.Market);

            if (markets.ContainsKey(SecurityType.Cfd) && !markets.ContainsKey(SecurityType.Forex))
            {
                markets.Add(SecurityType.Forex, markets[SecurityType.Cfd]);
            }
            if (markets.ContainsKey(SecurityType.Forex) && !markets.ContainsKey(SecurityType.Cfd))
            {
                markets.Add(SecurityType.Cfd, markets[SecurityType.Forex]);
            }

            var potentials = Currencies.CurrencyPairs.Select(fx => CreateSymbol(marketMap, fx, markets, SecurityType.Forex))
                             .Concat(Currencies.CfdCurrencyPairs.Select(cfd => CreateSymbol(marketMap, cfd, markets, SecurityType.Cfd)))
                             .Concat(Currencies.CryptoCurrencyPairs.Select(crypto => CreateSymbol(marketMap, crypto, markets, SecurityType.Crypto)));

            var minimumResolution = subscriptions.Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(Resolution.Minute).Min();
            var objectType        = minimumResolution == Resolution.Tick ? typeof(Tick) : typeof(QuoteBar);

            foreach (var symbol in potentials)
            {
                if (symbol.Value == normal || symbol.Value == invert)
                {
                    _invertRealTimePrice = symbol.Value == invert;
                    var  securityType     = symbol.ID.SecurityType;
                    var  symbolProperties = symbolPropertiesDatabase.GetSymbolProperties(symbol.ID.Market, symbol.Value, securityType, Symbol);
                    Cash quoteCash;
                    if (!cashBook.TryGetValue(symbolProperties.QuoteCurrency, out quoteCash))
                    {
                        throw new Exception("Unable to resolve quote cash: " + symbolProperties.QuoteCurrency + ". This is required to add conversion feed: " + symbol.Value);
                    }
                    var marketHoursDbEntry = marketHoursDatabase.GetEntry(symbol.ID.Market, symbol.Value, symbol.ID.SecurityType);
                    var exchangeHours      = marketHoursDbEntry.ExchangeHours;
                    // set this as an internal feed so that the data doesn't get sent into the algorithm's OnData events
                    var config = subscriptions.Add(objectType, TickType.Quote, symbol, minimumResolution, marketHoursDbEntry.DataTimeZone, exchangeHours.TimeZone, false, true, false, true);

                    Security security;
                    if (securityType == SecurityType.Cfd)
                    {
                        security = new Cfd.Cfd(exchangeHours, quoteCash, config, symbolProperties);
                    }
                    else if (securityType == SecurityType.Crypto)
                    {
                        security = new Crypto.Crypto(exchangeHours, quoteCash, config, symbolProperties);
                    }
                    else
                    {
                        security = new Forex.Forex(exchangeHours, quoteCash, config, symbolProperties);
                    }

                    ConversionRateSecurity = security;
                    securities.Add(config.Symbol, security);
                    Log.Trace("Cash.EnsureCurrencyDataFeed(): Adding " + symbol.Value + " for cash " + Symbol + " currency feed");
                    return(security);
                }
            }

            // if this still hasn't been set then it's an error condition
            throw new ArgumentException(string.Format("In order to maintain cash in {0} you are required to add a subscription for Forex pair {0}{1} or {1}{0}", Symbol, CashBook.AccountCurrency));
        }
コード例 #12
0
 /// <summary>
 /// Creates and configures a security for the specified symbol
 /// </summary>
 /// <param name="symbol">The symbol of the security to be created</param>
 /// <param name="algorithm">The algorithm instance</param>
 /// <param name="marketHoursDatabase">The market hours database</param>
 /// <param name="symbolPropertiesDatabase">The symbol properties database</param>
 /// <returns>The newly initialized security object</returns>
 public override Security CreateSecurity(Symbol symbol, IAlgorithm algorithm, MarketHoursDatabase marketHoursDatabase, SymbolPropertiesDatabase symbolPropertiesDatabase)
 {
     // set the underlying security and pricing model from the canonical security
     var option = (Option)base.CreateSecurity(symbol, algorithm, marketHoursDatabase, symbolPropertiesDatabase);
     option.Underlying = _option.Underlying;
     option.PriceModel = _option.PriceModel;
     return option;
 }
コード例 #13
0
 /// <summary>
 /// Creates and configures a security for the specified symbol
 /// </summary>
 /// <param name="symbol">The symbol of the security to be created</param>
 /// <param name="algorithm">The algorithm instance</param>
 /// <param name="marketHoursDatabase">The market hours database</param>
 /// <param name="symbolPropertiesDatabase">The symbol properties database</param>
 /// <returns>The newly initialized security object</returns>
 public override Security CreateSecurity(Symbol symbol, IAlgorithm algorithm, MarketHoursDatabase marketHoursDatabase, SymbolPropertiesDatabase symbolPropertiesDatabase)
 {
     return Universe.CreateSecurity(symbol, algorithm, marketHoursDatabase, symbolPropertiesDatabase);
 }