Lean  $LEAN_TAG$
SecurityManager.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.Linq;
18 using QuantConnect.Data;
19 using System.Collections;
21 using System.Collections.Generic;
22 using System.Collections.Specialized;
23 
25 {
26  /// <summary>
27  /// Enumerable security management class for grouping security objects into an array and providing any common properties.
28  /// </summary>
29  /// <remarks>Implements IDictionary for the index searching of securities by symbol</remarks>
30  public class SecurityManager : ExtendedDictionary<Security>, IDictionary<Symbol, Security>, INotifyCollectionChanged
31  {
32  /// <summary>
33  /// Event fired when a security is added or removed from this collection
34  /// </summary>
35  public event NotifyCollectionChangedEventHandler CollectionChanged;
36 
37  private readonly ITimeKeeper _timeKeeper;
38 
39  //Internal dictionary implementation:
40  private readonly Dictionary<Symbol, Security> _securityManager;
41  private readonly Dictionary<Symbol, Security> _completeSecuritiesCollection;
42  // let's keep ah thread safe enumerator created which we reset and recreate if required
43  private List<Symbol> _enumeratorKeys;
44  private List<Security> _enumeratorValues;
45  private List<KeyValuePair<Symbol, Security>> _enumerator;
46  private SecurityService _securityService;
47 
48  /// <summary>
49  /// Gets the most recent time this manager was updated
50  /// </summary>
51  public DateTime UtcTime
52  {
53  get { return _timeKeeper.UtcTime; }
54  }
55 
56  /// <summary>
57  /// Initialise the algorithm security manager with two empty dictionaries
58  /// </summary>
59  /// <param name="timeKeeper"></param>
60  public SecurityManager(ITimeKeeper timeKeeper)
61  {
62  _timeKeeper = timeKeeper;
63  _securityManager = new();
64  _completeSecuritiesCollection = new();
65  }
66 
67  /// <summary>
68  /// Add a new security with this symbol to the collection.
69  /// </summary>
70  /// <remarks>IDictionary implementation</remarks>
71  /// <param name="symbol">symbol for security we're trading</param>
72  /// <param name="security">security object</param>
73  /// <seealso cref="Add(Security)"/>
74  public void Add(Symbol symbol, Security security)
75  {
76  bool changed;
77  lock (_securityManager)
78  {
79  changed = _securityManager.TryAdd(symbol, security);
80  if (changed)
81  {
82  _completeSecuritiesCollection[symbol] = security;
83  }
84  }
85 
86  if (changed)
87  {
88  security.SetLocalTimeKeeper(_timeKeeper.GetLocalTimeKeeper(security.Exchange.TimeZone));
89  OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, security));
90  }
91  }
92 
93  /// <summary>
94  /// Add a new security with this symbol to the collection.
95  /// </summary>
96  /// <param name="security">security object</param>
97  public void Add(Security security)
98  {
99  Add(security.Symbol, security);
100  }
101 
102  /// <summary>
103  /// Add a symbol-security by its key value pair.
104  /// </summary>
105  /// <remarks>IDictionary implementation</remarks>
106  /// <param name="pair"></param>
107  public void Add(KeyValuePair<Symbol, Security> pair)
108  {
109  Add(pair.Key, pair.Value);
110  }
111 
112  /// <summary>
113  /// Clear the securities array to delete all the portfolio and asset information.
114  /// </summary>
115  /// <remarks>IDictionary implementation</remarks>
116  public override void Clear()
117  {
118  lock (_securityManager)
119  {
120  _enumerator = null;
121  _enumeratorKeys = null;
122  _enumeratorValues = null;
123  _securityManager.Clear();
124  _completeSecuritiesCollection.Clear();
125  }
126  }
127 
128  /// <summary>
129  /// Check if this collection contains this key value pair.
130  /// </summary>
131  /// <param name="pair">Search key-value pair</param>
132  /// <remarks>IDictionary implementation</remarks>
133  /// <returns>Bool true if contains this key-value pair</returns>
134  public bool Contains(KeyValuePair<Symbol, Security> pair)
135  {
136  lock (_securityManager)
137  {
138  return _completeSecuritiesCollection.Contains(pair);
139  }
140  }
141 
142  /// <summary>
143  /// Check if this collection contains this symbol.
144  /// </summary>
145  /// <param name="symbol">Symbol we're checking for.</param>
146  /// <remarks>IDictionary implementation</remarks>
147  /// <returns>Bool true if contains this symbol pair</returns>
148  public bool ContainsKey(Symbol symbol)
149  {
150  lock (_securityManager)
151  {
152  return _completeSecuritiesCollection.ContainsKey(symbol);
153  }
154  }
155 
156  /// <summary>
157  /// Copy from the internal array to an external array.
158  /// </summary>
159  /// <param name="array">Array we're outputting to</param>
160  /// <param name="number">Starting index of array</param>
161  /// <remarks>IDictionary implementation</remarks>
162  public void CopyTo(KeyValuePair<Symbol, Security>[] array, int number)
163  {
164  lock (_securityManager)
165  {
166  ((IDictionary<Symbol, Security>)_securityManager).CopyTo(array, number);
167  }
168  }
169 
170  /// <summary>
171  /// Count of the number of securities in the collection.
172  /// </summary>
173  /// <remarks>IDictionary implementation</remarks>
174  public int Count
175  {
176  get
177  {
178  lock (_securityManager)
179  {
180  return _securityManager.Count;
181  }
182  }
183  }
184 
185  /// <summary>
186  /// Flag indicating if the internal array is read only.
187  /// </summary>
188  /// <remarks>IDictionary implementation</remarks>
189  public override bool IsReadOnly
190  {
191  get { return false; }
192  }
193 
194  /// <summary>
195  /// Remove a key value of of symbol-securities from the collections.
196  /// </summary>
197  /// <remarks>IDictionary implementation</remarks>
198  /// <param name="pair">Key Value pair of symbol-security to remove</param>
199  /// <returns>Boolean true on success</returns>
200  public bool Remove(KeyValuePair<Symbol, Security> pair)
201  {
202  return Remove(pair.Key);
203  }
204 
205  /// <summary>
206  /// Remove this symbol security: Dictionary interface implementation.
207  /// </summary>
208  /// <param name="symbol">Symbol we're searching for</param>
209  /// <returns>true success</returns>
210  public override bool Remove(Symbol symbol)
211  {
212  Security security;
213  lock (_securityManager)
214  {
215  _securityManager.Remove(symbol, out security);
216  }
217 
218  if (security != null)
219  {
220  OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, security));
221  return true;
222  }
223  return false;
224  }
225 
226  /// <summary>
227  /// List of the symbol-keys in the collection of securities.
228  /// </summary>
229  /// <remarks>Excludes non active or delisted securities</remarks>
230  public ICollection<Symbol> Keys
231  {
232  get
233  {
234  var result = _enumeratorKeys;
235  if (result == null)
236  {
237  lock (_securityManager)
238  {
239  _enumeratorKeys = result = _securityManager.Keys.ToList();
240  }
241  }
242  return result;
243  }
244  }
245 
246  /// <summary>
247  /// Try and get this security object with matching symbol and return true on success.
248  /// </summary>
249  /// <param name="symbol">String search symbol</param>
250  /// <param name="security">Output Security object</param>
251  /// <remarks>IDictionary implementation</remarks>
252  /// <returns>True on successfully locating the security object</returns>
253  public override bool TryGetValue(Symbol symbol, out Security security)
254  {
255  lock (_securityManager)
256  {
257  return _completeSecuritiesCollection.TryGetValue(symbol, out security);
258  }
259  }
260 
261  /// <summary>
262  /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the Symbol objects of the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
263  /// </summary>
264  /// <remarks>Excludes non active or delisted securities</remarks>
265  /// <returns>
266  /// An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the Symbol objects of the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>.
267  /// </returns>
268  protected override IEnumerable<Symbol> GetKeys => Keys;
269 
270  /// <summary>
271  /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
272  /// </summary>
273  /// <remarks>Excludes non active or delisted securities</remarks>
274  /// <returns>
275  /// An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>.
276  /// </returns>
277  protected override IEnumerable<Security> GetValues => Values;
278 
279  /// <summary>
280  /// Get a list of the security objects for this collection.
281  /// </summary>
282  /// <remarks>Excludes non active or delisted securities</remarks>
283  public ICollection<Security> Values
284  {
285  get
286  {
287  var result = _enumeratorValues;
288  if (result == null)
289  {
290  lock (_securityManager)
291  {
292  _enumeratorValues = result = _securityManager.Values.ToList();
293  }
294  }
295  return result;
296  }
297  }
298 
299  /// <summary>
300  /// Get a list of the complete security objects for this collection, including non active or delisted securities
301  /// </summary>
302  public ICollection<Security> Total
303  {
304  get
305  {
306  ICollection<Security> result;
307  lock (_securityManager)
308  {
309  result = _completeSecuritiesCollection.Values.ToList();
310  }
311  return result;
312  }
313  }
314 
315  /// <summary>
316  /// Get the enumerator for this security collection.
317  /// </summary>
318  /// <remarks>IDictionary implementation</remarks>
319  /// <returns>Enumerable key value pair</returns>
320  IEnumerator<KeyValuePair<Symbol, Security>> IEnumerable<KeyValuePair<Symbol, Security>>.GetEnumerator()
321  {
322  return GetEnumeratorImplementation();
323  }
324 
325  /// <summary>
326  /// Get the enumerator for this securities collection.
327  /// </summary>
328  /// <remarks>IDictionary implementation</remarks>
329  /// <returns>Enumerator.</returns>
330  IEnumerator IEnumerable.GetEnumerator()
331  {
332  return GetEnumeratorImplementation();
333  }
334 
335  private List<KeyValuePair<Symbol, Security>>.Enumerator GetEnumeratorImplementation()
336  {
337  var result = _enumerator;
338  if (result == null)
339  {
340  lock (_securityManager)
341  {
342  _enumerator = result = _securityManager.ToList();
343  }
344  }
345  return result.GetEnumerator();
346  }
347 
348  /// <summary>
349  /// Indexer method for the security manager to access the securities objects by their symbol.
350  /// </summary>
351  /// <remarks>IDictionary implementation</remarks>
352  /// <param name="symbol">Symbol object indexer</param>
353  /// <returns>Security</returns>
354  public override Security this[Symbol symbol]
355  {
356  get
357  {
358  Security security;
359  lock (_securityManager)
360  {
361  if (!_completeSecuritiesCollection.TryGetValue(symbol, out security))
362  {
363  throw new KeyNotFoundException(Messages.SecurityManager.SymbolNotFoundInSecurities(symbol));
364  }
365  }
366  return security;
367  }
368  set
369  {
370  Security existing;
371  lock (_securityManager)
372  {
373  if (_securityManager.TryGetValue(symbol, out existing) && existing != value)
374  {
375  throw new ArgumentException(Messages.SecurityManager.UnableToOverwriteSecurity(symbol));
376  }
377  }
378 
379  // no security exists for the specified symbol key, add it now
380  if (existing == null)
381  {
382  Add(symbol, value);
383  }
384  }
385  }
386 
387  /// <summary>
388  /// Event invocator for the <see cref="CollectionChanged"/> event
389  /// </summary>
390  /// <param name="changedEventArgs">Event arguments for the <see cref="CollectionChanged"/> event</param>
391  protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs changedEventArgs)
392  {
393  _enumerator = null;
394  _enumeratorKeys = null;
395  _enumeratorValues = null;
396  CollectionChanged?.Invoke(this, changedEventArgs);
397  }
398 
399  /// <summary>
400  /// Sets the Security Service to be used
401  /// </summary>
402  public void SetSecurityService(SecurityService securityService)
403  {
404  _securityService = securityService;
405  }
406 
407  /// <summary>
408  /// Creates a new security
409  /// </summary>
410  /// <remarks>Following the obsoletion of Security.Subscriptions,
411  /// both overloads will be merged removing <see cref="SubscriptionDataConfig"/> arguments</remarks>
413  Symbol symbol,
414  List<SubscriptionDataConfig> subscriptionDataConfigList,
415  decimal leverage = 0,
416  bool addToSymbolCache = true,
417  Security underlying = null)
418  {
419  return _securityService.CreateSecurity(symbol, subscriptionDataConfigList, leverage, addToSymbolCache, underlying);
420  }
421 
422 
423  /// <summary>
424  /// Creates a new security
425  /// </summary>
426  /// <remarks>Following the obsoletion of Security.Subscriptions,
427  /// both overloads will be merged removing <see cref="SubscriptionDataConfig"/> arguments</remarks>
429  Symbol symbol,
430  SubscriptionDataConfig subscriptionDataConfig,
431  decimal leverage = 0,
432  bool addToSymbolCache = true,
433  Security underlying = null
434  )
435  {
436  return _securityService.CreateSecurity(symbol, subscriptionDataConfig, leverage, addToSymbolCache, underlying);
437  }
438 
439  /// <summary>
440  /// Set live mode state of the algorithm
441  /// </summary>
442  /// <param name="isLiveMode">True, live mode is enabled</param>
443  public void SetLiveMode(bool isLiveMode)
444  {
445  _securityService.SetLiveMode(isLiveMode);
446  }
447  }
448 }