/* * 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 System.Collections; using System.Collections.Generic; using QuantConnect.Python; namespace QuantConnect.Data.UniverseSelection { /// /// This type exists for transport of data as a single packet /// public class BaseDataCollection : BaseData, IEnumerable { private DateTime _endTime; /// /// The associated underlying price data if any /// [PandasNonExpandable] public BaseData Underlying { get; set; } /// /// Gets or sets the contracts selected by the universe /// [PandasIgnore] public HashSet FilteredContracts { get; set; } /// /// Gets the data list /// public List Data { get; set; } /// /// Gets or sets the end time of this data /// [PandasIgnore] public override DateTime EndTime { get { if (_endTime == default) { // to be user friendly let's return Time if not set, like BaseData does return Time; } return _endTime; } set { _endTime = value; } } /// /// Initializes a new default instance of the c;ass /// public BaseDataCollection() : this(DateTime.MinValue, Symbol.Empty) { } /// /// Initializes a new instance of the class /// /// The time of this data /// A common identifier for all data in this packet /// The data to add to this collection public BaseDataCollection(DateTime time, Symbol symbol, IEnumerable data = null) : this(time, time, symbol, data) { } /// /// Initializes a new instance of the class /// /// The start time of this data /// The end time of this data /// A common identifier for all data in this packet /// The data to add to this collection /// The associated underlying price data if any /// The contracts selected by the universe public BaseDataCollection(DateTime time, DateTime endTime, Symbol symbol, IEnumerable data = null, BaseData underlying = null, HashSet filteredContracts = null) : this(time, endTime, symbol, data != null ? data.ToList() : new List(), underlying, filteredContracts) { } /// /// Initializes a new instance of the class /// /// The start time of this data /// The end time of this data /// A common identifier for all data in this packet /// The data to add to this collection /// The associated underlying price data if any /// The contracts selected by the universe public BaseDataCollection(DateTime time, DateTime endTime, Symbol symbol, List data, BaseData underlying, HashSet filteredContracts) : this(time, endTime, symbol, underlying, filteredContracts) { if (data != null && data.Count == 1 && data[0] is BaseDataCollection collection && collection.Data != null && collection.Data.Count > 0) { // we were given a base data collection, let's be nice and fetch it's data if it has any Data = collection.Data; } else { Data = data ?? new List(); } } /// /// Helper method to create an instance without setting the data list /// protected BaseDataCollection(DateTime time, DateTime endTime, Symbol symbol, BaseData underlying, HashSet filteredContracts) { Symbol = symbol; Time = time; _endTime = endTime; Underlying = underlying; FilteredContracts = filteredContracts; } /// /// Copy constructor for /// /// The base data collection being copied public BaseDataCollection(BaseDataCollection other) : this(other.Time, other.EndTime, other.Symbol, other.Underlying, other.FilteredContracts) { Data = other.Data; } /// /// Creates the universe symbol for the target market /// /// The universe symbol to use public virtual Symbol UniverseSymbol(string market = null) { market ??= QuantConnect.Market.USA; var ticker = $"{GetType().Name}-{market}-{Guid.NewGuid()}"; return Symbol.Create(ticker, SecurityType.Base, market, baseDataType: GetType()); } /// /// Indicates whether this contains data that should be stored in the security cache /// /// Whether this contains data that should be stored in the security cache public override bool ShouldCacheToSecurity() { if (Data == null || Data.Count == 0) { return true; } // if we hold the same data type we are, else we ask underlying type return Data[0].GetType() == GetType() || Data[0].ShouldCacheToSecurity(); } /// /// Adds a new data point to this collection /// /// The new data point to add public virtual void Add(BaseData newDataPoint) { Data.Add(newDataPoint); } /// /// Adds a new data points to this collection /// /// The new data points to add public virtual void AddRange(IEnumerable newDataPoints) { Data.AddRange(newDataPoints); } /// /// Return a new instance clone of this object, used in fill forward /// /// /// This base implementation uses reflection to copy all public fields and properties /// /// A clone of the current object public override BaseData Clone() { return new BaseDataCollection(this); } /// /// Returns an IEnumerator for this enumerable Object. The enumerator provides /// a simple way to access all the contents of a collection. /// public IEnumerator GetEnumerator() { return (Data ?? Enumerable.Empty()).GetEnumerator(); } /// /// Returns an IEnumerator for this enumerable Object. The enumerator provides /// a simple way to access all the contents of a collection. /// IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }