/*
* 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);
}
}
}