Lean  $LEAN_TAG$
ETFConstituentUniverse.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.Generic;
18 using System.Globalization;
19 using System.IO;
20 using NodaTime;
21 using QuantConnect.Util;
22 
24 {
25  [Obsolete("'ETFConstituentData' was renamed to 'ETFConstituentUniverse'")]
27 
28  /// <summary>
29  /// ETF constituent data
30  /// </summary>
32  {
33  /// <summary>
34  /// Time of the previous ETF constituent data update
35  /// </summary>
36  public DateTime? LastUpdate { get; set; }
37 
38  /// <summary>
39  /// The percentage of the ETF allocated to this constituent
40  /// </summary>
41  public decimal? Weight { get; set; }
42 
43  /// <summary>
44  /// Number of shares held in the ETF
45  /// </summary>
46  public decimal? SharesHeld { get; set; }
47 
48  /// <summary>
49  /// Market value of the current asset held in U.S. dollars
50  /// </summary>
51  public decimal? MarketValue { get; set; }
52 
53  /// <summary>
54  /// Period of the data
55  /// </summary>
56  public TimeSpan Period { get; set; } = TimeSpan.FromDays(1);
57 
58  /// <summary>
59  /// Time that the data became available to use
60  /// </summary>
61  public override DateTime EndTime
62  {
63  get { return Time + Period; }
64  set { Time = value - Period; }
65  }
66 
67  /// <summary>
68  /// Return the URL string source of the file. This will be converted to a stream
69  /// </summary>
70  /// <param name="config">Configuration object</param>
71  /// <param name="date">Date of this source file</param>
72  /// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
73  /// <returns>String URL of source file.</returns>
74  public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
75  {
76  return new SubscriptionDataSource(
77  Path.Combine(
79  config.SecurityType.SecurityTypeToLower(),
80  config.Market,
81  "universes",
82  "etf",
83  config.Symbol.Underlying.Value.ToLowerInvariant(),
84  $"{date:yyyyMMdd}.csv"),
86  FileFormat.FoldingCollection);
87  }
88 
89  /// <summary>
90  /// 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
91  /// each time it is called.
92  /// </summary>
93  /// <param name="config">Subscription data config setup object</param>
94  /// <param name="line">Line of the source document</param>
95  /// <param name="date">Date of the requested data</param>
96  /// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
97  /// <returns>Instance of the T:BaseData object generated by this line of the CSV</returns>
98  public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
99  {
100  if (string.IsNullOrEmpty(line))
101  {
102  return null;
103  }
104 
105  var split = line.Split(',');
106 
107  var symbol = new Symbol(SecurityIdentifier.Parse(split[1]), split[0]);
108  var lastUpdateDate = Parse.TryParseExact(split[2], "yyyyMMdd", DateTimeStyles.None, out var lastUpdateDateParsed)
109  ? lastUpdateDateParsed
110  : (DateTime?)null;
111  var weighting = split[3].IsNullOrEmpty()
112  ? (decimal?)null
113  : Parse.Decimal(split[3], NumberStyles.Any);
114  var sharesHeld = split[4].IsNullOrEmpty()
115  ? (decimal?)null
116  : Parse.Decimal(split[4], NumberStyles.Any);
117  var marketValue = split[5].IsNullOrEmpty()
118  ? (decimal?)null
119  : Parse.Decimal(split[5], NumberStyles.Any);
120 
121  return new ETFConstituentUniverse
122  {
123  LastUpdate = lastUpdateDate,
124  Weight = weighting,
125  SharesHeld = sharesHeld,
126  MarketValue = marketValue,
127 
128  Symbol = symbol,
129  Time = date
130  };
131  }
132 
133  /// <summary>
134  /// Indicates if there is support for mapping
135  /// </summary>
136  /// <returns>True indicates mapping should be used</returns>
137  public override bool RequiresMapping()
138  {
139  return true;
140  }
141 
142  /// <summary>
143  /// Creates a copy of the instance
144  /// </summary>
145  /// <returns>Clone of the instance</returns>
146  public override BaseData Clone()
147  {
148  return new ETFConstituentUniverse
149  {
151  Weight = Weight,
154 
155  Symbol = Symbol,
156  Time = Time,
157  Data = Data
158  };
159  }
160 
161  /// <summary>
162  /// Indicates that the data set is expected to be sparse
163  /// </summary>
164  /// <remarks>Relies on the <see cref="Symbol"/> property value</remarks>
165  /// <remarks>This is a method and not a property so that python
166  /// custom data types can override it</remarks>
167  /// <returns>True if the data set represented by this type is expected to be sparse</returns>
168  public override bool IsSparseData()
169  {
170  return true;
171  }
172 
173  /// <summary>
174  /// Gets the default resolution for this data and security type
175  /// </summary>
176  /// <remarks>
177  /// This is a method and not a property so that python
178  /// custom data types can override it.
179  /// </remarks>
180  public override Resolution DefaultResolution()
181  {
182  return Resolution.Daily;
183  }
184 
185  /// <summary>
186  /// Gets the supported resolution for this data and security type
187  /// </summary>
188  /// <remarks>Relies on the <see cref="Symbol"/> property value</remarks>
189  /// <remarks>This is a method and not a property so that python
190  /// custom data types can override it</remarks>
191  public override List<Resolution> SupportedResolutions()
192  {
193  return DailyResolution;
194  }
195 
196  /// <summary>
197  /// Specifies the data time zone for this data type. This is useful for custom data types
198  /// </summary>
199  /// <remarks>Will throw <see cref="InvalidOperationException"/> for security types
200  /// other than <see cref="SecurityType.Base"/></remarks>
201  /// <returns>The <see cref="DateTimeZone"/> of this data type</returns>
202  public override DateTimeZone DataTimeZone()
203  {
204  return TimeZones.Utc;
205  }
206  }
207 }