/* * 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 Common.Util; using QuantConnect.Python; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; namespace QuantConnect.Data.Market { /// /// Provides a base class for types holding base data instances keyed by symbol /// [PandasNonExpandable] public class DataDictionary : BaseExtendedDictionary { /// /// Used to cache the sorted items in the dictionary. /// We do this instead of using a SortedDictionary to keep the O(1) access time. /// private List> _items; private List _keys; private List _values; /// /// Gets or sets the time associated with this collection of data /// public DateTime Time { get; set; } /// /// Initializes a new instance of the class. /// public DataDictionary() : base() { } /// /// Initializes a new instance of the class /// using the specified as a data source /// /// The data source for this data dictionary /// Delegate used to select a key from the value public DataDictionary(IEnumerable data, Func keySelector) : base(data, keySelector) { } /// /// Initializes a new instance of the class. /// /// The time this data was emitted. public DataDictionary(DateTime time) : base() { Time = time; } /// /// Gets or sets the element with the specified key. /// public override T this[Symbol symbol] { get { T data; if (TryGetValue(symbol, out data)) { return data; } CheckForImplicitlyCreatedSymbol(symbol); 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}\")"); } set { _items = null; base[symbol] = value; } } /// /// Gets the value associated with the specified key. /// public virtual T GetValue(Symbol key) { T value; TryGetValue(key, out value); return value; } /// /// Gets all the items in the dictionary /// /// All the items in the dictionary public override IEnumerable> GetItems() { if (_items == null) { _items = base.GetItems().OrderBy(x => x.Key).ToList(); } return _items; } /// /// Gets a collection containing the keys of the dictionary /// public override ICollection Keys { get { if (_keys == null) { _keys = (_items == null ? base.Keys.OrderBy(x => x) : _items.Select(x => x.Key)).ToList(); } return _keys; } } /// /// Gets a collection containing the values of the dictionary /// public override ICollection Values { get { if (_values == null) { var items = _items == null ? base.GetItems().OrderBy(x => x.Key) : (IEnumerable>)_items; _values = items.Select(x => x.Value).ToList(); } return _values; } } /// /// Gets a collection containing the keys in the dictionary /// protected override IEnumerable GetKeys => Keys; /// /// Gets a collection containing the values in the dictionary /// protected override IEnumerable GetValues => Values; /// /// Returns an enumerator that iterates through the dictionary /// /// An enumerator for the dictionary public override IEnumerator> GetEnumerator() { return GetItems().GetEnumerator(); } /// /// Removes all items from the dictionary /// public override void Clear() { ClearCache(); base.Clear(); } /// /// Removes the value with the specified key /// /// The key of the element to remove /// true if the element was successfully found and removed; otherwise, false public override bool Remove(Symbol key) { ClearCache(); return base.Remove(key); } /// /// Removes the first occurrence of a specific object from the dictionary /// /// The key-value pair to remove /// true if the key-value pair was successfully removed; otherwise, false public override bool Remove(KeyValuePair item) { ClearCache(); return base.Remove(item); } /// /// Adds an element with the provided key and value to the dictionary /// /// The key of the element to add /// The value of the element to add public override void Add(Symbol key, T value) { ClearCache(); base.Add(key, value); } /// /// Adds an element with the provided key-value pair to the dictionary /// /// The key-value pair to add public override void Add(KeyValuePair item) { ClearCache(); base.Add(item); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ClearCache() { _items = null; _keys = null; _values = null; } } /// /// Provides extension methods for the DataDictionary class /// public static class DataDictionaryExtensions { /// /// Provides a convenience method for adding a base data instance to our data dictionary /// public static void Add(this DataDictionary dictionary, T data) where T : BaseData { dictionary.Add(data.Symbol, data); } } }