Lean  $LEAN_TAG$
BaseDataDownloadConfig.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 
17 using System.Globalization;
18 using QuantConnect.Logging;
22 
24 
25 /// <summary>
26 /// Abstract base class for configuring data download parameters, including common properties and initialization logic.
27 /// </summary>
28 public abstract class BaseDataDownloadConfig
29 {
30  /// <summary>
31  /// Gets the start date for the data download.
32  /// </summary>
33  public DateTime StartDate { get; set; }
34 
35  /// <summary>
36  /// Gets the end date for the data download.
37  /// </summary>
38  public DateTime EndDate { get; set; }
39 
40  /// <summary>
41  /// Gets or sets the resolution of the downloaded data.
42  /// </summary>
43  public Resolution Resolution { get; protected set; }
44 
45  /// <summary>
46  /// Gets or sets the market name for which the data will be downloaded.
47  /// </summary>
48  public string MarketName { get; protected set; }
49 
50  /// <summary>
51  /// Gets the type of security for which the data is being downloaded.
52  /// </summary>
53  public SecurityType SecurityType { get; set; }
54 
55  /// <summary>
56  /// Gets or sets the type of tick data to be downloaded.
57  /// </summary>
58  public TickType TickType { get; protected set; }
59 
60  /// <summary>
61  /// The type of data based on <see cref="TickTypes"/>
62  /// </summary>
63  public abstract Type DataType { get; }
64 
65  /// <summary>
66  /// Gets the list of symbols for which the data will be downloaded.
67  /// </summary>
68  public IReadOnlyCollection<Symbol> Symbols { get; protected set; } = [];
69 
70  /// <summary>
71  /// Initializes a new instance of the <see cref="BaseDataDownloadConfig"/> class.
72  /// </summary>
74  {
75  StartDate = ParseDate(Config.Get(DownloaderCommandArguments.CommandStartDate).ToString());
76  EndDate = ParseDate(Config.Get(DownloaderCommandArguments.CommandEndDate).ToString());
77 
78  SecurityType = ParseEnum<SecurityType>(Config.Get(DownloaderCommandArguments.CommandSecurityType).ToString());
79 
80  MarketName = Config.Get(DownloaderCommandArguments.CommandMarketName).ToString().ToLower(CultureInfo.InvariantCulture);
81 
82  if (string.IsNullOrEmpty(MarketName))
83  {
85  Log.Trace($"{nameof(BaseDataDownloadConfig)}: Default market '{MarketName}' applied for SecurityType '{SecurityType}'");
86  }
87 
88  if (!Market.SupportedMarkets().Contains(MarketName))
89  {
90  throw new ArgumentException($"The specified market '{MarketName}' is not supported. Supported markets are: {string.Join(", ", Market.SupportedMarkets())}.");
91  }
92 
93  Symbols = LoadSymbols(Config.GetValue<Dictionary<string, string>>(DownloaderCommandArguments.CommandTickers), SecurityType, MarketName);
94  }
95 
96  /// <summary>
97  /// Initializes a new instance of the <see cref="DataDownloadConfig"/> class with the specified parameters.
98  /// </summary>
99  /// <param name="tickType">The type of tick data to be downloaded.</param>
100  /// <param name="securityType">The type of security for which data is being downloaded.</param>
101  /// <param name="resolution">The resolution of the data being downloaded.</param>
102  /// <param name="startDate">The start date for the data download range.</param>
103  /// <param name="endDate">The end date for the data download range.</param>
104  /// <param name="marketName">The name of the market from which the data is being downloaded.</param>
105  /// <param name="symbols">A list of symbols for which data is being downloaded.</param>
106  protected BaseDataDownloadConfig(TickType tickType, SecurityType securityType, Resolution resolution, DateTime startDate, DateTime endDate, string marketName, List<Symbol> symbols)
107  {
108  StartDate = startDate;
109  EndDate = endDate;
110  Resolution = resolution;
111  MarketName = marketName;
112  SecurityType = securityType;
113  TickType = tickType;
114  Symbols = symbols;
115  }
116 
117  /// <summary>
118  /// Loads the symbols for which data will be downloaded.
119  /// </summary>
120  /// <param name="tickers">A dictionary of tickers to load symbols for.</param>
121  /// <param name="securityType">The type of security to download data for.</param>
122  /// <param name="market">The market for which the symbols are valid.</param>
123  /// <returns>A collection of symbols for the specified market and security type.</returns>
124  /// <summary>
125  private static IReadOnlyCollection<Symbol> LoadSymbols(Dictionary<string, string> tickers, SecurityType securityType, string market)
126  {
127  if (tickers == null || tickers.Count == 0)
128  {
129  throw new ArgumentException($"{nameof(BaseDataDownloadConfig)}.{nameof(LoadSymbols)}: The tickers dictionary cannot be null or empty.");
130  }
131 
132  return tickers.Keys.Select(ticker => Symbol.Create(ticker, securityType, market)).ToList();
133  }
134 
135  /// <summary>
136  /// Parses a string to a <see cref="DateTime"/> using a specific date format.
137  /// </summary>
138  /// <param name="date">The date string to parse.</param>
139  /// <returns>The parsed <see cref="DateTime"/> value.</returns>
140  protected static DateTime ParseDate(string date) => DateTime.ParseExact(date, DateFormat.EightCharacter, CultureInfo.InvariantCulture);
141 
142 
143  /// <summary>
144  /// Parses a string value into an enum of the specified type.
145  /// </summary>
146  /// <typeparam name="TEnum">The enum type to parse the value into.</typeparam>
147  /// <param name="value">The string value to parse.</param>
148  /// <returns>The parsed enum value.</returns>
149  /// <exception cref="ArgumentException">Thrown if the value cannot be parsed or is not a valid enum value.</exception>
150  protected static TEnum ParseEnum<TEnum>(string value) where TEnum : struct, Enum
151  {
152  if (!Enum.TryParse(value, true, out TEnum result) || !Enum.IsDefined(result))
153  {
154  throw new ArgumentException($"Invalid {typeof(TEnum).Name} specified: '{value}'. Please provide a valid {typeof(TEnum).Name}. " +
155  $"Valid values are: {string.Join(", ", Enum.GetNames<TEnum>())}.");
156  }
157  return result;
158  }
159 }