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