Lean  $LEAN_TAG$
SubscriptionDataSource.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.Linq;
18 using System.Collections.Generic;
19 using static QuantConnect.StringExtensions;
20 
21 namespace QuantConnect.Data
22 {
23  /// <summary>
24  /// Represents the source location and transport medium for a subscription
25  /// </summary>
26  public class SubscriptionDataSource : IEquatable<SubscriptionDataSource>
27  {
28  private readonly static IReadOnlyList<KeyValuePair<string, string>> _empty = new List<KeyValuePair<string, string>>();
29 
30  /// <summary>
31  /// Specifies whether the data source should be sorted.
32  /// <c>If False</c>, data will be returned in the original order, <c>else</c> it will be ordered by time.
33  /// </summary>
34  public bool Sort { get; set; }
35 
36  /// <summary>
37  /// Identifies where to get the subscription's data from
38  /// </summary>
39  public string Source { get; init; }
40 
41  /// <summary>
42  /// Identifies the format of the data within the source
43  /// </summary>
44  public FileFormat Format { get; init; }
45 
46  /// <summary>
47  /// Identifies the transport medium used to access the data, such as a local or remote file, or a polling rest API
48  /// </summary>
50 
51  /// <summary>
52  /// Gets the header values to be used in the web request.
53  /// </summary>
54  public IReadOnlyList<KeyValuePair<string, string>> Headers { get; init; }
55 
56  /// <summary>
57  /// Initializes a new instance of the <see cref="SubscriptionDataSource"/> class.
58  /// </summary>
59  /// <param name="source">The subscription's data source location</param>
60  public SubscriptionDataSource(string source)
61  : this(source, GetDefaultSubscriptionTransportMedium(source), FileFormat.Csv)
62  {
63  }
64 
65  /// <summary>
66  /// Initializes a new instance of the <see cref="SubscriptionDataSource"/> class.
67  /// </summary>
68  /// <param name="source">The subscription's data source location</param>
69  /// <param name="transportMedium">The transport medium to be used to retrieve the subscription's data from the source</param>
70  public SubscriptionDataSource(string source, SubscriptionTransportMedium transportMedium)
71  : this(source, transportMedium, FileFormat.Csv)
72  {
73  }
74 
75  /// <summary>
76  /// Initializes a new instance of the <see cref="SubscriptionDataSource"/> class.
77  /// </summary>
78  /// <param name="source">The subscription's data source location</param>
79  /// <param name="transportMedium">The transport medium to be used to retrieve the subscription's data from the source</param>
80  /// <param name="format">The format of the data within the source</param>
81  public SubscriptionDataSource(string source, SubscriptionTransportMedium transportMedium, FileFormat format)
82  : this(source, transportMedium, format, null)
83  {
84  }
85 
86  /// <summary>
87  /// Initializes a new instance of the <see cref="SubscriptionDataSource"/> class with <see cref="SubscriptionTransportMedium.Rest"/>
88  /// including the specified header values
89  /// </summary>
90  /// <param name="source">The subscription's data source location</param>
91  /// <param name="transportMedium">The transport medium to be used to retrieve the subscription's data from the source</param>
92  /// <param name="format">The format of the data within the source</param>
93  /// <param name="headers">The headers to be used for this source</param>
94  public SubscriptionDataSource(string source, SubscriptionTransportMedium transportMedium, FileFormat format, IEnumerable<KeyValuePair<string, string>> headers)
95  {
96  Source = source;
97  Format = format;
98  TransportMedium = transportMedium;
99  Headers = headers?.ToList() ?? _empty;
100  }
101 
102  /// <summary>
103  /// Indicates whether the current object is equal to another object of the same type.
104  /// </summary>
105  /// <returns>
106  /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
107  /// </returns>
108  /// <param name="other">An object to compare with this object.</param>
109  public bool Equals(SubscriptionDataSource other)
110  {
111  if (ReferenceEquals(null, other)) return false;
112  if (ReferenceEquals(this, other)) return true;
113  return string.Equals(Source, other.Source)
114  && TransportMedium == other.TransportMedium
115  && Headers.SequenceEqual(other.Headers);
116  }
117 
118  /// <summary>
119  /// Determines whether the specified instance is equal to the current instance.
120  /// </summary>
121  /// <returns>
122  /// true if the specified object is equal to the current object; otherwise, false.
123  /// </returns>
124  /// <param name="obj">The object to compare with the current object. </param><filterpriority>2</filterpriority>
125  public override bool Equals(object obj)
126  {
127  if (ReferenceEquals(null, obj)) return false;
128  if (ReferenceEquals(this, obj)) return true;
129  if (obj.GetType() != GetType()) return false;
130  return Equals((SubscriptionDataSource) obj);
131  }
132 
133  /// <summary>
134  /// Serves as a hash function for a particular type.
135  /// </summary>
136  /// <returns>
137  /// A hash code for the current <see cref="T:System.Object"/>.
138  /// </returns>
139  /// <filterpriority>2</filterpriority>
140  public override int GetHashCode()
141  {
142  unchecked
143  {
144  return ((Source != null ? Source.GetHashCode() : 0)*397) ^ (int) TransportMedium;
145  }
146  }
147 
148  /// <summary>
149  /// Indicates whether the current object is equal to another object of the same type.
150  /// </summary>
151  /// <param name="left">The <see cref="SubscriptionDataSource"/> instance on the left of the operator</param>
152  /// <param name="right">The <see cref="SubscriptionDataSource"/> instance on the right of the operator</param>
153  /// <returns>True if the two instances are considered equal, false otherwise</returns>
155  {
156  return Equals(left, right);
157  }
158 
159  /// <summary>
160  /// Indicates whether the current object is not equal to another object of the same type.
161  /// </summary>
162  /// <param name="left">The <see cref="SubscriptionDataSource"/> instance on the left of the operator</param>
163  /// <param name="right">The <see cref="SubscriptionDataSource"/> instance on the right of the operator</param>
164  /// <returns>True if the two instances are not considered equal, false otherwise</returns>
166  {
167  return !Equals(left, right);
168  }
169 
170  /// <summary>
171  /// Returns a string that represents the current object.
172  /// </summary>
173  /// <returns>
174  /// A string that represents the current object.
175  /// </returns>
176  /// <filterpriority>2</filterpriority>
177  public override string ToString()
178  {
179  return Invariant($"{TransportMedium}: {Format} {Source}");
180  }
181 
182  /// <summary>
183  /// Gets the default transport medium for the specified source
184  /// </summary>
185  private static SubscriptionTransportMedium GetDefaultSubscriptionTransportMedium(string source)
186  {
187  if (source.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
188  source.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
189  {
190  return SubscriptionTransportMedium.RemoteFile;
191  }
192  return SubscriptionTransportMedium.LocalFile;
193  }
194  }
195 }