/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using QuantConnect.Data; using QuantConnect.Interfaces; namespace QuantConnect.Securities { /// /// Enumerable security management class for grouping security objects into an array and providing any common properties. /// /// Implements IDictionary for the index searching of securities by symbol public class SecurityManager : IDictionary, INotifyCollectionChanged { /// /// Event fired when a security is added or removed from this collection /// public event NotifyCollectionChangedEventHandler CollectionChanged; private readonly ITimeKeeper _timeKeeper; //Internal dictionary implementation: private readonly ConcurrentDictionary _securityManager; private SecurityService _securityService; /// /// Gets the most recent time this manager was updated /// public DateTime UtcTime { get { return _timeKeeper.UtcTime; } } /// /// Initialise the algorithm security manager with two empty dictionaries /// /// public SecurityManager(ITimeKeeper timeKeeper) { _timeKeeper = timeKeeper; _securityManager = new ConcurrentDictionary(); } /// /// Add a new security with this symbol to the collection. /// /// IDictionary implementation /// symbol for security we're trading /// security object /// public void Add(Symbol symbol, Security security) { if (_securityManager.TryAdd(symbol, security)) { security.SetLocalTimeKeeper(_timeKeeper.GetLocalTimeKeeper(security.Exchange.TimeZone)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, security)); } } /// /// Add a new security with this symbol to the collection. /// /// security object public void Add(Security security) { Add(security.Symbol, security); } /// /// Add a symbol-security by its key value pair. /// /// IDictionary implementation /// public void Add(KeyValuePair pair) { Add(pair.Key, pair.Value); } /// /// Clear the securities array to delete all the portfolio and asset information. /// /// IDictionary implementation public void Clear() { _securityManager.Clear(); } /// /// Check if this collection contains this key value pair. /// /// Search key-value pair /// IDictionary implementation /// Bool true if contains this key-value pair public bool Contains(KeyValuePair pair) { return _securityManager.Contains(pair); } /// /// Check if this collection contains this symbol. /// /// Symbol we're checking for. /// IDictionary implementation /// Bool true if contains this symbol pair public bool ContainsKey(Symbol symbol) { return _securityManager.ContainsKey(symbol); } /// /// Copy from the internal array to an external array. /// /// Array we're outputting to /// Starting index of array /// IDictionary implementation public void CopyTo(KeyValuePair[] array, int number) { ((IDictionary)_securityManager).CopyTo(array, number); } /// /// Count of the number of securities in the collection. /// /// IDictionary implementation public int Count => _securityManager.Skip(0).Count(); /// /// Flag indicating if the internal arrray is read only. /// /// IDictionary implementation public bool IsReadOnly { get { return false; } } /// /// Remove a key value of of symbol-securities from the collections. /// /// IDictionary implementation /// Key Value pair of symbol-security to remove /// Boolean true on success public bool Remove(KeyValuePair pair) { return Remove(pair.Key); } /// /// Remove this symbol security: Dictionary interface implementation. /// /// Symbol we're searching for /// true success public bool Remove(Symbol symbol) { Security security; if (_securityManager.TryRemove(symbol, out security)) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, security)); return true; } return false; } /// /// List of the symbol-keys in the collection of securities. /// /// IDictionary implementation public ICollection Keys => _securityManager.Select(x => x.Key).ToList(); /// /// Try and get this security object with matching symbol and return true on success. /// /// String search symbol /// Output Security object /// IDictionary implementation /// True on successfully locating the security object public bool TryGetValue(Symbol symbol, out Security security) { return _securityManager.TryGetValue(symbol, out security); } /// /// Get a list of the security objects for this collection. /// /// IDictionary implementation public ICollection Values => _securityManager.Select(x => x.Value).ToList(); /// /// Get the enumerator for this security collection. /// /// IDictionary implementation /// Enumerable key value pair IEnumerator> IEnumerable>.GetEnumerator() { return _securityManager.GetEnumerator(); } /// /// Get the enumerator for this securities collection. /// /// IDictionary implementation /// Enumerator. IEnumerator IEnumerable.GetEnumerator() { return _securityManager.GetEnumerator(); } /// /// Indexer method for the security manager to access the securities objects by their symbol. /// /// IDictionary implementation /// Symbol object indexer /// Security public Security this[Symbol symbol] { get { Security security; if (!_securityManager.TryGetValue(symbol, out security)) { throw new Exception(string.Format("This asset symbol ({0}) was not found in your security list. Please add this security or check it exists before using it with 'Securities.ContainsKey(\"{1}\")'", symbol, SymbolCache.GetTicker(symbol))); } return security; } set { Security existing; if (_securityManager.TryGetValue(symbol, out existing) && existing != value) { throw new ArgumentException("Unable to over write existing Security: " + symbol.ToString()); } // no security exists for the specified symbol key, add it now if (existing == null) { Add(symbol, value); } } } /// /// Indexer method for the security manager to access the securities objects by their symbol. /// /// IDictionary implementation /// string ticker symbol indexer /// Security public Security this[string ticker] { get { Symbol symbol; if (!SymbolCache.TryGetSymbol(ticker, out symbol)) { throw new Exception(string.Format("This asset symbol ({0}) was not found in your security list. Please add this security or check it exists before using it with 'Securities.ContainsKey(\"{0}\")'", ticker)); } return this[symbol]; } set { Symbol symbol; if (!SymbolCache.TryGetSymbol(ticker, out symbol)) { throw new Exception(string.Format("This asset symbol ({0}) was not found in your security list. Please add this security or check it exists before using it with 'Securities.ContainsKey(\"{0}\")'", ticker)); } this[symbol] = value; } } /// /// Event invocator for the event /// /// Event arguments for the event protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs changedEventArgs) { var handler = CollectionChanged; if (handler != null) handler(this, changedEventArgs); } /// /// Sets the Security Service to be used /// public void SetSecurityService(SecurityService securityService) { _securityService = securityService; } /// /// Creates a new security /// /// Following the obsoletion of Security.Subscriptions, /// both overloads will be merged removing arguments public Security CreateSecurity( Symbol symbol, List subscriptionDataConfigList, decimal leverage = 0, bool addToSymbolCache = true) { return _securityService.CreateSecurity(symbol, subscriptionDataConfigList, leverage, addToSymbolCache); } /// /// Creates a new security /// /// Following the obsoletion of Security.Subscriptions, /// both overloads will be merged removing arguments public Security CreateSecurity( Symbol symbol, SubscriptionDataConfig subscriptionDataConfig, decimal leverage = 0, bool addToSymbolCache = true ) { return _securityService.CreateSecurity(symbol, subscriptionDataConfig, leverage, addToSymbolCache); } /// /// Set live mode state of the algorithm /// /// True, live mode is enabled public void SetLiveMode(bool isLiveMode) { _securityService.SetLiveMode(isLiveMode); } } }