Lean  $LEAN_TAG$
DataDictionary.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 QuantConnect.Python;
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 
22 {
23  /// <summary>
24  /// Provides a base class for types holding base data instances keyed by symbol
25  /// </summary>
26  [PandasNonExpandable]
27  public class DataDictionary<T> : ExtendedDictionary<T>, IDictionary<Symbol, T>
28  {
29  // storage for the data
30  private readonly IDictionary<Symbol, T> _data = new Dictionary<Symbol, T>();
31 
32  /// <summary>
33  /// Initializes a new instance of the <see cref="QuantConnect.Data.Market.DataDictionary{T}"/> class.
34  /// </summary>
35  public DataDictionary()
36  {
37  }
38 
39  /// <summary>
40  /// Initializes a new instance of the <see cref="QuantConnect.Data.Market.DataDictionary{T}"/> class
41  /// using the specified <paramref name="data"/> as a data source
42  /// </summary>
43  /// <param name="data">The data source for this data dictionary</param>
44  /// <param name="keySelector">Delegate used to select a key from the value</param>
45  public DataDictionary(IEnumerable<T> data, Func<T, Symbol> keySelector)
46  {
47  foreach (var datum in data)
48  {
49  this[keySelector(datum)] = datum;
50  }
51  }
52 
53  /// <summary>
54  /// Initializes a new instance of the <see cref="QuantConnect.Data.Market.DataDictionary{T}"/> class.
55  /// </summary>
56  /// <param name="time">The time this data was emitted.</param>
57  public DataDictionary(DateTime time)
58  {
59 #pragma warning disable 618 // This assignment is left here until the Time property is removed.
60  Time = time;
61 #pragma warning restore 618
62  }
63 
64  /// <summary>
65  /// Gets or sets the time associated with this collection of data
66  /// </summary>
67  public DateTime Time { get; set; }
68 
69  /// <summary>
70  /// Returns an enumerator that iterates through the collection.
71  /// </summary>
72  /// <returns>
73  /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
74  /// </returns>
75  /// <filterpriority>1</filterpriority>
76  public IEnumerator<KeyValuePair<Symbol, T>> GetEnumerator()
77  {
78  return _data.GetEnumerator();
79  }
80  /// <summary>
81  /// Returns an enumerator that iterates through a collection.
82  /// </summary>
83  /// <returns>
84  /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
85  /// </returns>
86  /// <filterpriority>2</filterpriority>
87  IEnumerator IEnumerable.GetEnumerator()
88  {
89  return ((IEnumerable)_data).GetEnumerator();
90  }
91 
92  /// <summary>
93  /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
94  /// </summary>
95  /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
96  public void Add(KeyValuePair<Symbol, T> item)
97  {
98  _data.Add(item);
99  }
100 
101  /// <summary>
102  /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
103  /// </summary>
104  /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
105  public override void Clear()
106  {
107  _data.Clear();
108  }
109 
110  /// <summary>
111  /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
112  /// </summary>
113  /// <returns>
114  /// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
115  /// </returns>
116  /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
117  public bool Contains(KeyValuePair<Symbol, T> item)
118  {
119  return _data.Contains(item);
120  }
121 
122  /// <summary>
123  /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
124  /// </summary>
125  /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException">The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.</exception>
126  public void CopyTo(KeyValuePair<Symbol, T>[] array, int arrayIndex)
127  {
128  _data.CopyTo(array, arrayIndex);
129  }
130 
131  /// <summary>
132  /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
133  /// </summary>
134  /// <returns>
135  /// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
136  /// </returns>
137  /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
138  public bool Remove(KeyValuePair<Symbol, T> item)
139  {
140  return _data.Remove(item);
141  }
142 
143  /// <summary>
144  /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
145  /// </summary>
146  /// <returns>
147  /// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
148  /// </returns>
149  public int Count
150  {
151  get { return _data.Count; }
152  }
153 
154  /// <summary>
155  /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
156  /// </summary>
157  /// <returns>
158  /// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
159  /// </returns>
160  public override bool IsReadOnly
161  {
162  get { return _data.IsReadOnly; }
163  }
164 
165  /// <summary>
166  /// Determines whether the <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> contains an element with the specified key.
167  /// </summary>
168  /// <returns>
169  /// true if the <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> contains an element with the key; otherwise, false.
170  /// </returns>
171  /// <param name="key">The key to locate in the <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>.</param><exception cref="System.ArgumentNullException"><paramref name="key"/> is null.</exception>
172  public bool ContainsKey(Symbol key)
173  {
174  return _data.ContainsKey(key);
175  }
176 
177  /// <summary>
178  /// Adds an element with the provided key and value to the <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>.
179  /// </summary>
180  /// <param name="key">The object to use as the key of the element to add.</param><param name="value">The object to use as the value of the element to add.</param><exception cref="System.ArgumentNullException"><paramref name="key"/> is null.</exception><exception cref="T:System.ArgumentException">An element with the same key already exists in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.</exception><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only.</exception>
181  public void Add(Symbol key, T value)
182  {
183  _data.Add(key, value);
184  }
185 
186  /// <summary>
187  /// Removes the element with the specified key from the <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>.
188  /// </summary>
189  /// <returns>
190  /// true if the element is successfully removed; otherwise, false. This method also returns false if <paramref name="key"/> was not found in the original <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/>.
191  /// </returns>
192  /// <param name="key">The key of the element to remove.</param><exception cref="System.ArgumentNullException"><paramref name="key"/> is null.</exception><exception cref="System.NotSupportedException">The <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> is read-only.</exception>
193  public override bool Remove(Symbol key)
194  {
195  return _data.Remove(key);
196  }
197 
198  /// <summary>
199  /// Gets the value associated with the specified key.
200  /// </summary>
201  /// <returns>
202  /// true if the object that implements <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> contains an element with the specified key; otherwise, false.
203  /// </returns>
204  /// <param name="key">The key whose value to get.</param><param name="value">When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.</param><exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null.</exception>
205  public override bool TryGetValue(Symbol key, out T value)
206  {
207  return _data.TryGetValue(key, out value);
208  }
209 
210  /// <summary>
211  /// Gets or sets the element with the specified key.
212  /// </summary>
213  /// <returns>
214  /// The element with the specified key.
215  /// </returns>
216  /// <param name="symbol">The key of the element to get or set.</param>
217  /// <exception cref="System.ArgumentNullException"><paramref name="symbol"/> is null.</exception>
218  /// <exception cref="System.Collections.Generic.KeyNotFoundException">The property is retrieved and <paramref name="symbol"/> is not found.</exception>
219  /// <exception cref="System.NotSupportedException">The property is set and the <see cref="System.Collections.Generic.IDictionary{TKey, TValue}"/> is read-only.</exception>
220  public override T this[Symbol symbol]
221  {
222  get
223  {
224  T data;
225  if (TryGetValue(symbol, out data))
226  {
227  return data;
228  }
229  throw new KeyNotFoundException($"'{symbol}' wasn't found in the {GetType().GetBetterTypeName()} object, likely because there was no-data at this moment in time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with data.ContainsKey(\"{symbol}\")");
230  }
231  set
232  {
233  _data[symbol] = value;
234  }
235  }
236 
237  /// <summary>
238  /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
239  /// </summary>
240  /// <returns>
241  /// An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>.
242  /// </returns>
243  public ICollection<Symbol> Keys
244  {
245  get { return _data.Keys; }
246  }
247 
248  /// <summary>
249  /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
250  /// </summary>
251  /// <returns>
252  /// 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"/>.
253  /// </returns>
254  public ICollection<T> Values
255  {
256  get { return _data.Values; }
257  }
258 
259  /// <summary>
260  /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the Symbol objects of the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
261  /// </summary>
262  /// <returns>
263  /// 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"/>.
264  /// </returns>
265  protected override IEnumerable<Symbol> GetKeys => Keys;
266 
267  /// <summary>
268  /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
269  /// </summary>
270  /// <returns>
271  /// 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"/>.
272  /// </returns>
273  protected override IEnumerable<T> GetValues => Values;
274 
275  /// <summary>
276  /// Gets the value associated with the specified key.
277  /// </summary>
278  /// <param name="key">The key whose value to get.</param>
279  /// <returns>
280  /// The value associated with the specified key, if the key is found; otherwise, the default value for the type of the <typeparamref name="T"/> parameter.
281  /// </returns>
282  public virtual T GetValue(Symbol key)
283  {
284  T value;
285  TryGetValue(key, out value);
286  return value;
287  }
288  }
289 
290  /// <summary>
291  /// Provides extension methods for the DataDictionary class
292  /// </summary>
293  public static class DataDictionaryExtensions
294  {
295  /// <summary>
296  /// Provides a convenience method for adding a base data instance to our data dictionary
297  /// </summary>
298  public static void Add<T>(this DataDictionary<T> dictionary, T data)
299  where T : BaseData
300  {
301  dictionary.Add(data.Symbol, data);
302  }
303  }
304 }