/* * 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.Collections.Generic; using System.Globalization; using System.IO; using NodaTime; using QuantConnect.Util; namespace QuantConnect.Data.UniverseSelection { /// /// ETF Constituent data /// [Obsolete("'ETFConstituentData' was renamed to 'ETFConstituentUniverse'")] public class ETFConstituentData : ETFConstituentUniverse { } /// /// ETF constituent data /// public class ETFConstituentUniverse : BaseDataCollection { /// /// Time of the previous ETF constituent data update /// public DateTime? LastUpdate { get; set; } /// /// The percentage of the ETF allocated to this constituent /// public decimal? Weight { get; set; } /// /// Number of shares held in the ETF /// public decimal? SharesHeld { get; set; } /// /// Market value of the current asset held in U.S. dollars /// public decimal? MarketValue { get; set; } /// /// Period of the data /// public TimeSpan Period { get; set; } = TimeSpan.FromDays(1); /// /// Time that the data became available to use /// public override DateTime EndTime { get { return Time + Period; } set { Time = value - Period; } } /// /// Return the URL string source of the file. This will be converted to a stream /// /// Configuration object /// Date of this source file /// true if we're in live mode, false for backtesting mode /// String URL of source file. public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode) { return new SubscriptionDataSource( Path.Combine( Globals.DataFolder, config.SecurityType.SecurityTypeToLower(), config.Market, "universes", "etf", config.Symbol.Underlying.Value.ToLowerInvariant(), $"{date:yyyyMMdd}.csv"), SubscriptionTransportMedium.LocalFile, FileFormat.FoldingCollection); } /// /// Reader converts each line of the data source into BaseData objects. Each data type creates its own factory method, and returns a new instance of the object /// each time it is called. /// /// Subscription data config setup object /// Line of the source document /// Date of the requested data /// true if we're in live mode, false for backtesting mode /// Instance of the T:BaseData object generated by this line of the CSV public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode) { if (string.IsNullOrEmpty(line)) { return null; } var split = line.Split(','); var symbol = new Symbol(SecurityIdentifier.Parse(split[1]), split[0]); var lastUpdateDate = Parse.TryParseExact(split[2], "yyyyMMdd", DateTimeStyles.None, out var lastUpdateDateParsed) ? lastUpdateDateParsed : (DateTime?)null; var weighting = split[3].IsNullOrEmpty() ? (decimal?)null : Parse.Decimal(split[3], NumberStyles.Any); var sharesHeld = split[4].IsNullOrEmpty() ? (decimal?)null : Parse.Decimal(split[4], NumberStyles.Any); var marketValue = split[5].IsNullOrEmpty() ? (decimal?)null : Parse.Decimal(split[5], NumberStyles.Any); return new ETFConstituentUniverse { LastUpdate = lastUpdateDate, Weight = weighting, SharesHeld = sharesHeld, MarketValue = marketValue, Symbol = symbol, Time = date }; } /// /// Indicates if there is support for mapping /// /// True indicates mapping should be used public override bool RequiresMapping() { return true; } /// /// Creates a copy of the instance /// /// Clone of the instance public override BaseData Clone() { return new ETFConstituentUniverse { LastUpdate = LastUpdate, Weight = Weight, SharesHeld = SharesHeld, MarketValue = MarketValue, Symbol = Symbol, Time = Time, Data = Data }; } /// /// Indicates that the data set is expected to be sparse /// /// Relies on the property value /// This is a method and not a property so that python /// custom data types can override it /// True if the data set represented by this type is expected to be sparse public override bool IsSparseData() { return true; } /// /// Gets the default resolution for this data and security type /// /// /// This is a method and not a property so that python /// custom data types can override it. /// public override Resolution DefaultResolution() { return Resolution.Daily; } /// /// Gets the supported resolution for this data and security type /// /// Relies on the property value /// This is a method and not a property so that python /// custom data types can override it public override List SupportedResolutions() { return DailyResolution; } /// /// Specifies the data time zone for this data type. This is useful for custom data types /// /// Will throw for security types /// other than /// The of this data type public override DateTimeZone DataTimeZone() { return TimeZones.Utc; } } }