17 using System.Collections.Generic;
19 using System.Runtime.CompilerServices;
33 public static partial class Messages
43 [MethodImpl(MethodImplOptions.AggressiveInlining)]
44 public static string ToString(Securities.AccountEvent accountEvent)
46 return Invariant($
"Account {accountEvent.CurrencySymbol} Balance: {accountEvent.CashBalance:0.00}");
73 public static string InvalidLeverage =
"Leverage must be greater than or equal to 1.";
78 [MethodImpl(MethodImplOptions.AggressiveInlining)]
81 return Invariant($
"Null order ticket for id: {order.Id}");
88 [MethodImpl(MethodImplOptions.AggressiveInlining)]
90 decimal initialMarginRequiredForRemainderOfOrder, decimal freeMargin)
92 return Invariant($
@"Id: {order.Id}, Initial Margin: {
93 initialMarginRequiredForRemainderOfOrder.Normalize()}, Free Margin: {freeMargin.Normalize()}");
99 [MethodImpl(MethodImplOptions.AggressiveInlining)]
102 return Invariant($
"The target order margin {absDifferenceOfMargin} is less than the minimum {minimumValue}.");
109 [MethodImpl(MethodImplOptions.AggressiveInlining)]
112 return "Warning: Portfolio rebalance result ignored as it resulted in a single share trade recommendation which can generate high fees." +
113 " To disable minimum order size checks please set Settings.MinimumOrderMarginPortfolioPercentage = 0.";
120 [MethodImpl(MethodImplOptions.AggressiveInlining)]
123 return Invariant($
@"The order quantity is less than the lot size of {
124 security.SymbolProperties.LotSize} and has been rounded to zero. Target order margin {targetOrderMargin}. ");
131 [MethodImpl(MethodImplOptions.AggressiveInlining)]
133 decimal signedTargetFinalMarginValue, decimal orderFees)
135 return Invariant($
@"GetMaximumOrderQuantityForTargetBuyingPower failed to converge on the target margin: {
136 signedTargetFinalMarginValue}; the following information can be used to reproduce the issue. Total Portfolio Cash: {
137 parameters.Portfolio.Cash}; Security : {parameters.Security.Symbol.ID}; Price : {parameters.Security.Close}; Leverage: {
138 parameters.Security.Leverage}; Order Fee: {orderFees}; Lot Size: {
139 parameters.Security.SymbolProperties.LotSize}; Current Holdings: {parameters.Security.Holdings.Quantity} @ {
140 parameters.Security.Holdings.AveragePrice}; Target Percentage: %{parameters.TargetBuyingPower * 100};");
147 [MethodImpl(MethodImplOptions.AggressiveInlining)]
150 return Invariant($
@"Underlying Security: {underlying.Symbol.ID}; Underlying Price: {
151 underlying.Close}; Underlying Holdings: {underlying.Holdings.Quantity} @ {underlying.Holdings.AveragePrice};");
158 [MethodImpl(MethodImplOptions.AggressiveInlining)]
162 $
@"Margin is being adjusted in the wrong direction. Reproduce this issue with the following variables, Target Margin: {
163 targetMargin}; MarginForOneUnit: {marginForOneUnit}; Security Holdings: {security.Holdings.Quantity} @ {
164 security.Holdings.AveragePrice}; LotSize: {security.SymbolProperties.LotSize}; Price: {security.Close}; Leverage: {
165 security.Leverage}");
172 [MethodImpl(MethodImplOptions.AggressiveInlining)]
175 return Invariant($
@"Underlying Security: {underlying.Symbol.ID}; Underlying Price: {
176 underlying.Close}; Underlying Holdings: {underlying.Holdings.Quantity} @ {underlying.Holdings.AveragePrice};");
194 [MethodImpl(MethodImplOptions.AggressiveInlining)]
197 return Invariant($
"Computed zero initial margin requirement for {positionGroup.GetUserFriendlyName()}.");
203 [MethodImpl(MethodImplOptions.AggressiveInlining)]
206 return Invariant($
"The position group order quantity has been rounded to zero. Target order margin {targetOrderMargin}.");
212 [MethodImpl(MethodImplOptions.AggressiveInlining)]
216 return Invariant($
@"Failed to converge on the target margin: {targetMargin}; the following information can be used to reproduce the issue. Total Portfolio Cash: {parameters.Portfolio.Cash}; Position group: {parameters.PositionGroup.GetUserFriendlyName()}; Position group order quantity: {positionGroupQuantity} Order Fee: {orderFees}; Current Holdings: {parameters.PositionGroup.Quantity}; Target Percentage: %{parameters.TargetBuyingPower * 100};");
234 [MethodImpl(MethodImplOptions.AggressiveInlining)]
236 IEnumerable<KeyValuePair<SecurityType, string>> marketMap)
238 return Invariant($
@"No tradeable pair was found for currency {cashCurrencySymbol}, conversion rate to account currency ({
239 accountCurrency}) will be set to zero. Markets: [{string.Join(",
", marketMap.Select(x => $"{x.Key}:{x.Value}
"))}]");
246 [MethodImpl(MethodImplOptions.AggressiveInlining)]
249 return Invariant($
"Adding {symbol.Value} {symbol.ID.Market} for cash {cashCurrencySymbol} currency feed");
255 [MethodImpl(MethodImplOptions.AggressiveInlining)]
256 public static string ToString(Securities.Cash cash,
string accountCurrency)
259 var rate = cash.ConversionRate;
260 rate = rate < 1000 ? rate.RoundToSignificantDigits(5) : Math.Round(rate, 2);
261 return Invariant($
@"{cash.Symbol}: {cash.CurrencySymbol}{cash.Amount,15:0.00} @ {rate,10:0.00####} = {
262 QuantConnect.Currencies.GetCurrencySymbol(accountCurrency)}{Math.Round(cash.ValueInAccountCurrency, 2)}");
279 [MethodImpl(MethodImplOptions.AggressiveInlining)]
282 return Invariant($
"The conversion rate for {currency} is not available.");
288 [MethodImpl(MethodImplOptions.AggressiveInlining)]
289 public static string ToString(Securities.CashBook cashBook)
291 var sb =
new StringBuilder();
292 sb.AppendLine(Invariant($
"Symbol {"Quantity
",13} {"Conversion
",10} = Value in {cashBook.AccountCurrency}"));
293 foreach (var value
in cashBook.Values)
295 sb.AppendLine(value.ToString(cashBook.AccountCurrency));
297 sb.AppendLine(
"-------------------------------------------------");
298 sb.AppendLine(Invariant($
@"CashBook Total Value: {
299 QuantConnect.Currencies.GetCurrencySymbol(cashBook.AccountCurrency)}{
300 Math.Round(cashBook.TotalValueInAccountCurrency, 2).ToStringInvariant()}"));
302 return sb.ToString();
308 [MethodImpl(MethodImplOptions.AggressiveInlining)]
311 return $
"This cash symbol ({symbol}) was not found in your cash book.";
318 [MethodImpl(MethodImplOptions.AggressiveInlining)]
321 return $
"Failed to remove the cash book record for symbol {symbol}";
333 public static string UnsupportedLeverage =
"CashBuyingPowerModel does not allow setting leverage. Cash accounts have no leverage.";
339 $
@"The {nameof(CashBuyingPowerModel)} does not require '{
340 nameof(Securities.CashBuyingPowerModel.GetMaximumOrderQuantityForDeltaBuyingPower)}'.";
350 public static string InvalidSecurity = $
"The security type must be {nameof(SecurityType.Crypto)}or {nameof(SecurityType.Forex)}.";
356 [MethodImpl(MethodImplOptions.AggressiveInlining)]
359 return $
@"The '{security.Symbol.Value}' security is not supported by this cash model. Currently only {
360 nameof(SecurityType.Crypto)} and {nameof(SecurityType.Forex)} are supported.";
367 [MethodImpl(MethodImplOptions.AggressiveInlining)]
371 return Invariant($
@"Your portfolio holds {totalQuantity.Normalize()} {
372 baseCurrency.BaseCurrency.Symbol}, {openOrdersReservedQuantity.Normalize()} {
373 baseCurrency.BaseCurrency.Symbol} of which are reserved for open orders, but your Sell order is for {
374 orderQuantity.Normalize()} {baseCurrency.BaseCurrency.Symbol
375 }. Cash Modeling trading does not permit short holdings so ensure you only sell what you have, including any additional open orders.");
381 [MethodImpl(MethodImplOptions.AggressiveInlining)]
383 decimal openOrdersReservedQuantity, decimal orderQuantity,
IBaseCurrencySymbol baseCurrency, Securities.Security security,
386 return Invariant($
@"Your portfolio holds {totalQuantity.Normalize()} {
387 security.QuoteCurrency.Symbol}, {openOrdersReservedQuantity.Normalize()} {
388 security.QuoteCurrency.Symbol} of which are reserved for open orders, but your Buy order is for {
389 order.AbsoluteQuantity.Normalize()} {baseCurrency.BaseCurrency.Symbol}. Your order requires a total value of {
390 orderQuantity.Normalize()} {security.QuoteCurrency.Symbol}, but only a total value of {
391 Math.Abs(maximumQuantity).Normalize()} {security.QuoteCurrency.Symbol} is available.");
398 [MethodImpl(MethodImplOptions.AggressiveInlining)]
401 return Invariant($
@"The internal cash feed required for converting {security.QuoteCurrency.Symbol} to {
402 portfolio.CashBook.AccountCurrency} does not have any data yet (or market may be closed).");
408 [MethodImpl(MethodImplOptions.AggressiveInlining)]
411 return $
@"The contract multiplier for the {
412 security.Symbol.Value} security is zero. The symbol properties database may be out of date.";
418 [MethodImpl(MethodImplOptions.AggressiveInlining)]
421 return Invariant($
@"The order quantity is less than the lot size of {
422 security.SymbolProperties.LotSize} and has been rounded to zero.");
429 [MethodImpl(MethodImplOptions.AggressiveInlining)]
432 return Invariant($
"Target order value {targetOrderValue}. Order fees {orderFees}. Order quantity {orderQuantity}.");
439 [MethodImpl(MethodImplOptions.AggressiveInlining)]
441 decimal orderFees, Securities.Security security)
443 return Invariant($
@"GetMaximumOrderQuantityForTargetBuyingPower failed to converge to target order value {
444 targetOrderValue}. Current order value is {currentOrderValue}. Order quantity {orderQuantity}. Lot size is {
445 security.SymbolProperties.LotSize}. Order fees {orderFees}. Security symbol {security.Symbol}");
469 "DynamicSecurityData is a view of the SecurityCache. It is readonly, properties can not be set";
474 [MethodImpl(MethodImplOptions.AggressiveInlining)]
477 return $
"Property with name '{name}' does not exist.";
483 [MethodImpl(MethodImplOptions.AggressiveInlining)]
486 return $
"Expected a list with type '{type.GetBetterTypeName()}' but found type '{data.GetType().GetBetterTypeName()}";
498 [MethodImpl(MethodImplOptions.AggressiveInlining)]
501 return Invariant($
"Invalid SecurityType: {security.Type}");
519 $
@"This method purposefully throws as a proof that a test does not depend on {
520 nameof(ICurrencyConverter)}. If this exception is encountered, it means the test DOES depend on {
521 nameof(ICurrencyConverter)} and should be properly updated to use a real implementation of {nameof(ICurrencyConverter)}.";
532 [MethodImpl(MethodImplOptions.AggressiveInlining)]
535 return $
"Seeded security: {seedData.Symbol.Value}: {seedData.GetType()} {seedData.Value}";
541 [MethodImpl(MethodImplOptions.AggressiveInlining)]
544 return $
"Unable to seed security: {security.Symbol.Value}";
550 [MethodImpl(MethodImplOptions.AggressiveInlining)]
553 return $
"Could not seed price for security {security.Symbol}";
566 $
"The {nameof(Securities.IdentityCurrencyConverter)} can only handle CashAmounts in units of the account currency";
578 "ForUnderlying is only invokable for IDerivativeSecurity (Option|Future)";
589 [MethodImpl(MethodImplOptions.AggressiveInlining)]
590 public static string ToString(Securities.LocalMarketHours instance)
592 if (instance.IsClosedAllDay)
594 return "Closed All Day";
597 if (instance.IsOpenAllDay)
599 return "Open All Day";
602 return Invariant($
"{instance.DayOfWeek}: {string.Join(" |
", instance.Segments)}");
615 "ForUnderlying is only invokable for IDerivativeSecurity (Option|Future)";
627 "Future.Usa market type is no longer supported as we mapped each ticker to its actual exchange. " +
628 "Please find your specific market in the symbol-properties database.";
634 [MethodImpl(MethodImplOptions.AggressiveInlining)]
636 IEnumerable<Securities.SecurityDatabaseKey> availableKeys =
null)
639 if (availableKeys !=
null)
641 keys =
" Available keys: " +
string.Join(
", ", availableKeys);
644 return $
"Unable to locate exchange hours for {key}.{keys}";
650 [MethodImpl(MethodImplOptions.AggressiveInlining)]
653 return $
"Suggested market based on the provided ticker 'Market.{market.ToUpperInvariant()}'.";
680 [MethodImpl(MethodImplOptions.AggressiveInlining)]
681 public static string ToString(Securities.MarketHoursSegment instance)
683 return $
"{instance.State}: {instance.Start.ToStringInvariant(null)}-{instance.End.ToStringInvariant(null)}";
696 [MethodImpl(MethodImplOptions.AggressiveInlining)]
699 return $
"Two different types were detected trying to register the same type name: {existingType} - {type}";
722 "Security.SetLocalTimeKeeper(LocalTimeKeeper) must be called in order to use the LocalTime property.";
743 [MethodImpl(MethodImplOptions.AggressiveInlining)]
746 return $
"The specified key was not in the expected format: {key}";
752 [MethodImpl(MethodImplOptions.AggressiveInlining)]
753 public static string ToString(Securities.SecurityDatabaseKey instance)
755 return Invariant($
"{instance.SecurityType}-{instance.Market}-{instance.Symbol}");
767 [MethodImpl(MethodImplOptions.AggressiveInlining)]
770 return $
"No security definitions data loaded from file: {securitiesDefinitionKey}";
793 [MethodImpl(MethodImplOptions.AggressiveInlining)]
796 return $
"Did not find last market open for {localDateTime}. IsMarketAlwaysOpen: {isMarketAlwaysOpen}";
808 [MethodImpl(MethodImplOptions.AggressiveInlining)]
809 public static string ToString(Securities.SecurityHolding instance)
811 return Invariant($
"{instance.Symbol.Value}: {instance.Quantity} @ {instance.AveragePrice}");
823 [MethodImpl(MethodImplOptions.AggressiveInlining)]
826 return Invariant($
@"This asset symbol ({
827 symbol}) was not found in your security list. Please add this security or check it exists before using it with 'Securities.ContainsKey(""{
828 QuantConnect.SymbolCache.GetTicker(symbol)}"")'");
834 [MethodImpl(MethodImplOptions.AggressiveInlining)]
837 return Invariant($
"Unable to overwrite existing Security: {symbol}");
851 "Portfolio object is an adaptor for Security Manager. To add a new asset add the required data during initialization.";
868 "Cannot change AccountCurrency after adding a Security. Please move SetAccountCurrency() before AddSecurity().";
875 "Cannot change AccountCurrency after setting cash. Please move SetAccountCurrency() before SetCash().";
881 [MethodImpl(MethodImplOptions.AggressiveInlining)]
884 return $
"account currency has already been set to {cashBook.AccountCurrency}. Will ignore new value {newAccountCurrency}";
890 [MethodImpl(MethodImplOptions.AggressiveInlining)]
893 return $
"setting account currency to {accountCurrency}";
900 [MethodImpl(MethodImplOptions.AggressiveInlining)]
903 return Invariant($
"Total margin information: TotalMarginUsed: {totalMarginUsed:F2}, MarginRemaining: {marginRemaining:F2}");
909 [MethodImpl(MethodImplOptions.AggressiveInlining)]
912 return Invariant($
"Order request margin information: MarginUsed: {marginUsed:F2}, MarginRemaining: {marginRemaining:F2}");
924 [MethodImpl(MethodImplOptions.AggressiveInlining)]
927 return $
"Symbol could not be found in the Symbol Properties Database: {symbol.Value}";
940 "This operation is not allowed in Initialize or during warm up: CancelOpenOrders. Please move this code to the OnWarmupFinished() method.";
945 [MethodImpl(MethodImplOptions.AggressiveInlining)]
948 return Invariant($
"Canceled by CancelOpenOrders() at {time:o}");
954 [MethodImpl(MethodImplOptions.AggressiveInlining)]
957 return Invariant($
"Unable to locate ticket for order: {orderId}");
963 [MethodImpl(MethodImplOptions.AggressiveInlining)]
966 return Invariant($
"Order did not fill within {fillTimeout.TotalSeconds} seconds.");
978 public static string InvalidLotSize =
"SymbolProperties LotSize can not be less than or equal to 0";
993 [MethodImpl(MethodImplOptions.AggressiveInlining)]
994 public static string ToString(Securities.SymbolProperties instance)
996 var marketTicker =
",";
997 var minimumOrderSize = marketTicker;
998 var priceMagnifier = marketTicker;
999 if (!
string.IsNullOrEmpty(instance.MarketTicker))
1001 marketTicker = $
",{instance.MarketTicker}";
1003 if (instance.MinimumOrderSize !=
null)
1005 minimumOrderSize = Invariant($
",{instance.MinimumOrderSize}");
1007 if (instance.PriceMagnifier != 1)
1009 priceMagnifier = Invariant($
",{instance.PriceMagnifier}");
1012 return Invariant($
@"{instance.Description},{instance.QuoteCurrency},{instance.ContractMultiplier},{
1013 instance.MinimumPriceVariation},{instance.LotSize}{marketTicker}{minimumOrderSize}{priceMagnifier}");
1027 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1030 return $
"Encountered duplicate key while processing file: {file}. Key: {key}";
1036 [MethodImpl(MethodImplOptions.AggressiveInlining)]
1039 return $
"Unable to locate symbol properties file: {file}";