Lean  $LEAN_TAG$
Messages.QuantConnect.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.Runtime.CompilerServices;
19 
20 using Python.Runtime;
21 
23 
24 using static QuantConnect.StringExtensions;
25 
26 namespace QuantConnect
27 {
28  /// <summary>
29  /// Provides user-facing message construction methods and static messages for the <see cref="QuantConnect"/> namespace
30  /// </summary>
31  public static partial class Messages
32  {
33  /// <summary>
34  /// Provides user-facing messages for the <see cref="AlphaRuntimeStatistics"/> class and its consumers or related classes
35  /// </summary>
36  public static class AlphaRuntimeStatistics
37  {
38  /// <summary>
39  /// Returns a string message saying: Return Over Maximum Drawdown
40  /// </summary>
41  public static string ReturnOverMaximumDrawdownKey = "Return Over Maximum Drawdown";
42 
43  /// <summary>
44  /// Returns a string message saying: Portfolio Turnover
45  /// </summary>
46  public static string PortfolioTurnoverKey = "Portfolio Turnover";
47 
48  /// <summary>
49  /// Returns a string message saying: Total Insights Generated
50  /// </summary>
51  public static string TotalInsightsGeneratedKey = "Total Insights Generated";
52 
53  /// <summary>
54  /// Returns a string message saying: Total Insights Closed
55  /// </summary>
56  public static string TotalInsightsClosedKey = "Total Insights Closed";
57 
58  /// <summary>
59  /// Returns a string message saying: Total Insights Analysis Completed
60  /// </summary>
61  public static string TotalInsightsAnalysisCompletedKey = "Total Insights Analysis Completed";
62 
63  /// <summary>
64  /// Returns a string message saying: Long Insight Count
65  /// </summary>
66  public static string LongInsightCountKey = "Long Insight Count";
67 
68  /// <summary>
69  /// Returns a string message saying: Short Insight Count
70  /// </summary>
71  public static string ShortInsightCountKey = "Short Insight Count";
72 
73  /// <summary>
74  /// Returns a string message saying: Long/Short Ratio
75  /// </summary>
76  public static string LongShortRatioKey = "Long/Short Ratio";
77  }
78 
79  /// <summary>
80  /// Provides user-facing messages for the <see cref="QuantConnect.Chart"/> class and its consumers or related classes
81  /// </summary>
82  public static class Chart
83  {
84  /// <summary>
85  /// Returns a string message saying Chart series name already exists
86  /// </summary>
87  public static string ChartSeriesAlreadyExists = "Chart series name already exists";
88  }
89 
90  /// <summary>
91  /// Provides user-facing messages for the <see cref="QuantConnect.ChartPoint"/> class and its consumers or related classes
92  /// </summary>
93  public static class ChartPoint
94  {
95  /// <summary>
96  /// Parses a given ChartPoint object into a string message
97  /// </summary>
98  [MethodImpl(MethodImplOptions.AggressiveInlining)]
99  public static string ToString(QuantConnect.ChartPoint instance)
100  {
101  return Invariant($"{instance.Time:o} - {instance.y}");
102  }
103  }
104 
105  /// <summary>
106  /// Provides user-facing messages for the <see cref="QuantConnect.Candlestick"/> class and its consumers or related classes
107  /// </summary>
108  public static class Candlestick
109  {
110  /// <summary>
111  /// Parses a given Candlestick object into a string message
112  /// </summary>
113  [MethodImpl(MethodImplOptions.AggressiveInlining)]
114  public static string ToString(QuantConnect.Candlestick instance)
115  {
116  return Invariant($@"{instance.Time:o} - (O:{instance.Open} H: {instance.High} L: {
117  instance.Low} C: {instance.Close})");
118  }
119  }
120 
121  /// <summary>
122  /// Provides user-facing messages for the <see cref="QuantConnect.Currencies"/> class and its consumers or related classes
123  /// </summary>
124  public static class Currencies
125  {
126  /// <summary>
127  /// Returns a string message saying the given value cannot be converted to a decimal number
128  /// </summary>
129  [MethodImpl(MethodImplOptions.AggressiveInlining)]
130  public static string FailedConversionToDecimal(string value)
131  {
132  return $"The value {value} cannot be converted to a decimal number";
133  }
134  }
135 
136  /// <summary>
137  /// Provides user-facing messages for the <see cref="QuantConnect.ExtendedDictionary{T}"/> class and its consumers or related classes
138  /// </summary>
139  public static class ExtendedDictionary
140  {
141  /// <summary>
142  /// Returns a string message saying the types deriving from ExtendedDictionary must implement the void Clear() method
143  /// </summary>
144  public static string ClearMethodNotImplemented = "Types deriving from 'ExtendedDictionary' must implement the 'void Clear() method.";
145 
146  /// <summary>
147  /// Returns a string message saying the types deriving from ExtendedDictionary must implement the void Remove(Symbol) method
148  /// </summary>
149  public static string RemoveMethodNotImplemented =
150  "Types deriving from 'ExtendedDictionary' must implement the 'void Remove(Symbol) method.";
151 
152  /// <summary>
153  /// Returns a string message saying the types deriving from ExtendedDictionary must implement the T this[Symbol] method
154  /// </summary>
155  public static string IndexerBySymbolNotImplemented =
156  "Types deriving from 'ExtendedDictionary' must implement the 'T this[Symbol] method.";
157 
158  /// <summary>
159  /// Returns a string message saying Clear/clear method call is an invalid operation. It also says that the given instance
160  /// is a read-only collection
161  /// </summary>
162  [MethodImpl(MethodImplOptions.AggressiveInlining)]
163  public static string ClearInvalidOperation<T>(ExtendedDictionary<T> instance)
164  {
165  return $"Clear/clear method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
166  }
167 
168  /// <summary>
169  /// Returns a string message saying that Remove/pop call method is an invalid operation. It also says that the given instance
170  /// is a read-only collection
171  /// </summary>
172  [MethodImpl(MethodImplOptions.AggressiveInlining)]
173  public static string RemoveInvalidOperation<T>(ExtendedDictionary<T> instance)
174  {
175  return $"Remove/pop method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
176  }
177 
178  /// <summary>
179  /// Returns a string message saying that the given ticker was not found in the SymbolCache. It also gives a recommendation
180  /// for solving this problem
181  /// </summary>
182  [MethodImpl(MethodImplOptions.AggressiveInlining)]
183  public static string TickerNotFoundInSymbolCache(string ticker)
184  {
185  return $"The ticker {ticker} was not found in the SymbolCache. Use the Symbol object as key instead. " +
186  "Accessing the securities collection/slice object by string ticker is only available for securities added with " +
187  "the AddSecurity-family methods. For more details, please check out the documentation.";
188  }
189 
190  /// <summary>
191  /// Returns a string message saying that the popitem method is not supported for the given instance
192  /// </summary>
193  [MethodImpl(MethodImplOptions.AggressiveInlining)]
195  {
196  return $"popitem method is not supported for {instance.GetType().Name}";
197  }
198 
199  /// <summary>
200  /// Returns a string message saying that the given symbol wasn't found in the give instance object. It also shows
201  /// a recommendation for solving this problem
202  /// </summary>
203  [MethodImpl(MethodImplOptions.AggressiveInlining)]
205  {
206  return $"'{symbol}' wasn't found in the {instance.GetType().Name} object, likely because there was no-data at this moment in " +
207  "time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with " +
208  $"data.ContainsKey(\"{symbol}\"). The collection is read-only, cannot set default.";
209  }
210 
211  /// <summary>
212  /// Returns a string message saying the update method call is an invalid operation. It also mentions that the given
213  /// instance is a read-only collection
214  /// </summary>
215  [MethodImpl(MethodImplOptions.AggressiveInlining)]
216  public static string UpdateInvalidOperation<T>(ExtendedDictionary<T> instance)
217  {
218  return $"update method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
219  }
220  }
221 
222  /// <summary>
223  /// Provides user-facing messages for the <see cref="QuantConnect.Extensions"/> class and its consumers or related classes
224  /// </summary>
225  public static class Extensions
226  {
227  /// <summary>
228  /// Returns a string message saying adjusting a symbol by an offset is currently only supported for non canonical futures
229  /// </summary>
230  public static string ErrorAdjustingSymbolByOffset =
231  "Adjusting a symbol by an offset is currently only supported for non canonical futures";
232 
233  /// <summary>
234  /// Returns a string message saying the provided DataProvider instance is null
235  /// </summary>
236  public static string NullDataProvider =
237  $"The provided '{nameof(IDataProvider)}' instance is null. Are you missing some initialization step?";
238 
239  /// <summary>
240  /// Returns a string message saying the source cannot be null or empty
241  /// </summary>
242  public static string NullOrEmptySourceToConvertToHexString = "Source cannot be null or empty.";
243 
244  /// <summary>
245  /// Returns a string message saying the CreateOptionChain method requires an option symbol
246  /// </summary>
247  public static string CreateOptionChainRequiresOptionSymbol = "CreateOptionChain requires an option symbol.";
248 
249  /// <summary>
250  /// Returns a string message saying the CreateFutureChain method requires a future symbol
251  /// </summary>
252  public static string CreateFutureChainRequiresFutureSymbol = "CreateFutureChain requires a future symbol.";
253 
254  /// <summary>
255  /// Returns a string message saying the list of values cannot be empty
256  /// </summary>
257  public static string GreatestCommonDivisorEmptyList = "The list of values cannot be empty";
258 
259  /// <summary>
260  /// Returns a string message saying the process of downloading data from the given url failed
261  /// </summary>
262  [MethodImpl(MethodImplOptions.AggressiveInlining)]
263  public static string DownloadDataFailed(string url)
264  {
265  return $"failed for: '{url}'";
266  }
267 
268  /// <summary>
269  /// Returns a string message saying the security does not have an accurate price as it has not yet received
270  /// a bar of data, as well as some recommendations
271  /// </summary>
272  [MethodImpl(MethodImplOptions.AggressiveInlining)]
273  public static string ZeroPriceForSecurity(QuantConnect.Symbol symbol)
274  {
275  return $"{symbol}: The security does not have an accurate price as it has not yet received a bar of data. " +
276  "Before placing a trade (or using SetHoldings) warm up your algorithm with SetWarmup, or use slice.Contains(symbol) " +
277  "to confirm the Slice object has price before using the data. Data does not necessarily all arrive at the same " +
278  "time so your algorithm should confirm the data is ready before using it. In live trading this can mean you do " +
279  "not have an active subscription to the asset class you're trying to trade. If using custom data make sure you've " +
280  "set the 'Value' property.";
281  }
282 
283  /// <summary>
284  /// Returns a string message saying: Waiting for the given thread to stop
285  /// </summary>
286  [MethodImpl(MethodImplOptions.AggressiveInlining)]
287  public static string WaitingForThreadToStopSafely(string threadName)
288  {
289  return $"Waiting for '{threadName}' thread to stop...";
290  }
291 
292  /// <summary>
293  /// Returns a string message saying: Timeout waiting for the given thread to stop
294  /// </summary>
295  [MethodImpl(MethodImplOptions.AggressiveInlining)]
296  public static string TimeoutWaitingForThreadToStopSafely(string threadName)
297  {
298  return $"Timeout waiting for '{threadName}' thread to stop";
299  }
300 
301  /// <summary>
302  /// Returns a string message saying the given data type is missing a parameterless constructor
303  /// </summary>
304  [MethodImpl(MethodImplOptions.AggressiveInlining)]
305  public static string DataTypeMissingParameterlessConstructor(Type type)
306  {
307  return $"Data type '{type.Name}' missing parameterless constructor. E.g. public {type.Name}() {{ }}";
308  }
309 
310  /// <summary>
311  /// Returns a string message saying the process of creating an instance of the given type failed
312  /// </summary>
313  [MethodImpl(MethodImplOptions.AggressiveInlining)]
314  public static string FailedToCreateInstanceOfType(Type type)
315  {
316  return $"Failed to create instance of type '{type.Name}'";
317  }
318 
319  /// <summary>
320  /// Returns a string message saying the given data type does not inherit the required BaseData
321  /// methods and/or attributes
322  /// </summary>
323  [MethodImpl(MethodImplOptions.AggressiveInlining)]
324  public static string TypeIsNotBaseData(Type type)
325  {
326  return $"Data type '{type.Name}' does not inherit required {nameof(Data.BaseData)}";
327  }
328 
329  /// <summary>
330  /// Returns a string message saying it is impossible to cast the given non-finite floating-point value
331  /// as a decimal
332  /// </summary>
333  [MethodImpl(MethodImplOptions.AggressiveInlining)]
334  public static string CannotCastNonFiniteFloatingPointValueToDecimal(double input)
335  {
336  return Invariant($@"It is not possible to cast a non-finite floating-point value ({
337  input}) as decimal. Please review math operations and verify the result is valid.");
338  }
339 
340  /// <summary>
341  /// Returns a string message saying it was not able to exactly convert the given time span to resolution
342  /// </summary>
343  [MethodImpl(MethodImplOptions.AggressiveInlining)]
344  public static string UnableToConvertTimeSpanToResolution(TimeSpan timeSpan)
345  {
346  return Invariant($"Unable to exactly convert time span ('{timeSpan}') to resolution.");
347  }
348 
349  /// <summary>
350  /// Returns a string message saying it was attempted to parse the given unknown security type
351  /// </summary>
352  [MethodImpl(MethodImplOptions.AggressiveInlining)]
353  public static string UnableToParseUnknownSecurityType(string value)
354  {
355  return $"Attempted to parse unknown SecurityType: {value}";
356  }
357 
358  /// <summary>
359  /// Returns a string message saying the given security type has no default OptionStyle, because it has no options
360  /// available for it
361  /// </summary>
362  [MethodImpl(MethodImplOptions.AggressiveInlining)]
363  public static string NoDefaultOptionStyleForSecurityType(SecurityType securityType)
364  {
365  return Invariant($"The SecurityType {securityType} has no default OptionStyle, because it has no options available for it");
366  }
367 
368  /// <summary>
369  /// Returns a string message saying the given OptionStyle was unexpected/unknown
370  /// </summary>
371  [MethodImpl(MethodImplOptions.AggressiveInlining)]
372  public static string UnknownOptionStyle(string value)
373  {
374  return $"Unexpected OptionStyle: {value}";
375  }
376 
377  /// <summary>
378  /// Returns a string message saying the given OptionStyle was unexpected/unknown
379  /// </summary>
380  [MethodImpl(MethodImplOptions.AggressiveInlining)]
381  public static string UnknownOptionStyle(OptionStyle value)
382  {
383  return $"Unexpected OptionStyle: {value}";
384  }
385 
386  /// <summary>
387  /// Returns a string message saying the given OptionRight was unexpected/unknown
388  /// </summary>
389  [MethodImpl(MethodImplOptions.AggressiveInlining)]
390  public static string UnknownOptionRight(string value)
391  {
392  return $"Unexpected OptionRight: {value}";
393  }
394 
395  /// <summary>
396  /// Returns a string message saying the given OptionRight was unexpected/unknown
397  /// </summary>
398  [MethodImpl(MethodImplOptions.AggressiveInlining)]
399  public static string UnknownOptionRight(OptionRight value)
400  {
401  return $"Unexpected OptionRight: {value}";
402  }
403 
404  /// <summary>
405  /// Returns a string message saying the given DataMappingMode was unexpected/unknown
406  /// </summary>
407  [MethodImpl(MethodImplOptions.AggressiveInlining)]
408  public static string UnknownDataMappingMode(string value)
409  {
410  return $"Unexpected DataMappingMode: {value}";
411  }
412 
413  /// <summary>
414  /// Returns a string message saying the given method cannot be used to convert a PyObject into the given type
415  /// </summary>
416  [MethodImpl(MethodImplOptions.AggressiveInlining)]
417  public static string ConvertToDelegateCannotConverPyObjectToType(string methodName, Type type)
418  {
419  return $"{methodName} cannot be used to convert a PyObject into {type}.";
420  }
421 
422  /// <summary>
423  /// Returns a string message saying the method ConvertToDictionary cannot be used to convert a given source
424  /// type into another given target type. It also specifies the reason.
425  /// </summary>
426  [MethodImpl(MethodImplOptions.AggressiveInlining)]
427  public static string ConvertToDictionaryFailed(string sourceType, string targetType, string reason)
428  {
429  return $"ConvertToDictionary cannot be used to convert a {sourceType} into {targetType}. Reason: {reason}";
430  }
431 
432  /// <summary>
433  /// Returns a string message saying the given argument type should Symbol or a list of Symbol. It also
434  /// shows the given item as well as its Python type
435  /// </summary>
436  [MethodImpl(MethodImplOptions.AggressiveInlining)]
437  public static string ConvertToSymbolEnumerableFailed(PyObject item)
438  {
439  return $"Argument type should be Symbol or a list of Symbol. Object: {item}. Type: {item.GetPythonType()}";
440  }
441 
442  /// <summary>
443  /// Returns a string message saying the given object is not a C# type
444  /// </summary>
445  [MethodImpl(MethodImplOptions.AggressiveInlining)]
446  public static string ObjectFromPythonIsNotACSharpType(string objectRepr)
447  {
448  return $"{objectRepr} is not a C# Type.";
449  }
450 
451  /// <summary>
452  /// Returns a string message saying there was a RuntimeError at a given time in UTC. It also
453  /// shows the given context
454  /// </summary>
455  [MethodImpl(MethodImplOptions.AggressiveInlining)]
456  public static string RuntimeError(IAlgorithm algorithm, string context)
457  {
458  return Invariant($"RuntimeError at {algorithm.UtcTime} UTC. Context: {context}");
459  }
460  }
461 
462  /// <summary>
463  /// Provides user-facing messages for the <see cref="QuantConnect.Holding"/> class and its consumers or related classes
464  /// </summary>
465  public static class Holding
466  {
467  /// <summary>
468  /// Parses a Holding object into a string message
469  /// </summary>
470  [MethodImpl(MethodImplOptions.AggressiveInlining)]
471  public static string ToString(QuantConnect.Holding instance)
472  {
473  var value = Invariant($@"{instance.Symbol.Value}: {instance.Quantity} @ {
474  instance.CurrencySymbol}{instance.AveragePrice} - Market: {instance.CurrencySymbol}{instance.MarketPrice}");
475 
476  if (instance.ConversionRate != 1m)
477  {
478  value += Invariant($" - Conversion: {instance.ConversionRate}");
479  }
480 
481  return value;
482  }
483  }
484 
485  /// <summary>
486  /// Provides user-facing messages for the <see cref="QuantConnect.AlgorithmControl"/> class and its consumers or related classes
487  /// </summary>
488  public static class AlgorithmControl
489  {
490  /// <summary>
491  /// Returns a string message saying: Strategy Equity
492  /// </summary>
493  public static string ChartSubscription = "Strategy Equity";
494  }
495 
496  /// <summary>
497  /// Provides user-facing messages for the <see cref="QuantConnect.Isolator"/> class and its consumers or related classes
498  /// </summary>
499  public static class Isolator
500  {
501  /// <summary>
502  /// Returns a string message saying: Execution Security Error: Memory Usage Maxed out, with the max memory capacity
503  /// and a last sample of the usage
504  /// </summary>
505  [MethodImpl(MethodImplOptions.AggressiveInlining)]
506  public static string MemoryUsageMaxedOut(string memoryCap, string lastSample)
507  {
508  return $"Execution Security Error: Memory Usage Maxed Out - {memoryCap}MB max, with last sample of {lastSample}MB.";
509  }
510 
511  /// <summary>
512  /// Returns a string message saying: Execution Security Error: Memory usage over 80% capacity, and the last sample taken
513  /// </summary>
514  [MethodImpl(MethodImplOptions.AggressiveInlining)]
515  public static string MemoryUsageOver80Percent(double lastSample)
516  {
517  return Invariant($"Execution Security Error: Memory usage over 80% capacity. Sampled at {lastSample}");
518  }
519 
520  /// <summary>
521  /// Returns a string message with useful information about the memory usage, such us the memory used, the last sample
522  /// the current memory used by the given app and the CPU usage
523  /// </summary>
524  [MethodImpl(MethodImplOptions.AggressiveInlining)]
525  public static string MemoryUsageInfo(string memoryUsed, string lastSample, string memoryUsedByApp, TimeSpan currentTimeStepElapsed,
526  int cpuUsage)
527  {
528  return Invariant($@"Used: {memoryUsed}, Sample: {lastSample}, App: {memoryUsedByApp}, CurrentTimeStepElapsed: {
529  currentTimeStepElapsed:mm':'ss'.'fff}. CPU: {cpuUsage}%");
530  }
531 
532  /// <summary>
533  /// Returns a string message saying: Execution Security Error: Operation timed out, with the maximum amount of minutes
534  /// allowed
535  /// </summary>
536  [MethodImpl(MethodImplOptions.AggressiveInlining)]
537  public static string MemoryUsageMonitorTaskTimedOut(TimeSpan timeout)
538  {
539  return $@"Execution Security Error: Operation timed out - {
540  timeout.TotalMinutes.ToStringInvariant()} minutes max. Check for recursive loops.";
541  }
542  }
543 
544  /// <summary>
545  /// Provides user-facing messages for the <see cref="QuantConnect.Market"/> class and its consumers or related classes
546  /// </summary>
547  public static class Market
548  {
549  /// <summary>
550  /// Returns a string message saying the market identifier is limited to positive values less than the given maximum market identifier
551  /// </summary>
552  [MethodImpl(MethodImplOptions.AggressiveInlining)]
553  public static string InvalidMarketIdentifier(int maxMarketIdentifier)
554  {
555  return $"The market identifier is limited to positive values less than {maxMarketIdentifier.ToStringInvariant()}.";
556  }
557 
558  /// <summary>
559  /// Returns a string message saying it was attempted to add an already added market with a different identifier
560  /// </summary>
561  [MethodImpl(MethodImplOptions.AggressiveInlining)]
562  public static string TriedToAddExistingMarketWithDifferentIdentifier(string market)
563  {
564  return $"Attempted to add an already added market with a different identifier. Market: {market}";
565  }
566 
567  /// <summary>
568  /// Returns a string message saying it was attempted to add a market identifier that is already in use
569  /// </summary>
570  /// <returns></returns>
571  [MethodImpl(MethodImplOptions.AggressiveInlining)]
572  public static string TriedToAddExistingMarketIdentifier(string market, string existingMarket)
573  {
574  return $"Attempted to add a market identifier that is already in use. New Market: {market} Existing Market: {existingMarket}";
575  }
576  }
577 
578  /// <summary>
579  /// Provides user-facing messages for the <see cref="QuantConnect.OS"/> class and its consumers or related classes
580  /// </summary>
581  public static class OS
582  {
583  /// <summary>
584  /// CPU Usage string
585  /// </summary>
586  public static string CPUUsageKey = "CPU Usage";
587 
588  /// <summary>
589  /// Used RAM (MB) string
590  /// </summary>
591  public static string UsedRAMKey = "Used RAM (MB)";
592 
593  /// <summary>
594  /// Total RAM (MB) string
595  /// </summary>
596  public static string TotalRAMKey = "Total RAM (MB)";
597 
598  /// <summary>
599  /// Hostname string
600  /// </summary>
601  public static string HostnameKey = "Hostname";
602 
603  /// <summary>
604  /// LEAN Version string
605  /// </summary>
606  public static string LEANVersionKey = "LEAN Version";
607  }
608 
609  /// <summary>
610  /// Provides user-facing messages for the <see cref="QuantConnect.Parse"/> class and its consumers or related classes
611  /// </summary>
612  public static class Parse
613  {
614  /// <summary>
615  /// Returns a string message saying the provided input was not parseable as the given target type
616  /// </summary>
617  [MethodImpl(MethodImplOptions.AggressiveInlining)]
618  public static string ValueIsNotParseable(string input, Type targetType)
619  {
620  return $"The provided value ({input}) was not parseable as {targetType.Name}";
621  }
622  }
623 
624  /// <summary>
625  /// Provides user-facing messages for the <see cref="QuantConnect.SecurityIdentifier"/> class and its consumers or related classes
626  /// </summary>
627  public static class SecurityIdentifier
628  {
629  /// <summary>
630  /// Returns a string message saying no underlying was specified for certain identifier
631  /// </summary>
632  public static string NoUnderlyingForIdentifier =
633  "No underlying specified for this identifier. Check that HasUnderlying is true before accessing the Underlying property.";
634 
635  /// <summary>
636  /// Returns a string message saying Date is only defined for SecurityType.Equity, SecurityType.Option, SecurityType.Future, SecurityType.FutureOption, SecurityType.IndexOption, and SecurityType.Base
637  /// </summary>
638  public static string DateNotSupportedBySecurityType =
639  "Date is only defined for SecurityType.Equity, SecurityType.Option, SecurityType.Future, SecurityType.FutureOption, SecurityType.IndexOption, and SecurityType.Base";
640 
641  /// <summary>
642  /// Returns a string message saying StrikePrice is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption
643  /// </summary>
645  "StrikePrice is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
646 
647  /// <summary>
648  /// Returns a string message saying OptionRight is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption
649  /// </summary>
651  "OptionRight is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
652 
653  /// <summary>
654  /// Returns a string message saying OptionStyle is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption
655  /// </summary>
657  "OptionStyle is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
658 
659  /// <summary>
660  /// Returns a string message saying SecurityIdentifier requires a non-null string 'symbol'
661  /// </summary>
662  public static string NullSymbol = "SecurityIdentifier requires a non-null string 'symbol'";
663 
664  /// <summary>
665  /// Returns a string message saying Symbol must not contain the characters '|' or ' '
666  /// </summary>
667  public static string SymbolWithInvalidCharacters = "Symbol must not contain the characters '|' or ' '.";
668 
669  /// <summary>
670  /// Returns a string message saying the provided properties do not match with a valid SecurityType
671  /// </summary>
672  public static string PropertiesDoNotMatchAnySecurityType = $"The provided properties do not match with a valid {nameof(SecurityType)}";
673 
674  /// <summary>
675  /// Returns a string message saying the string must be splittable on space into two parts
676  /// </summary>
677  public static string StringIsNotSplittable = "The string must be splittable on space into two parts.";
678 
679  /// <summary>
680  /// Returns a string message saying object must be of type SecurityIdentifier
681  /// </summary>
682  public static string UnexpectedTypeToCompareTo = $"Object must be of type {nameof(SecurityIdentifier)}";
683 
684  /// <summary>
685  /// Returns a string message saying the given parameter must be between 0 and 99
686  /// </summary>
687  [MethodImpl(MethodImplOptions.AggressiveInlining)]
688  public static string InvalidSecurityType(string parameterName)
689  {
690  return $"{parameterName} must be between 0 and 99";
691  }
692 
693  /// <summary>
694  /// Returns a string message saying the given parameter must be either 0 or 1
695  /// </summary>
696  [MethodImpl(MethodImplOptions.AggressiveInlining)]
697  public static string InvalidOptionRight(string parameterName)
698  {
699  return $"{parameterName} must be either 0 or 1";
700  }
701 
702  /// <summary>
703  /// Returns a string message saying the specified strike price's precision is too high
704  /// </summary>
705  [MethodImpl(MethodImplOptions.AggressiveInlining)]
706  public static string InvalidStrikePrice(decimal strikePrice)
707  {
708  return Invariant($"The specified strike price's precision is too high: {strikePrice}");
709  }
710 
711  /// <summary>
712  /// Returns a string message saying there was an error parsing SecurityIdentifier. It also says the given error and exception
713  /// </summary>
714  [MethodImpl(MethodImplOptions.AggressiveInlining)]
715  public static string ErrorParsingSecurityIdentifier(string value, Exception exception)
716  {
717  return Invariant($"Error parsing SecurityIdentifier: '{value}', Exception: {exception}");
718  }
719 
720  /// <summary>
721  /// Returns a string message saying the given market could not be found in the markets lookup
722  /// </summary>
723  [MethodImpl(MethodImplOptions.AggressiveInlining)]
724  public static string MarketNotFound(string market)
725  {
726  return $@"The specified market wasn't found in the markets lookup. Requested: {
727  market}. You can add markets by calling QuantConnect.Market.Add(string,int)";
728  }
729  }
730 
731  /// <summary>
732  /// Provides user-facing messages for the <see cref="QuantConnect.StringExtensions"/> class and its consumers or related classes
733  /// </summary>
734  public static class StringExtensions
735  {
736  /// <summary>
737  /// Returns a string message saying StringExtensinos.ConvertInvariant does not support converting to the given TypeCode
738  /// </summary>
739  [MethodImpl(MethodImplOptions.AggressiveInlining)]
740  public static string ConvertInvariantCannotConvertTo(TypeCode targetTypeCode)
741  {
742  return $"StringExtensions.ConvertInvariant does not support converting to TypeCode.{targetTypeCode}";
743  }
744  }
745 
746  /// <summary>
747  /// Provides user-facing messages for the <see cref="QuantConnect.Symbol"/> class and its consumers or related classes
748  /// </summary>
749  public static class Symbol
750  {
751  /// <summary>
752  /// Returns a string message saying there is insufficient information for creating certain future option symbol
753  /// </summary>
755  "Cannot create future option Symbol using this method (insufficient information). Use `CreateOption(Symbol, ...)` instead.";
756 
757  /// <summary>
758  /// Returns a string message saying Canonical is only defined for SecurityType.Option, SecurityType.Future, SecurityType.FutureOption
759  /// </summary>
760  public static string CanonicalNotDefined =
761  "Canonical is only defined for SecurityType.Option, SecurityType.Future, SecurityType.FutureOption";
762 
763  /// <summary>
764  /// Returns a string message saying certain object must be of type Symbol or string
765  /// </summary>
766  public static string UnexpectedObjectTypeToCompareTo = "Object must be of type Symbol or string.";
767 
768  /// <summary>
769  /// Returns a string message saying the given security type has not been implemented yet
770  /// </summary>
771  [MethodImpl(MethodImplOptions.AggressiveInlining)]
772  public static string SecurityTypeNotImplementedYet(SecurityType securityType)
773  {
774  return Invariant($"The security type has not been implemented yet: {securityType}");
775  }
776 
777  /// <summary>
778  /// Returns a string message saying the given security can not be mapped
779  /// </summary>
780  [MethodImpl(MethodImplOptions.AggressiveInlining)]
781  public static string SecurityTypeCannotBeMapped(SecurityType securityType)
782  {
783  return Invariant($"SecurityType {securityType} can not be mapped.");
784  }
785 
786  /// <summary>
787  /// Returns a string message saying no option type exists for the given underlying SecurityType
788  /// </summary>
789  [MethodImpl(MethodImplOptions.AggressiveInlining)]
790  public static string NoOptionTypeForUnderlying(SecurityType securityType)
791  {
792  return Invariant($"No option type exists for underlying SecurityType: {securityType}");
793  }
794 
795  /// <summary>
796  /// Returns a string message saying no underlying type exists for the given option SecurityType
797  /// </summary>
798  [MethodImpl(MethodImplOptions.AggressiveInlining)]
799  public static string NoUnderlyingForOption(SecurityType securityType)
800  {
801  return Invariant($"No underlying type exists for option SecurityType: {securityType}");
802  }
803 
804  [MethodImpl(MethodImplOptions.AggressiveInlining)]
805  public static string SidNotForOption(QuantConnect.SecurityIdentifier sid)
806  {
807  return Invariant($"The provided SecurityIdentifier is not for an option: {sid}");
808  }
809 
810  [MethodImpl(MethodImplOptions.AggressiveInlining)]
811  public static string UnderlyingSidDoesNotMatch(QuantConnect.SecurityIdentifier sid, QuantConnect.Symbol underlying)
812  {
813  return Invariant($"The provided SecurityIdentifier does not match the underlying symbol: {sid} != {underlying.ID}");
814  }
815  }
816 
817  /// <summary>
818  /// Provides user-facing messages for the <see cref="QuantConnect.SymbolCache"/> class and its consumers or related classes
819  /// </summary>
820  public static class SymbolCache
821  {
822  /// <summary>
823  /// Returns a string message saying the given ticker could not be localized
824  /// </summary>
825  [MethodImpl(MethodImplOptions.AggressiveInlining)]
826  public static string UnableToLocateTicker(string ticker)
827  {
828  return $"We were unable to locate the ticker '{ticker}'.";
829  }
830 
831  /// <summary>
832  /// Returns a string message saying mutiple potentially matching tickers were localized
833  /// </summary>
834  [MethodImpl(MethodImplOptions.AggressiveInlining)]
835  public static string MultipleMatchingTickersLocated(IEnumerable<string> tickers)
836  {
837  return "We located multiple potentially matching tickers. " +
838  "For custom data, be sure to append a dot followed by the custom data type name. " +
839  $"For example: 'BTC.Bitcoin'. Potential Matches: {string.Join(", ", tickers)}";
840  }
841  }
842 
843  /// <summary>
844  /// Provides user-facing messages for the <see cref="QuantConnect.SymbolRepresentation"/> class and its consumers or related classes
845  /// </summary>
846  public static class SymbolRepresentation
847  {
848  /// <summary>
849  /// Returns a string message saying SymbolRepresentation failed to get market for the given ticker and underlying
850  /// </summary>
851  [MethodImpl(MethodImplOptions.AggressiveInlining)]
852  public static string FailedToGetMarketForTickerAndUnderlying(string ticker, string underlying)
853  {
854  return $"Failed to get market for future '{ticker}' and underlying '{underlying}'";
855  }
856 
857  /// <summary>
858  /// Returns a string message saying no market was found for the given ticker
859  /// </summary>
860  [MethodImpl(MethodImplOptions.AggressiveInlining)]
861  public static string NoMarketFound(string ticker)
862  {
863  return $"No market found for '{ticker}'";
864  }
865 
866  /// <summary>
867  /// Returns a string message saying an unexpected security type was received by the given method name
868  /// </summary>
869  [MethodImpl(MethodImplOptions.AggressiveInlining)]
870  public static string UnexpectedSecurityTypeForMethod(string methodName, SecurityType securityType)
871  {
872  return Invariant($"{methodName} expects symbol to be an option, received {securityType}.");
873  }
874 
875  /// <summary>
876  /// Returns a string message saying the given ticker is not in the expected OSI format
877  /// </summary>
878  [MethodImpl(MethodImplOptions.AggressiveInlining)]
879  public static string InvalidOSITickerFormat(string ticker)
880  {
881  return $"Invalid ticker format {ticker}";
882  }
883 
884  /// <summary>
885  /// Returns a string message saying the given security type is not implemented
886  /// </summary>
887  [MethodImpl(MethodImplOptions.AggressiveInlining)]
888  public static string SecurityTypeNotImplemented(SecurityType securityType)
889  {
890  return Invariant($"Security type {securityType} not implemented");
891  }
892  }
893 
894  /// <summary>
895  /// Provides user-facing messages for the <see cref="QuantConnect.SymbolValueJsonConverter"/> class and its consumers or related classes
896  /// </summary>
897  public static class SymbolValueJsonConverter
898  {
899  /// <summary>
900  /// String message saying converter is write only
901  /// </summary>
902  public static string ConverterIsWriteOnly = "The SymbolValueJsonConverter is write-only.";
903 
904  /// <summary>
905  /// String message saying converter is intended to be directly decorated in member
906  /// </summary>
908  "The SymbolValueJsonConverter is intended to be decorated on the appropriate member directly.";
909  }
910 
911  /// <summary>
912  /// Provides user-facing messages for the <see cref="QuantConnect.Time"/> class and its consumers or related classes
913  /// </summary>
914  public static class Time
915  {
916  /// <summary>
917  /// Invalid Bar Size string message
918  /// </summary>
919  public static string InvalidBarSize = "barSize must be greater than TimeSpan.Zero";
920 
921  /// <summary>
922  /// Returns a string message containing the number of securities
923  /// </summary>
924  [MethodImpl(MethodImplOptions.AggressiveInlining)]
925  public static string SecurityCount(int count)
926  {
927  return $"Security Count: {count}";
928  }
929  }
930 
931  /// <summary>
932  /// Provides user-facing messages for the <see cref="QuantConnect.TradingCalendar"/> class and its consumers or related classes
933  /// </summary>
934  public static class TradingCalendar
935  {
936  /// <summary>
937  /// Returns a string message for invalid total days
938  /// </summary>
939  [MethodImpl(MethodImplOptions.AggressiveInlining)]
940  public static string InvalidTotalDays(int totalDays)
941  {
942  return Invariant($@"Total days is negative ({
943  totalDays
944  }), indicating reverse start and end times. Check your usage of TradingCalendar to ensure proper arrangement of variables");
945  }
946  }
947  }
948 }