/* * 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.Linq; using QuantConnect.Data; using System.Collections; using QuantConnect.Interfaces; using System.Collections.Generic; using System.Collections.Specialized; 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 : ExtendedDictionary, 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 Dictionary _securityManager; private readonly Dictionary _completeSecuritiesCollection; // let's keep ah thread safe enumerator created which we reset and recreate if required private List _enumeratorKeys; private List _enumeratorValues; private List> _enumerator; 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(); _completeSecuritiesCollection = new(); } /// /// 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) { bool changed; lock (_securityManager) { changed = _securityManager.TryAdd(symbol, security); if (changed) { _completeSecuritiesCollection[symbol] = security; } } if (changed) { 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 override void Clear() { lock (_securityManager) { _enumerator = null; _enumeratorKeys = null; _enumeratorValues = null; _securityManager.Clear(); _completeSecuritiesCollection.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) { lock (_securityManager) { return _completeSecuritiesCollection.Contains(pair); } } /// /// Check if this collection contains this symbol. /// /// Symbol we're checking for. /// IDictionary implementation /// Bool true if contains this symbol pair public override bool ContainsKey(Symbol symbol) { lock (_securityManager) { return _completeSecuritiesCollection.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) { lock (_securityManager) { ((IDictionary)_securityManager).CopyTo(array, number); } } /// /// Count of the number of securities in the collection. /// /// IDictionary implementation public override int Count { get { lock (_securityManager) { return _securityManager.Count; } } } /// /// Flag indicating if the internal array is read only. /// /// IDictionary implementation public override 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 override bool Remove(Symbol symbol) { Security security; lock (_securityManager) { _securityManager.Remove(symbol, out security); } if (security != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, security)); return true; } return false; } /// /// List of the symbol-keys in the collection of securities. /// /// Excludes non active or delisted securities public ICollection Keys { get { var result = _enumeratorKeys; if (result == null) { lock (_securityManager) { _enumeratorKeys = result = _securityManager.Keys.ToList(); } } return result; } } /// /// 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 override bool TryGetValue(Symbol symbol, out Security security) { lock (_securityManager) { return _completeSecuritiesCollection.TryGetValue(symbol, out security); } } /// /// Gets an containing the Symbol objects of the . /// /// Excludes non active or delisted securities /// /// An containing the Symbol objects of the object that implements . /// protected override IEnumerable GetKeys => Keys; /// /// Gets an containing the values in the . /// /// Excludes non active or delisted securities /// /// An containing the values in the object that implements . /// protected override IEnumerable GetValues => Values; /// /// Get a list of the security objects for this collection. /// /// Excludes non active or delisted securities public ICollection Values { get { var result = _enumeratorValues; if (result == null) { lock (_securityManager) { _enumeratorValues = result = _securityManager.Values.ToList(); } } return result; } } /// /// Get a list of the complete security objects for this collection, including non active or delisted securities /// public ICollection Total { get { ICollection result; lock (_securityManager) { result = _completeSecuritiesCollection.Values.ToList(); } return result; } } /// /// Get the enumerator for this security collection. /// /// IDictionary implementation /// Enumerable key value pair IEnumerator> IEnumerable>.GetEnumerator() { return GetEnumeratorImplementation(); } /// /// Get the enumerator for this securities collection. /// /// IDictionary implementation /// Enumerator. IEnumerator IEnumerable.GetEnumerator() { return GetEnumeratorImplementation(); } private List> GetEnumerable() { var result = _enumerator; if (result == null) { lock (_securityManager) { _enumerator = result = _securityManager.ToList(); } } return result; } private List>.Enumerator GetEnumeratorImplementation() { return GetEnumerable().GetEnumerator(); } /// /// Gets all the items in the dictionary /// /// All the items in the dictionary public override IEnumerable> GetItems() => GetEnumerable(); /// /// Indexer method for the security manager to access the securities objects by their symbol. /// /// IDictionary implementation /// Symbol object indexer /// Security public override Security this[Symbol symbol] { get { Security security; lock (_securityManager) { if (!_completeSecuritiesCollection.TryGetValue(symbol, out security)) { CheckForImplicitlyCreatedSymbol(symbol); throw new KeyNotFoundException(Messages.SecurityManager.SymbolNotFoundInSecurities(symbol)); } } return security; } set { Security existing; lock (_securityManager) { if (_securityManager.TryGetValue(symbol, out existing) && existing != value) { throw new ArgumentException(Messages.SecurityManager.UnableToOverwriteSecurity(symbol)); } } // no security exists for the specified symbol key, add it now if (existing == null) { Add(symbol, value); } } } /// /// Event invocator for the event /// /// Event arguments for the event protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs changedEventArgs) { _enumerator = null; _enumeratorKeys = null; _enumeratorValues = null; CollectionChanged?.Invoke(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, Security underlying = null) { return _securityService.CreateSecurity(symbol, subscriptionDataConfigList, leverage, addToSymbolCache, underlying); } /// /// 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, Security underlying = null ) { return _securityService.CreateSecurity(symbol, subscriptionDataConfig, leverage, addToSymbolCache, underlying); } /// /// Creates a new benchmark security /// public Security CreateBenchmarkSecurity(Symbol symbol) { return _securityService.CreateBenchmarkSecurity(symbol); } /// /// Set live mode state of the algorithm /// /// True, live mode is enabled public void SetLiveMode(bool isLiveMode) { _securityService.SetLiveMode(isLiveMode); } } }