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="QuantConnect.AlphaRuntimeStatistics"/> class and its consumers or related classes
35  /// </summary>
36  public static class AlphaRuntimeStatistics
37  {
38  public static string ReturnOverMaximumDrawdownKey = "Return Over Maximum Drawdown";
39 
40  public static string PortfolioTurnoverKey = "Portfolio Turnover";
41 
42  public static string TotalInsightsGeneratedKey = "Total Insights Generated";
43 
44  public static string TotalInsightsClosedKey = "Total Insights Closed";
45 
46  public static string TotalInsightsAnalysisCompletedKey = "Total Insights Analysis Completed";
47 
48  public static string LongInsightCountKey = "Long Insight Count";
49 
50  public static string ShortInsightCountKey = "Short Insight Count";
51 
52  public static string LongShortRatioKey = "Long/Short Ratio";
53  }
54 
55  /// <summary>
56  /// Provides user-facing messages for the <see cref="QuantConnect.Chart"/> class and its consumers or related classes
57  /// </summary>
58  public static class Chart
59  {
60  public static string ChartSeriesAlreadyExists = "Chart series name already exists";
61  }
62 
63  /// <summary>
64  /// Provides user-facing messages for the <see cref="QuantConnect.ChartPoint"/> class and its consumers or related classes
65  /// </summary>
66  public static class ChartPoint
67  {
68  [MethodImpl(MethodImplOptions.AggressiveInlining)]
69  public static string ToString(QuantConnect.ChartPoint instance)
70  {
71  return Invariant($"{instance.Time:o} - {instance.y}");
72  }
73  }
74 
75  /// <summary>
76  /// Provides user-facing messages for the <see cref="QuantConnect.Candlestick"/> class and its consumers or related classes
77  /// </summary>
78  public static class Candlestick
79  {
80  [MethodImpl(MethodImplOptions.AggressiveInlining)]
81  public static string ToString(QuantConnect.Candlestick instance)
82  {
83  return Invariant($@"{instance.Time:o} - (O:{instance.Open} H: {instance.High} L: {
84  instance.Low} C: {instance.Close})");
85  }
86  }
87 
88  /// <summary>
89  /// Provides user-facing messages for the <see cref="QuantConnect.Currencies"/> class and its consumers or related classes
90  /// </summary>
91  public static class Currencies
92  {
93  [MethodImpl(MethodImplOptions.AggressiveInlining)]
94  public static string FailedConversionToDecimal(string value)
95  {
96  return $"The value {value} cannot be converted to a decimal number";
97  }
98  }
99 
100  /// <summary>
101  /// Provides user-facing messages for the <see cref="QuantConnect.ExtendedDictionary{T}"/> class and its consumers or related classes
102  /// </summary>
103  public static class ExtendedDictionary
104  {
105  public static string ClearMethodNotImplemented = "Types deriving from 'ExtendedDictionary' must implement the 'void Clear() method.";
106 
107  public static string RemoveMethodNotImplemented =
108  "Types deriving from 'ExtendedDictionary' must implement the 'void Remove(Symbol) method.";
109 
110  public static string IndexerBySymbolNotImplemented =
111  "Types deriving from 'ExtendedDictionary' must implement the 'T this[Symbol] method.";
112 
113  [MethodImpl(MethodImplOptions.AggressiveInlining)]
114  public static string ClearInvalidOperation<T>(ExtendedDictionary<T> instance)
115  {
116  return $"Clear/clear method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
117  }
118 
119  [MethodImpl(MethodImplOptions.AggressiveInlining)]
120  public static string RemoveInvalidOperation<T>(ExtendedDictionary<T> instance)
121  {
122  return $"Remove/pop method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
123  }
124 
125  [MethodImpl(MethodImplOptions.AggressiveInlining)]
126  public static string TickerNotFoundInSymbolCache(string ticker)
127  {
128  return $"The ticker {ticker} was not found in the SymbolCache. Use the Symbol object as key instead. " +
129  "Accessing the securities collection/slice object by string ticker is only available for securities added with " +
130  "the AddSecurity-family methods. For more details, please check out the documentation.";
131  }
132 
133  [MethodImpl(MethodImplOptions.AggressiveInlining)]
134  public static string PopitemMethodNotSupported<T>(ExtendedDictionary<T> instance)
135  {
136  return $"popitem method is not supported for {instance.GetType().Name}";
137  }
138 
139  [MethodImpl(MethodImplOptions.AggressiveInlining)]
140  public static string SymbolNotFoundDueToNoData<T>(ExtendedDictionary<T> instance, QuantConnect.Symbol symbol)
141  {
142  return $"'{symbol}' wasn't found in the {instance.GetType().Name} object, likely because there was no-data at this moment in " +
143  "time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with " +
144  $"data.ContainsKey(\"{symbol}\"). The collection is read-only, cannot set default.";
145  }
146 
147  [MethodImpl(MethodImplOptions.AggressiveInlining)]
148  public static string UpdateInvalidOperation<T>(ExtendedDictionary<T> instance)
149  {
150  return $"update method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
151  }
152  }
153 
154  /// <summary>
155  /// Provides user-facing messages for the <see cref="QuantConnect.Extensions"/> class and its consumers or related classes
156  /// </summary>
157  public static class Extensions
158  {
159  public static string ErrorAdjustingSymbolByOffset =
160  "Adjusting a symbol by an offset is currently only supported for non canonical futures";
161 
162  public static string NullDataProvider =
163  $"The provided '{nameof(IDataProvider)}' instance is null. Are you missing some initialization step?";
164 
165  public static string NullOrEmptySourceToConvertToHexString = "Source cannot be null or empty.";
166 
167  public static string CreateOptionChainRequiresOptionSymbol = "CreateOptionChain requires an option symbol.";
168 
169  public static string CreateFutureChainRequiresFutureSymbol = "CreateFutureChain requires a future symbol.";
170 
171  public static string GreatestCommonDivisorEmptyList = "The list of values cannot be empty";
172 
173  [MethodImpl(MethodImplOptions.AggressiveInlining)]
174  public static string DownloadDataFailed(string url)
175  {
176  return $"failed for: '{url}'";
177  }
178 
179  [MethodImpl(MethodImplOptions.AggressiveInlining)]
180  public static string ZeroPriceForSecurity(QuantConnect.Symbol symbol)
181  {
182  return $"{symbol}: The security does not have an accurate price as it has not yet received a bar of data. " +
183  "Before placing a trade (or using SetHoldings) warm up your algorithm with SetWarmup, or use slice.Contains(symbol) " +
184  "to confirm the Slice object has price before using the data. Data does not necessarily all arrive at the same " +
185  "time so your algorithm should confirm the data is ready before using it. In live trading this can mean you do " +
186  "not have an active subscription to the asset class you're trying to trade. If using custom data make sure you've " +
187  "set the 'Value' property.";
188  }
189 
190  [MethodImpl(MethodImplOptions.AggressiveInlining)]
191  public static string WaitingForThreadToStopSafely(string threadName)
192  {
193  return $"Waiting for '{threadName}' thread to stop...";
194  }
195 
196  [MethodImpl(MethodImplOptions.AggressiveInlining)]
197  public static string TimeoutWaitingForThreadToStopSafely(string threadName)
198  {
199  return $"Timeout waiting for '{threadName}' thread to stop";
200  }
201 
202  [MethodImpl(MethodImplOptions.AggressiveInlining)]
203  public static string DataTypeMissingParameterlessConstructor(Type type)
204  {
205  return $"Data type '{type.Name}' missing parameterless constructor. E.g. public {type.Name}() {{ }}";
206  }
207 
208  [MethodImpl(MethodImplOptions.AggressiveInlining)]
209  public static string FailedToCreateInstanceOfType(Type type)
210  {
211  return $"Failed to create instance of type '{type.Name}'";
212  }
213 
214  [MethodImpl(MethodImplOptions.AggressiveInlining)]
215  public static string TypeIsNotBaseData(Type type)
216  {
217  return $"Data type '{type.Name}' does not inherit required {nameof(Data.BaseData)}";
218  }
219 
220  [MethodImpl(MethodImplOptions.AggressiveInlining)]
221  public static string CannotCastNonFiniteFloatingPointValueToDecimal(double input)
222  {
223  return Invariant($@"It is not possible to cast a non-finite floating-point value ({
224  input}) as decimal. Please review math operations and verify the result is valid.");
225  }
226 
227  [MethodImpl(MethodImplOptions.AggressiveInlining)]
228  public static string UnableToConvertTimeSpanToResolution(TimeSpan timeSpan)
229  {
230  return Invariant($"Unable to exactly convert time span ('{timeSpan}') to resolution.");
231  }
232 
233  [MethodImpl(MethodImplOptions.AggressiveInlining)]
234  public static string UnableToParseUnknownSecurityType(string value)
235  {
236  return $"Attempted to parse unknown SecurityType: {value}";
237  }
238 
239  [MethodImpl(MethodImplOptions.AggressiveInlining)]
240  public static string NoDefaultOptionStyleForSecurityType(SecurityType securityType)
241  {
242  return Invariant($"The SecurityType {securityType} has no default OptionStyle, because it has no options available for it");
243  }
244 
245  [MethodImpl(MethodImplOptions.AggressiveInlining)]
246  public static string UnknownOptionStyle(string value)
247  {
248  return $"Unexpected OptionStyle: {value}";
249  }
250 
251  [MethodImpl(MethodImplOptions.AggressiveInlining)]
252  public static string UnknownOptionStyle(OptionStyle value)
253  {
254  return $"Unexpected OptionStyle: {value}";
255  }
256 
257  [MethodImpl(MethodImplOptions.AggressiveInlining)]
258  public static string UnknownOptionRight(string value)
259  {
260  return $"Unexpected OptionRight: {value}";
261  }
262 
263  [MethodImpl(MethodImplOptions.AggressiveInlining)]
264  public static string UnknownOptionRight(OptionRight value)
265  {
266  return $"Unexpected OptionRight: {value}";
267  }
268 
269  [MethodImpl(MethodImplOptions.AggressiveInlining)]
270  public static string UnknownDataMappingMode(string value)
271  {
272  return $"Unexpected DataMappingMode: {value}";
273  }
274 
275  [MethodImpl(MethodImplOptions.AggressiveInlining)]
276  public static string ConvertToDelegateCannotConverPyObjectToType(string methodName, Type type)
277  {
278  return $"{methodName} cannot be used to convert a PyObject into {type}.";
279  }
280 
281  [MethodImpl(MethodImplOptions.AggressiveInlining)]
282  public static string ConvertToDictionaryFailed(string sourceType, string targetType, string reason)
283  {
284  return $"ConvertToDictionary cannot be used to convert a {sourceType} into {targetType}. Reason: {reason}";
285  }
286 
287  [MethodImpl(MethodImplOptions.AggressiveInlining)]
288  public static string ConvertToSymbolEnumerableFailed(PyObject item)
289  {
290  return $"Argument type should be Symbol or a list of Symbol. Object: {item}. Type: {item.GetPythonType()}";
291  }
292 
293  [MethodImpl(MethodImplOptions.AggressiveInlining)]
294  public static string ObjectFromPythonIsNotACSharpType(string objectRepr)
295  {
296  return $"{objectRepr} is not a C# Type.";
297  }
298 
299  [MethodImpl(MethodImplOptions.AggressiveInlining)]
300  public static string RuntimeError(IAlgorithm algorithm, string context)
301  {
302  return Invariant($"RuntimeError at {algorithm.UtcTime} UTC. Context: {context}");
303  }
304  }
305 
306  /// <summary>
307  /// Provides user-facing messages for the <see cref="QuantConnect.Holding"/> class and its consumers or related classes
308  /// </summary>
309  public static class Holding
310  {
311  [MethodImpl(MethodImplOptions.AggressiveInlining)]
312  public static string ToString(QuantConnect.Holding instance)
313  {
314  var value = Invariant($@"{instance.Symbol.Value}: {instance.Quantity} @ {
315  instance.CurrencySymbol}{instance.AveragePrice} - Market: {instance.CurrencySymbol}{instance.MarketPrice}");
316 
317  if (instance.ConversionRate != 1m)
318  {
319  value += Invariant($" - Conversion: {instance.ConversionRate}");
320  }
321 
322  return value;
323  }
324  }
325 
326  /// <summary>
327  /// Provides user-facing messages for the <see cref="QuantConnect.AlgorithmControl"/> class and its consumers or related classes
328  /// </summary>
329  public static class AlgorithmControl
330  {
331  public static string ChartSubscription = "Strategy Equity";
332  }
333 
334  /// <summary>
335  /// Provides user-facing messages for the <see cref="QuantConnect.Isolator"/> class and its consumers or related classes
336  /// </summary>
337  public static class Isolator
338  {
339  [MethodImpl(MethodImplOptions.AggressiveInlining)]
340  public static string MemoryUsageMaxedOut(string memoryCap, string lastSample)
341  {
342  return $"Execution Security Error: Memory Usage Maxed Out - {memoryCap}MB max, with last sample of {lastSample}MB.";
343  }
344 
345  [MethodImpl(MethodImplOptions.AggressiveInlining)]
346  public static string MemoryUsageOver80Percent(double lastSample)
347  {
348  return Invariant($"Execution Security Error: Memory usage over 80% capacity. Sampled at {lastSample}");
349  }
350 
351  [MethodImpl(MethodImplOptions.AggressiveInlining)]
352  public static string MemoryUsageInfo(string memoryUsed, string lastSample, string memoryUsedByApp, TimeSpan currentTimeStepElapsed,
353  int cpuUsage)
354  {
355  return Invariant($@"Used: {memoryUsed}, Sample: {lastSample}, App: {memoryUsedByApp}, CurrentTimeStepElapsed: {
356  currentTimeStepElapsed:mm':'ss'.'fff}. CPU: {cpuUsage}%");
357  }
358 
359  [MethodImpl(MethodImplOptions.AggressiveInlining)]
360  public static string MemoryUsageMonitorTaskTimedOut(TimeSpan timeout)
361  {
362  return $@"Execution Security Error: Operation timed out - {
363  timeout.TotalMinutes.ToStringInvariant()} minutes max. Check for recursive loops.";
364  }
365  }
366 
367  /// <summary>
368  /// Provides user-facing messages for the <see cref="QuantConnect.Market"/> class and its consumers or related classes
369  /// </summary>
370  public static class Market
371  {
372  [MethodImpl(MethodImplOptions.AggressiveInlining)]
373  public static string InvalidMarketIdentifier(int maxMarketIdentifier)
374  {
375  return $"The market identifier is limited to positive values less than {maxMarketIdentifier.ToStringInvariant()}.";
376  }
377 
378  [MethodImpl(MethodImplOptions.AggressiveInlining)]
379  public static string TriedToAddExistingMarketWithDifferentIdentifier(string market)
380  {
381  return $"Attempted to add an already added market with a different identifier. Market: {market}";
382  }
383 
384  [MethodImpl(MethodImplOptions.AggressiveInlining)]
385  public static string TriedToAddExistingMarketIdentifier(string market, string existingMarket)
386  {
387  return $"Attempted to add a market identifier that is already in use. New Market: {market} Existing Market: {existingMarket}";
388  }
389  }
390 
391  /// <summary>
392  /// Provides user-facing messages for the <see cref="QuantConnect.OS"/> class and its consumers or related classes
393  /// </summary>
394  public static class OS
395  {
396  public static string CPUUsageKey = "CPU Usage";
397  public static string UsedRAMKey = "Used RAM (MB)";
398  public static string TotalRAMKey = "Total RAM (MB)";
399  public static string HostnameKey = "Hostname";
400  public static string LEANVersionKey = "LEAN Version";
401  }
402 
403  /// <summary>
404  /// Provides user-facing messages for the <see cref="QuantConnect.Parse"/> class and its consumers or related classes
405  /// </summary>
406  public static class Parse
407  {
408  [MethodImpl(MethodImplOptions.AggressiveInlining)]
409  public static string ValueIsNotParseable(string input, Type targetType)
410  {
411  return $"The provided value ({input}) was not parseable as {targetType.Name}";
412  }
413  }
414 
415  /// <summary>
416  /// Provides user-facing messages for the <see cref="QuantConnect.SecurityIdentifier"/> class and its consumers or related classes
417  /// </summary>
418  public static class SecurityIdentifier
419  {
420  public static string NoUnderlyingForIdentifier =
421  "No underlying specified for this identifier. Check that HasUnderlying is true before accessing the Underlying property.";
422 
423  public static string DateNotSupportedBySecurityType =
424  "Date is only defined for SecurityType.Equity, SecurityType.Option, SecurityType.Future, SecurityType.FutureOption, SecurityType.IndexOption, and SecurityType.Base";
425 
426  public static string StrikePriceNotSupportedBySecurityType =
427  "StrikePrice is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
428 
429  public static string OptionRightNotSupportedBySecurityType =
430  "OptionRight is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
431 
432  public static string OptionStyleNotSupportedBySecurityType =
433  "OptionStyle is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
434 
435  public static string NullSymbol = "SecurityIdentifier requires a non-null string 'symbol'";
436 
437  public static string SymbolWithInvalidCharacters = "Symbol must not contain the characters '|' or ' '.";
438 
439  public static string PropertiesDoNotMatchAnySecurityType = $"The provided properties do not match with a valid {nameof(SecurityType)}";
440 
441  public static string StringIsNotSplittable = "The string must be splittable on space into two parts.";
442 
443  public static string UnexpectedTypeToCompareTo = $"Object must be of type {nameof(SecurityIdentifier)}";
444 
445  [MethodImpl(MethodImplOptions.AggressiveInlining)]
446  public static string InvalidSecurityType(string parameterName)
447  {
448  return $"{parameterName} must be between 0 and 99";
449  }
450 
451  [MethodImpl(MethodImplOptions.AggressiveInlining)]
452  public static string InvalidOptionRight(string parameterName)
453  {
454  return $"{parameterName} must be either 0 or 1";
455  }
456 
457  [MethodImpl(MethodImplOptions.AggressiveInlining)]
458  public static string InvalidStrikePrice(decimal strikePrice)
459  {
460  return Invariant($"The specified strike price's precision is too high: {strikePrice}");
461  }
462 
463  [MethodImpl(MethodImplOptions.AggressiveInlining)]
464  public static string ErrorParsingSecurityIdentifier(string value, Exception exception)
465  {
466  return Invariant($"Error parsing SecurityIdentifier: '{value}', Exception: {exception}");
467  }
468 
469  [MethodImpl(MethodImplOptions.AggressiveInlining)]
470  public static string MarketNotFound(string market)
471  {
472  return $@"The specified market wasn't found in the markets lookup. Requested: {
473  market}. You can add markets by calling QuantConnect.Market.Add(string,int)";
474  }
475  }
476 
477  /// <summary>
478  /// Provides user-facing messages for the <see cref="QuantConnect.StringExtensions"/> class and its consumers or related classes
479  /// </summary>
480  public static class StringExtensions
481  {
482  [MethodImpl(MethodImplOptions.AggressiveInlining)]
483  public static string ConvertInvariantCannotConvertTo(TypeCode targetTypeCode)
484  {
485  return $"StringExtensions.ConvertInvariant does not support converting to TypeCode.{targetTypeCode}";
486  }
487  }
488 
489  /// <summary>
490  /// Provides user-facing messages for the <see cref="QuantConnect.Symbol"/> class and its consumers or related classes
491  /// </summary>
492  public static class Symbol
493  {
494  public static string InsufficientInformationToCreateFutureOptionSymbol =
495  "Cannot create future option Symbol using this method (insufficient information). Use `CreateOption(Symbol, ...)` instead.";
496 
497  public static string CanonicalNotDefined =
498  "Canonical is only defined for SecurityType.Option, SecurityType.Future, SecurityType.FutureOption";
499 
500  public static string UnexpectedObjectTypeToCompareTo = "Object must be of type Symbol or string.";
501 
502  [MethodImpl(MethodImplOptions.AggressiveInlining)]
503  public static string SecurityTypeNotImplementedYet(SecurityType securityType)
504  {
505  return Invariant($"The security type has not been implemented yet: {securityType}");
506  }
507 
508  [MethodImpl(MethodImplOptions.AggressiveInlining)]
509  public static string SecurityTypeCannotBeMapped(SecurityType securityType)
510  {
511  return Invariant($"SecurityType {securityType} can not be mapped.");
512  }
513 
514  [MethodImpl(MethodImplOptions.AggressiveInlining)]
515  public static string NoOptionTypeForUnderlying(SecurityType securityType)
516  {
517  return Invariant($"No option type exists for underlying SecurityType: {securityType}");
518  }
519 
520  [MethodImpl(MethodImplOptions.AggressiveInlining)]
521  public static string NoUnderlyingForOption(SecurityType securityType)
522  {
523  return Invariant($"No underlying type exists for option SecurityType: {securityType}");
524  }
525  }
526 
527  /// <summary>
528  /// Provides user-facing messages for the <see cref="QuantConnect.SymbolCache"/> class and its consumers or related classes
529  /// </summary>
530  public static class SymbolCache
531  {
532  [MethodImpl(MethodImplOptions.AggressiveInlining)]
533  public static string UnableToLocateTicker(string ticker)
534  {
535  return $"We were unable to locate the ticker '{ticker}'.";
536  }
537 
538  [MethodImpl(MethodImplOptions.AggressiveInlining)]
539  public static string MultipleMatchingTickersLocated(IEnumerable<string> tickers)
540  {
541  return "We located multiple potentially matching tickers. " +
542  "For custom data, be sure to append a dot followed by the custom data type name. " +
543  $"For example: 'BTC.Bitcoin'. Potential Matches: {string.Join(", ", tickers)}";
544  }
545  }
546 
547  /// <summary>
548  /// Provides user-facing messages for the <see cref="QuantConnect.SymbolRepresentation"/> class and its consumers or related classes
549  /// </summary>
550  public static class SymbolRepresentation
551  {
552  [MethodImpl(MethodImplOptions.AggressiveInlining)]
553  public static string FailedToGetMarketForTickerAndUnderlying(string ticker, string underlying)
554  {
555  return $"Failed to get market for future '{ticker}' and underlying '{underlying}'";
556  }
557 
558  [MethodImpl(MethodImplOptions.AggressiveInlining)]
559  public static string NoMarketFound(string ticker)
560  {
561  return $"No market found for '{ticker}'";
562  }
563 
564  [MethodImpl(MethodImplOptions.AggressiveInlining)]
565  public static string UnexpectedSecurityTypeForMethod(string methodName, SecurityType securityType)
566  {
567  return Invariant($"{methodName} expects symbol to be an option, received {securityType}.");
568  }
569 
570  [MethodImpl(MethodImplOptions.AggressiveInlining)]
571  public static string UnexpectedOptionRightFormatForParseOptionTickerOSI(string ticker)
572  {
573  return $"Expected 12th character to be 'C' or 'P' for OptionRight: {ticker} but was '{ticker[12]}'";
574  }
575 
576  [MethodImpl(MethodImplOptions.AggressiveInlining)]
577  public static string SecurityTypeNotImplemented(SecurityType securityType)
578  {
579  return Invariant($"Security type {securityType} not implemented");
580  }
581  }
582 
583  /// <summary>
584  /// Provides user-facing messages for the <see cref="QuantConnect.SymbolValueJsonConverter"/> class and its consumers or related classes
585  /// </summary>
586  public static class SymbolValueJsonConverter
587  {
588  public static string ConverterIsWriteOnly = "The SymbolValueJsonConverter is write-only.";
589 
590  public static string ConverterIsIntendedToBeDirectlyDecoratedInMember =
591  "The SymbolValueJsonConverter is intended to be decorated on the appropriate member directly.";
592  }
593 
594  /// <summary>
595  /// Provides user-facing messages for the <see cref="QuantConnect.Time"/> class and its consumers or related classes
596  /// </summary>
597  public static class Time
598  {
599  public static string InvalidBarSize = "barSize must be greater than TimeSpan.Zero";
600 
601  [MethodImpl(MethodImplOptions.AggressiveInlining)]
602  public static string SecurityCount(int count)
603  {
604  return $"Security Count: {count}";
605  }
606  }
607 
608  /// <summary>
609  /// Provides user-facing messages for the <see cref="QuantConnect.TradingCalendar"/> class and its consumers or related classes
610  /// </summary>
611  public static class TradingCalendar
612  {
613  [MethodImpl(MethodImplOptions.AggressiveInlining)]
614  public static string InvalidTotalDays(int totalDays)
615  {
616  return Invariant($@"Total days is negative ({
617  totalDays
618  }), indicating reverse start and end times. Check your usage of TradingCalendar to ensure proper arrangement of variables");
619  }
620  }
621  }
622 }