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