chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:02:50 +08:00
commit 0fc60fdcb1
5008 changed files with 910633 additions and 0 deletions
@@ -0,0 +1,63 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Runtime.CompilerServices;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Algorithm.Framework.Alphas.Analysis"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Algorithm.Framework.Alphas.Analysis.InsightManager"/> class and its consumers or related classes
/// </summary>
public static class InsightManager
{
/// <summary>
/// String message saying extraAnalysisPeriodRatio must be greater than or equal to zero
/// </summary>
public static string InvalidExtraAnalysisPeriodRatio = "extraAnalysisPeriodRatio must be greater than or equal to zero.";
/// <summary>
/// Returns a string message warning the user of an insight with zero initial price
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ZeroInitialPriceValue(DateTime frontierTimeUtc, Algorithm.Framework.Alphas.Insight insight)
{
return Invariant($"InsightManager.Step(): Warning {frontierTimeUtc} UTC: insight {insight} initial price value is 0");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="ReadOnlySecurityValuesCollection"/> class and its consumers or related classes
/// </summary>
public static class ReadOnlySecurityValuesCollection
{
/// <summary>
/// Returns a string message saying no SecurityValues were found for the given symbol
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SecurityValuesForSymbolNotFound(QuantConnect.Symbol symbol)
{
return Invariant($"SecurityValues for symbol {symbol} was not found");
}
}
}
}
@@ -0,0 +1,147 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Runtime.CompilerServices;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Algorithm.Framework.Alphas"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Algorithm.Framework.Alphas.Insight"/> class and its consumers or related classes
/// </summary>
public static class Insight
{
/// <summary>
/// Returns a string message saying: Insight barCount must be grater than zero
/// </summary>
public static string InvalidBarCount = "Insight barCount must be greater than zero.";
/// <summary>
/// Returns a string message saying: Insight period must be greater than or equal to 1 second
/// </summary>
public static string InvalidPeriod = "Insight period must be greater than or equal to 1 second.";
/// <summary>
/// Returns a string message saying: Insight closeTimeUtc must be greater than generatedTimeUtc
/// </summary>
public static string InvalidCloseTimeUtc = "Insight closeTimeUtc must be greater than generatedTimeUtc.";
/// <summary>
/// Returns a string message saying: Insight closeTimeLocal must not be in the past
/// </summary>
public static string InvalidCloseTimeLocal = "Insight closeTimeLocal must not be in the past.";
/// <summary>
/// Returns a string message saying the Insight's GeneratedTimeUtc property must be set before calling SetPeriodAndCloseTime
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GeneratedTimeUtcNotSet(Algorithm.Framework.Alphas.Insight insight)
{
return Invariant($@"The insight's '{nameof(insight.GeneratedTimeUtc)}' property must be set before calling {
nameof(insight.SetPeriodAndCloseTime)}.");
}
/// <summary>
/// Returns a string message saying it was impossible to set group id on the given insight because it has already
/// been assigned to a group
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InsightAlreadyAssignedToAGroup(Algorithm.Framework.Alphas.Insight insight)
{
return Invariant($"Unable to set group id on insight {insight} because it has already been assigned to a group.");
}
/// <summary>
/// Parses the given insight into a string containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Algorithm.Framework.Alphas.Insight insight)
{
var str = Invariant($"{insight.Id:N}: {insight.Symbol} {insight.Type} {insight.Direction} within {insight.Period}");
if (insight.Magnitude.HasValue)
{
str += Invariant($" by {insight.Magnitude.Value}%");
}
if (insight.Confidence.HasValue)
{
str += Invariant($" with {Math.Round(100 * insight.Confidence.Value, 1)}% confidence");
}
if (insight.Weight.HasValue)
{
str += Invariant($" and {Math.Round(100 * insight.Weight.Value, 1)}% weight");
}
if (!string.IsNullOrEmpty(insight.Tag))
{
str += Invariant($": {insight.Tag}");
}
return str;
}
/// <summary>
/// Parses a short insight into a string containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ShortToString(Algorithm.Framework.Alphas.Insight insight)
{
var str = Invariant($"{insight.Symbol.Value} {insight.Type} {insight.Direction} {insight.Period}");
if (insight.Magnitude.HasValue)
{
str += Invariant($" M:{insight.Magnitude.Value}%");
}
if (insight.Confidence.HasValue)
{
str += Invariant($" C:{Math.Round(100 * insight.Confidence.Value, 1)}%");
}
if (insight.Weight.HasValue)
{
str += Invariant($" W:{Math.Round(100 * insight.Weight.Value, 1)}%");
}
if (!string.IsNullOrEmpty(insight.Tag))
{
str += Invariant($". {insight.Tag}");
}
return str;
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Algorithm.Framework.Alphas.InsightScore"/> class and its consumers or related classes
/// </summary>
public static class InsightScore
{
/// <summary>
/// Parses an InsightScore object into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Algorithm.Framework.Alphas.InsightScore insightScore)
{
return Invariant($@"Direction: {Math.Round(100 * insightScore.Direction, 2)} Magnitude: {
Math.Round(100 * insightScore.Magnitude, 2)}");
}
}
}
}
@@ -0,0 +1,91 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Interfaces;
using QuantConnect.Securities.Positions;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Algorithm.Framework.Portfolio"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Algorithm.Framework.Portfolio.PortfolioTarget"/> class and its consumers or related classes
/// </summary>
public static class PortfolioTarget
{
/// <summary>
/// Returns a string message saying the portfolio target percent is invalid
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidTargetPercent(IAlgorithm algorithm, decimal percent)
{
return Invariant($@"The portfolio target percent: {
percent}, does not comply with the current '{FormatCodeRoot("Settings")}.{FormatCode("MaxAbsolutePortfolioTargetPercentage")}': {
algorithm.Settings.MaxAbsolutePortfolioTargetPercentage} or '{FormatCodeRoot("Settings")}.{FormatCode("MinAbsolutePortfolioTargetPercentage")}': {
algorithm.Settings.MinAbsolutePortfolioTargetPercentage}. Skipping");
}
/// <summary>
/// Returns a string message saying the given symbol was not found in the portfolio
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SymbolNotFound(QuantConnect.Symbol symbol)
{
return Invariant($"{symbol} not found in portfolio. Request this data when initializing the algorithm.");
}
/// <summary>
/// Returns a string message saying it was impossible to compute the order quantity of the given symbol. It also
/// explains the reason why it was impossible
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnableToComputeOrderQuantityDueToNullResult(QuantConnect.Symbol symbol, GetMaximumLotsResult result)
{
return Invariant($"Unable to compute order quantity of {symbol}. Reason: {result.Reason} Returning null.");
}
/// <summary>
/// Parses the given portfolio target into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Algorithm.Framework.Portfolio.PortfolioTarget portfolioTarget)
{
var str = Invariant($"{portfolioTarget.Symbol}: {portfolioTarget.Quantity.Normalize()}");
if (!string.IsNullOrEmpty(portfolioTarget.Tag))
{
str += $" ({portfolioTarget.Tag})";
}
return str;
}
/// <summary>
/// Returns a string message saying the insight direction is invalid for the given symbol
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidInsightDirection(QuantConnect.Symbol symbol, InsightDirection insightDirection)
{
return Invariant($"Invalid insight direction {insightDirection} for symbol: {symbol}.");
}
}
}
}
+120
View File
@@ -0,0 +1,120 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Algorithm"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Algorithm.QCAlgorithm"/> class and its consumers or related classes
/// </summary>
public static class QCAlgorithm
{
/// <summary>
/// Returns a string message saying the time zone cannot be changed after the algorithm is running
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SetTimeZoneAlreadyRunning()
{
return $"{AlgorithmPrefix()}.{FormatCode("SetTimeZone")}(): Cannot change time zone after algorithm running.";
}
/// <summary>
/// Returns a string message saying the benchmark cannot be changed after the algorithm is initialized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SetBenchmarkAlreadyInitialized()
{
return $"{AlgorithmPrefix()}.{FormatCode("SetBenchmark")}(): Cannot change Benchmark after algorithm initialized.";
}
/// <summary>
/// Returns a string message saying the account currency cannot be changed after the algorithm is initialized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SetAccountCurrencyAlreadyInitialized()
{
return $"{AlgorithmPrefix()}.{FormatCode("SetAccountCurrency")}(): Cannot change AccountCurrency after algorithm initialized.";
}
/// <summary>
/// Returns a string message saying the cash cannot be changed after the algorithm is initialized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SetCashAlreadyInitialized()
{
return $"{AlgorithmPrefix()}.{FormatCode("SetCash")}(): Cannot change cash available after algorithm initialized.";
}
/// <summary>
/// Returns a string message saying the start date cannot be changed after the algorithm is initialized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SetStartDateAlreadyInitialized()
{
return $"{AlgorithmPrefix()}.{FormatCode("SetStartDate")}(): Cannot change start date after algorithm initialized.";
}
/// <summary>
/// Returns a string message saying the end date cannot be changed after the algorithm is initialized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SetEndDateAlreadyInitialized()
{
return $"{AlgorithmPrefix()}.{FormatCode("SetEndDate")}(): Cannot change end date after algorithm initialized.";
}
/// <summary>
/// Returns a string message saying SetWarmup cannot be used after the algorithm is initialized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SetWarmupAlreadyInitialized()
{
return $"{AlgorithmPrefix()}.{FormatCode("SetWarmup")}(): This method cannot be used after algorithm initialized";
}
/// <summary>
/// Returns a string message saying the first argument to AddData must be a custom data class
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string AddDataInvalidPyObjectType(string repr)
{
return $"{AlgorithmPrefix()}.{FormatCode("AddData")}(): the first argument must be a custom data type (a Python class deriving from {FormatCode("PythonData")} or a CLR {FormatCode("BaseData")} type), but received {repr}. " +
$"To subscribe to built-in asset classes use, for example, {FormatCode("AddEquity")} or {FormatCode("AddCrypto")}.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="AlgorithmFactory.Python.Wrappers.AlgorithmPythonWrapper"/> class
/// and its consumers or related classes
/// </summary>
public static class AlgorithmPythonWrapper
{
/// <summary>
/// Returns a string message saying OnMarginCall must return a non-empty list of SubmitOrderRequest
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string OnMarginCallMustReturnNonEmptyList()
{
return $"{FormatCode("OnMarginCall")} must return a non-empty list of SubmitOrderRequest";
}
}
}
}
+35
View File
@@ -0,0 +1,35 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Benchmarks"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Benchmarks.FuncBenchmark"/> class and its consumers or related classes
/// </summary>
public static class FuncBenchmark
{
/// <summary>
/// String message saying it was impossible to convert the Python function to a benchmark function
/// </summary>
public static string UnableToConvertPythonFunctionToBenchmarkFunction =
"Unable to convert Python function to benchmark function, please ensure the function supports Datetime input and decimal output";
}
}
}
+663
View File
@@ -0,0 +1,663 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Runtime.CompilerServices;
using QuantConnect.Brokerages;
using QuantConnect.Orders;
using static QuantConnect.StringExtensions;
using System.Collections.Generic;
using QuantConnect.Orders.TimeInForces;
using System.Globalization;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Brokerages"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.DefaultBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class DefaultBrokerageModel
{
/// <summary>
/// String message saying: MarketOnOpen orders are not supported for futures and future options
/// </summary>
public static string UnsupportedMarketOnOpenOrdersForFuturesAndFutureOptions =
"MarketOnOpen orders are not supported for futures and future options.";
/// <summary>
/// String message saying: There is no data for this symbol yet
/// </summary>
public static string NoDataForSymbol =
"There is no data for this symbol yet, please check the security.HasData flag to ensure there is at least one data point.";
/// <summary>
/// String message saying: Brokerage does not support update. You must cancel and re-create instead
/// </summary>
public static string OrderUpdateNotSupported = "Brokerage does not support update. You must cancel and re-create instead.";
/// <summary>
/// Retunrns a string message saying the type of the given security is not supported by the given brokerage
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedSecurityType(IBrokerageModel brokerageModel, Securities.Security security)
{
return Invariant($"The {brokerageModel.GetType().Name} does not support {security.Type} security type.");
}
/// <summary>
/// Returns a string message saying the given brokerage does not support updating the quantity of Cross Zero orders
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedCrossZeroOrderUpdate(IBrokerageModel brokerageModel)
{
return Invariant($"Unfortunately, the {brokerageModel.GetType().Name} brokerage model does not support updating the quantity of Cross Zero Orders.");
}
/// <summary>
/// Returns a string message saying the type of the given security is invalid for the given brokerage GetFillModel() method
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidSecurityTypeToGetFillModel(IBrokerageModel brokerageModel, Securities.Security security)
{
return Invariant($"{brokerageModel.GetType().Name}.GetFillModel: Invalid security type {security.Type}");
}
/// <summary>
/// Returns a string message saying the quantity given was invalid for the given security
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidOrderQuantity(Securities.Security security, decimal quantity)
{
return Invariant($@"The minimum order size (in quote currency) for {security.Symbol.Value} is {
security.SymbolProperties.MinimumOrderSize}. Order quantity was {quantity}.");
}
/// <summary>
/// Returns a string message saying the given order size (quantity * price) was invalid for the given security
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidOrderSize(Securities.Security security, decimal quantity, decimal price)
{
return Invariant($@"The minimum order size (in quote currency) for {security.Symbol.Value} is {security.SymbolProperties.MinimumOrderSize}. Order size was {quantity * price}.");
}
/// <summary>
/// Returns a string message saying the type of the given order is unsupported by the given brokerage model. It also
/// mentions the supported order types
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedOrderType(IBrokerageModel brokerageModel, Orders.Order order, IEnumerable<OrderType> supportedOrderTypes)
{
return Invariant($"The {brokerageModel.GetType().Name} does not support {order.Type} order type. Only supports [{string.Join(',', supportedOrderTypes)}]");
}
/// <summary>
/// Returns a string message saying the Time In Force of the given order is unsupported by the given brokerage
/// model
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedTimeInForce(IBrokerageModel brokerageModel, Orders.Order order)
{
return Invariant($@"The {brokerageModel.GetType().Name} does not support {
order.TimeInForce.GetType().Name} time in force.");
}
/// <summary>
/// Returns a string message saying the type of the given security is invalid
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidSecurityTypeForLeverage(Securities.Security security)
{
return Invariant($"Invalid security type: {security.Type}");
}
/// <summary>
/// Returns a message indicating that the specified order type is not supported for orders that cross the zero holdings threshold.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedCrossZeroByOrderType(IBrokerageModel brokerageModel, OrderType orderType)
{
return Invariant($"Order type '{orderType}' is not supported for orders that cross the zero holdings threshold in the {brokerageModel.GetType().Name}. This means you cannot change a position from positive to negative or vice versa using this order type. Please close the existing position first.");
}
/// <summary>
/// Returns a message indicating that the specified order type cannot be updated quantity using the given brokerage model.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedUpdateQuantityOrder(IBrokerageModel brokerageModel, OrderType orderType)
{
return Invariant($"Order type '{orderType}' is not supported to update quantity in the {brokerageModel.GetType().Name}.");
}
/// <summary>
/// Builds a descriptive error message when a <see cref="OrderType.MarketOnOpen"/>
/// order is submitted outside the valid submission window.
/// </summary>
/// <param name="windowStart">The start of the valid submission window (typically evening of the prior day).</param>
/// <param name="windowEnd">The end of the valid submission window (typically morning of the next day).</param>
/// <returns>
/// A formatted string describing why the order is not valid at the current time,
/// including the allowed submission window and suggested fixes.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedMarketOnOpenOrderTime(
in TimeOnly windowStart,
in TimeOnly windowEnd)
{
return Invariant($"MarketOnOpen submission time is invalid. Valid local times are {windowStart: hh\\:mm}{windowEnd: hh\\:mm}. Consider setting {FormatCode(nameof(AlgorithmSettings.DailyPreciseEndTime))} = false or using {FormatCodeRoot(nameof(Schedule))}.{FormatCode(nameof(Schedule.On))}.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.AlpacaBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class AlpacaBrokerageModel
{
/// <summary>
/// Returns a message indicating that the specified order type is not supported for trading outside
/// regular hours by the given brokerage model.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TradingOutsideRegularHoursNotSupported(IBrokerageModel brokerageModel, OrderType orderType, TimeInForce timeInForce)
{
return Invariant($"The {brokerageModel.GetType().Name} does not support {orderType} orders with {timeInForce} TIF outside regular hours. ") +
Invariant($"Only {OrderType.Limit} orders with {TimeInForce.Day} TIF are supported outside regular trading hours.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.AlphaStreamsBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class AlphaStreamsBrokerageModel
{
/// <summary>
/// String message saying: The Alpha Streams brokerage does not currently support Cash trading
/// </summary>
public static string UnsupportedAccountType = "The Alpha Streams brokerage does not currently support Cash trading.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.AxosClearingBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class AxosBrokerageModel
{
/// <summary>
/// Returns a string message saying the order quantity must be Integer. It also contains
/// the quantity of the given order
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NonIntegerOrderQuantity(Orders.Order order)
{
return Invariant($"Order Quantity must be Integer, but provided {order.Quantity}.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.BinanceBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class BinanceBrokerageModel
{
/// <summary>
/// Returns a string message saying the type of the given order is unsupported for the symbol of the given
/// security
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedOrderTypeForSecurityType(Orders.Order order, Securities.Security security)
{
return Invariant($"{order.Type} orders are not supported for this symbol ${security.Symbol}");
}
/// <summary>
/// Returns a string message saying the type of the given order is unsupported for the symbol of the given
/// security. The message also contains a link to the supported order types in Binance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedOrderTypeWithLinkToSupportedTypes(string baseApiEndpoint, Orders.Order order, Securities.Security security)
{
return Invariant($@"{order.Type} orders are not supported for this symbol. Please check '{baseApiEndpoint}/exchangeInfo?symbol={security.SymbolProperties.MarketTicker}' to see supported order types.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.BinanceUSBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class BinanceUSBrokerageModel
{
/// <summary>
/// String message saying: The Binance.US brokerage does not currently support Margin trading
/// </summary>
public static string UnsupportedAccountType = "The Binance.US brokerage does not currently support Margin trading.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.BrokerageMessageEvent"/> class and its consumers or related classes
/// </summary>
public static class BrokerageMessageEvent
{
/// <summary>
/// String message saying: Disconnect
/// </summary>
public static string DisconnectCode = "Disconnect";
/// <summary>
/// String message saying: Reconnect
/// </summary>
public static string ReconnectCode = "Reconnect";
/// <summary>
/// Parses a given BrokerageMessageEvent object into a string containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Brokerages.BrokerageMessageEvent messageEvent)
{
return Invariant($"{messageEvent.Type} - Code: {messageEvent.Code} - {messageEvent.Message}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.DefaultBrokerageMessageHandler"/> class and its consumers or related classes
/// </summary>
public static class DefaultBrokerageMessageHandler
{
/// <summary>
/// String message saying: Brokerage Error
/// </summary>
public static string BrokerageErrorContext = "Brokerage Error";
/// <summary>
/// String message saying: DefaultBrokerageMessageHandler.Handle(): Disconnected
/// </summary>
public static string Disconnected = "DefaultBrokerageMessageHandler.Handle(): Disconnected.";
/// <summary>
/// String message saying: DefaultBrookerageMessageHandler.Handle(): Reconnected
/// </summary>
public static string Reconnected = "DefaultBrokerageMessageHandler.Handle(): Reconnected.";
/// <summary>
/// String message saying: DefaultBrokerageMessageHandler.Handle(): Disconnect when exchanges are closed,
/// checking back before exchange open
/// </summary>
public static string DisconnectedWhenExchangesAreClosed =
"DefaultBrokerageMessageHandler.Handle(): Disconnect when exchanges are closed, checking back before exchange open.";
/// <summary>
/// String message saying: DefaultBrokerageMessageHandler.Handle(): Still disconnected, goodbye
/// </summary>
public static string StillDisconnected = "DefaultBrokerageMessageHandler.Handle(): Still disconnected, goodbye.";
/// <summary>
/// String message saying: Brokerage Disconnect
/// </summary>
public static string BrokerageDisconnectedShutDownContext = "Brokerage Disconnect";
/// <summary>
/// Returns a string message with basic information about the given message event
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string BrokerageInfo(Brokerages.BrokerageMessageEvent messageEvent)
{
return $"Brokerage Info: {messageEvent.Message}";
}
/// <summary>
/// Returns a string message warning from the given message event
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string BrokerageWarning(Brokerages.BrokerageMessageEvent messageEvent)
{
return $"Brokerage Warning: {messageEvent.Message}";
}
/// <summary>
/// Returns a string message saying the brokerage is disconnected when exchanges are open and that it's
/// trying to reconnect for the given reconnection timeout minutes
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string DisconnectedWhenExchangesAreOpen(TimeSpan reconnectionTimeout)
{
return Invariant($@"DefaultBrokerageMessageHandler.Handle(): Disconnect when exchanges are open, trying to reconnect for {
reconnectionTimeout.TotalMinutes} minutes.");
}
/// <summary>
/// Returns a string message with the time until the next market open
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TimeUntilNextMarketOpen(TimeSpan timeUntilNextMarketOpen)
{
return Invariant($"DefaultBrokerageMessageHandler.Handle(): TimeUntilNextMarketOpen: {timeUntilNextMarketOpen}");
}
/// <summary>
/// Returns a string message notify about unrecognized orders that are not being observed by Lean
/// </summary>
/// <param name="brokerageOrderId">The brokerage order id.</param>
/// <returns>The string represent unrecognized message</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string IgnoreUnrecognizedOrder(string brokerageOrderId)
{
return $"Ignoring unrecognized order (BrokerId: {brokerageOrderId}). Please use 'SetBrokerageMessageHandler(...)' to set a custom brokerage message handler to optionally accept unknown orders.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.ExanteBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class ExanteBrokerageModel
{
/// <summary>
/// String message saying: Order is null
/// </summary>
public static string NullOrder = "Order is null.";
/// <summary>
/// String message saying: Price is not set
/// </summary>
public static string PriceNotSet = "Price is not set.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.FTXBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class FTXBrokerageModel
{
/// <summary>
/// String message saying: Trigger price too high, must be below current market price
/// </summary>
public static string TriggerPriceTooHigh = "Trigger price too high: must be below current market price.";
/// <summary>
/// String message saying: Trigger price too low, must be above current market price
/// </summary>
public static string TriggerPriceTooLow = "Trigger price too low: must be above current market price.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.FxcmBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class FxcmBrokerageModel
{
/// <summary>
/// String message saying: Limit Buy orders and Stop Sell orders must be below market, Limit Sell orders and Stop Buy orders
/// must be above market
/// </summary>
public static string InvalidOrderPrice =
"Limit Buy orders and Stop Sell orders must be below market, Limit Sell orders and Stop Buy orders must be above market.";
/// <summary>
/// Returns a string message saying the order quantity must be a multiple of LotSize. It also contains the security's Lot
/// Size
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidOrderQuantityForLotSize(Securities.Security security)
{
return Invariant($"The order quantity must be a multiple of {FormatCode("LotSize")}: [{security.SymbolProperties.LotSize}].");
}
/// <summary>
/// Returns a string message saying the order price is too far from the current market price
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string PriceOutOfRange(OrderType orderType, OrderDirection orderDirection, decimal orderPrice, decimal currentPrice)
{
return Invariant($@"The {orderType} {orderDirection} order price ({
orderPrice}) is too far from the current market price ({currentPrice}).");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.CoinbaseBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class CoinbaseBrokerageModel
{
/// <summary>
/// String message saying: The Coinbase brokerage does not currently support Margin trading
/// </summary>
public static string UnsupportedAccountType = "The Coinbase brokerage does not currently support Margin trading.";
/// <summary>
/// Returns a string message saying the Stop Market orders are no longer supported since the given end date
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string StopMarketOrdersNoLongerSupported(DateTime stopMarketOrderSupportEndDate)
{
return Invariant($"Stop Market orders are no longer supported since {stopMarketOrderSupportEndDate}.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.InteractiveBrokersFixModel"/> class and its consumers or related classes
/// </summary>
public static class InteractiveBrokersFixModel
{
/// <summary>
/// Returns a string message saying the given brokerage model does not support combo orders
/// that mix future options and futures legs
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedFopFutureComboOrders(Brokerages.InteractiveBrokersFixModel brokerageModel, Orders.Order order)
{
return Invariant($@"The {brokerageModel.GetType().Name} does not support {order.Type} combining future options and futures legs.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.InteractiveBrokersBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class InteractiveBrokersBrokerageModel
{
/// <summary>
/// Returns a string message saying the given brokerage model does not support order exercises
/// for index and cash-settled options
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedExerciseForIndexAndCashSettledOptions(Brokerages.InteractiveBrokersBrokerageModel brokerageModel,
Orders.Order order)
{
return Invariant($@"The {brokerageModel.GetType().Name} does not support {
order.Type} exercises for index and cash-settled options.");
}
/// <summary>
/// Returns a string message saying the given brokerage model does not support four-leg combo leg limit orders
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedFourLegComboLegLimitOrders(Brokerages.InteractiveBrokersBrokerageModel brokerageModel)
{
return Invariant($"The {brokerageModel.GetType().Name} does not support four-leg ComboLegLimit orders. Use ComboLimit orders for four-leg combinations or more.");
}
/// <summary>
/// Returns a string message containing the minimum and maximum limits for the allowable order size as well as the currency
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidForexOrderSize(decimal min, decimal max, string currency)
{
return Invariant($"The minimum and maximum limits for the allowable order size are ({min}, {max}){currency}.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.TradierBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class TradierBrokerageModel
{
/// <summary>
/// Unsupported Security Type string message
/// </summary>
public static string UnsupportedSecurityType = "This model only supports equities and options.";
/// <summary>
/// Unsupported Time In Force Type string message
/// </summary>
public static string UnsupportedTimeInForceType = $"This model only supports orders with the following time in force types: {typeof(DayTimeInForce)} and {typeof(GoodTilCanceledTimeInForce)}";
/// <summary>
/// Extended Market Hours Trading Not Supported string message
/// </summary>
public static string ExtendedMarketHoursTradingNotSupported =
"Tradier does not support extended market hours trading. Your order will be processed at market open.";
/// <summary>
/// Order Quantity Update Not Supported string message
/// </summary>
public static string OrderQuantityUpdateNotSupported = "Tradier does not support updating order quantities.";
/// <summary>
/// Open Orders Cancel On Reverse Split Symbols string message
/// </summary>
public static string OpenOrdersCancelOnReverseSplitSymbols = "Tradier Brokerage cancels open orders on reverse split symbols";
/// <summary>
/// Short Order Is GTC string message
/// </summary>
public static string ShortOrderIsGtc = "You cannot place short stock orders with GTC, only day orders are allowed";
/// <summary>
/// Sell Short Order Last Price Below 5 string message
/// </summary>
public static string SellShortOrderLastPriceBelow5 = "Sell Short order cannot be placed for stock priced below $5";
/// <summary>
/// Incorrect Order Quantity string message
/// </summary>
public static string IncorrectOrderQuantity = "Quantity should be between 1 and 10,000,000";
/// <summary>
/// Extended Market Hours Trading Not Supported Outside Extended Session string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ExtendedMarketHoursTradingNotSupportedOutsideExtendedSession(Securities.MarketHoursSegment preMarketSegment,
Securities.MarketHoursSegment postMarketSegment)
{
return "Tradier does not support explicitly placing out-of-regular-hours orders if not currently " +
$"during the pre or post market session. {preMarketSegment}. {postMarketSegment}. " +
"Only equity limit orders are allowed during extended market hours.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.TradingTechnologiesBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class TradingTechnologiesBrokerageModel
{
/// <summary>
/// Invalid Stop Market Order Price string message
/// </summary>
public static string InvalidStopMarketOrderPrice =
"StopMarket Sell orders must be below market, StopMarket Buy orders must be above market.";
/// <summary>
/// Invalid Stop Limit Order Price string message
/// </summary>
public static string InvalidStopLimitOrderPrice =
"StopLimit Sell orders must be below market, StopLimit Buy orders must be above market.";
/// <summary>
/// Invalid Stop Limit Order Limit Price string message
/// </summary>
public static string InvalidStopLimitOrderLimitPrice =
"StopLimit Buy limit price must be greater than or equal to stop price, StopLimit Sell limit price must be smaller than or equal to stop price.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.WolverineBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class WolverineBrokerageModel
{
/// <summary>
/// Returns a message for an unsupported order type in Wolverine Brokerage Model
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedOrderType(Orders.Order order)
{
return Invariant($"{order.Type} order is not supported by Wolverine. Currently, only Market Order is supported.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.WebullBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class WebullBrokerageModel
{
/// <summary>
/// Returns a message explaining that Options and IndexOptions sell orders only support Day time in force.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidTimeInForceForOptionSellOrder(Orders.Order order)
{
return Invariant($"{order.Symbol.SecurityType} sell orders only support {nameof(DayTimeInForce)} time in force, but {order.TimeInForce.GetType().Name} was specified.");
}
/// <summary>
/// Returns a message explaining that OutsideRegularTradingHours is only supported for Equity orders.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string OutsideRegularTradingHoursNotSupportedForSecurityType(Securities.Security security)
{
return Invariant($"{nameof(WebullOrderProperties.OutsideRegularTradingHours)} is only supported for {nameof(SecurityType.Equity)} orders, but {security.Type} was specified.");
}
/// <summary>
/// Returns a message explaining that Market orders are not supported outside regular trading hours.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MarketOrdersNotSupportedOutsideRegularTradingHours()
{
return Invariant($"Market orders are not supported outside regular trading hours.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.PublicBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class PublicBrokerageModel
{
/// <summary>
/// Returns a message explaining that orders for the extended market must be Limit orders with Day time-in-force.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ExtendedMarketOrderMustBeLimit(Orders.Order order)
{
return Invariant($"Orders for extended market must be of type '{nameof(OrderType.Limit)}' and with 'DAY' time-in-force, but {order.Type} was specified.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Brokerages.RBIBrokerageModel"/> class and its consumers or related classes
/// </summary>
public static class RBIBrokerageModel
{
/// <summary>
/// Returns a message for an unsupported order type in RBI Brokerage Model
/// </summary>
/// <param name="order"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedOrderType(Orders.Order order)
{
return Invariant($"{order.Type} order is not supported by RBI. Currently, only Market Order, Limit Order, StopMarket Order and StopLimit Order are supported.");
}
}
}
}
+100
View File
@@ -0,0 +1,100 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
using QuantConnect.Commands;
using QuantConnect.Orders;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Commands"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Commands.BaseCommand"/> class and its consumers or related classes
/// </summary>
public static class BaseCommand
{
/// <summary>
/// Returns a string message saying: Please provide values for: Ticker, Market and SecurityType
/// </summary>
public static string MissingValuesToGetSymbol = "Please provide values for: Ticker, Market & SecurityType";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Commands.BaseCommandHandler"/> class and its consumers or related classes
/// </summary>
public static class BaseCommandHandler
{
/// <summary>
/// Returns a string with the given command
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ExecutingCommand(ICommand command)
{
return $"Executing {command}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Commands.FileCommandHandler"/> class and its consumers or related classes
/// </summary>
public static class FileCommandHandler
{
/// <summary>
/// Returns a string message saying: Command Id is null or empty, will skip writing result file
/// </summary>
public static string NullOrEmptyCommandId = "Command Id is null or empty, will skip writing result file";
/// <summary>
/// Returns a string message saying the given commandFilePath is being read
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ReadingCommandFile(string commandFilePath)
{
return $"Reading command file {commandFilePath}";
}
/// <summary>
/// Returns a string message saying the given commandFilePath does not exists
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string CommandFileDoesNotExist(string commandFilePath)
{
return $"File {commandFilePath} does not exists";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Commands.OrderCommand"/> class and its consumers or related classes
/// </summary>
public static class OrderCommand
{
/// <summary>
/// Returns a string message with basic information about a command, such us:
/// order type, symbol, quantity and response
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string CommandInfo(OrderType orderType, QuantConnect.Symbol symbol, decimal quantity, Orders.OrderResponse response)
{
return Invariant($"{orderType} for {quantity} units of {symbol}: {response}");
}
}
}
}
+167
View File
@@ -0,0 +1,167 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Runtime.CompilerServices;
using Python.Runtime;
using QuantConnect.Exceptions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Exceptions"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Exceptions.DllNotFoundPythonExceptionInterpreter"/> class and its consumers or related classes
/// </summary>
public static class DllNotFoundPythonExceptionInterpreter
{
/// <summary>
/// Returns a string message saying the given dynamic-link library could not be found
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string DynamicLinkLibraryNotFound(string dllName, string platform)
{
return $"The dynamic-link library for {dllName} could not be found. " +
"Please visit https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/readme.md for instructions " +
$"on how to enable python support in {platform}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Exceptions.InvalidTokenPythonExceptionInterpreter"/> class and its consumers or related classes
/// </summary>
public static class InvalidTokenPythonExceptionInterpreter
{
/// <summary>
/// String message saying: invalid token
/// </summary>
public static string InvalidTokenExpectedSubstring = "invalid token";
/// <summary>
/// String message saying: are not permitted
/// </summary>
public static string NotPermittedExpectedSubstring = "are not permitted;";
/// <summary>
/// Returns a string message saying: Tring to include an invalid token/character in any statement throws s SyntaxError
/// exception. It also contains an advice to prevent that exception
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InterpretException(PythonException exception)
{
var message = "Trying to include an invalid token/character in any statement throws a SyntaxError exception. " +
"To prevent the exception, ensure no invalid token are mistakenly included (e.g: leading zero).";
var errorLine = exception.Message.GetStringBetweenChars('(', ')');
return $"{message}{Environment.NewLine} in {errorLine}{Environment.NewLine}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Exceptions.KeyErrorPythonExceptionInterpreter"/> class and its consumers or related classes
/// </summary>
public static class KeyErrorPythonExceptionInterpreter
{
/// <summary>
/// Returns a string message saying the given key does not exists in the collection and the exception that is thrown
/// in this case. It also advises the user on how to prevent this exception
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string KeyNotFoundInCollection(string key)
{
return "Trying to retrieve an element from a collection using a key that does not exist " +
$@"in that collection throws a KeyError exception. To prevent the exception, ensure that the {
key} key exist in the collection and/or that collection is not empty.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Exceptions.NoMethodMatchPythonExceptionInterpreter"/> class and its consumers or related classes
/// </summary>
public static class NoMethodMatchPythonExceptionInterpreter
{
/// <summary>
/// String message saying: No method match
/// </summary>
public static string NoMethodMatchExpectedSubstring = "No method match";
/// <summary>
/// Returns a string message saying the given method does not exists. It also contains the exception
/// thrown is this case and an advice on how to prevent it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string AttemptedToAccessMethodThatDoesNotExist(string methodName)
{
return "Trying to dynamically access a method that does not exist throws a TypeError exception. " +
$@"To prevent the exception, ensure each parameter type matches those required by the {
methodName} method. Please checkout the API documentation.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Exceptions.ScheduledEventExceptionInterpreter"/> class and its consumers or related classes
/// </summary>
public static class ScheduledEventExceptionInterpreter
{
/// <summary>
/// Returns a string message with the given event name
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ScheduledEventName(string eventName)
{
return $"In Scheduled Event '{eventName}',";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Exceptions.StackExceptionInterpreter"/> class and its consumers or related classes
/// </summary>
public static class StackExceptionInterpreter
{
/// <summary>
/// Returns a message for a Loaded Exception Interpreter
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string LoadedExceptionInterpreter(IExceptionInterpreter interpreter)
{
return $"Loaded ExceptionInterpreter: {interpreter.GetType().Name}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Exceptions.UnsupportedOperandPythonExceptionInterpreter"/> class and its consumers or related classes
/// </summary>
public static class UnsupportedOperandPythonExceptionInterpreter
{
/// <summary>
/// Unsupported Operand Type Expected substring
/// </summary>
public static string UnsupportedOperandTypeExpectedSubstring = "unsupported operand type";
/// <summary>
/// Returns a message for invalid object types for operation
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidObjectTypesForOperation(string types)
{
return $@"Trying to perform a summation, subtraction, multiplication or division between {
types} objects throws a TypeError exception. To prevent the exception, ensure that both values share the same type.";
}
}
}
}
+82
View File
@@ -0,0 +1,82 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Runtime.CompilerServices;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Indicators"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Indicators.IndicatorDataPoint"/> class and its consumers or related classes
/// </summary>
public static class IndicatorDataPoint
{
/// <summary>
/// Returns a string message saying the given type is invalid for certain object
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidObjectTypeToCompareTo(Type type)
{
return $"Object must be of type {type.GetBetterTypeName()}";
}
/// <summary>
/// Parses a IndicatorDataPoint instance into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Indicators.IndicatorDataPoint instance)
{
return Invariant($"{instance.Time.ToStringInvariant("s")} - {instance.Value}");
}
/// <summary>
/// Returns a string message saying the given method cannot be called on this type
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedMethod(string methodName)
{
return $"IndicatorDataPoint does not support the {methodName} function. This function should never be called on this type.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Indicators.RollingWindow{T}"/> class and its consumers or related classes
/// </summary>
public static class RollingWindow
{
/// <summary>
/// String message saying the rolling windows must have size of at least 1
/// </summary>
public static string InvalidSize(int minimumSize) => $"RollingWindow must have size of at least {minimumSize}.";
/// <summary>
/// String message saying no items have been removed yet from the rolling window
/// </summary>
public static string NoItemsRemovedYet = "No items have been removed yet!";
/// <summary>
/// String message saying the index must be a non-negative integer
/// </summary>
public static string IndexOutOfSizeRange = "Index must be a non-negative integer";
}
}
}
+78
View File
@@ -0,0 +1,78 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Notifications"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Notifications.NotificationEmail"/> class and its consumers or related classes
/// </summary>
public static class NotificationEmail
{
/// <summary>
/// Returns a string message saying the given email is invalid
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidEmailAddress(string email)
{
return $"Invalid email address: {email}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Notifications.NotificationFtp"/> class and its consumers or related classes
/// </summary>
public static class NotificationFtp
{
/// <summary>
/// String message saying the SSH key is missing
/// </summary>
public static string MissingSSHKey = "FTP SSH key missing for SFTP notification.";
/// <summary>
/// String message saying the password is missing
/// </summary>
public static string MissingPassword = "FTP password is missing for unsecure FTP notification.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Notifications.NotificationJsonConverter"/> class and its consumers or related classes
/// </summary>
public static class NotificationJsonConverter
{
/// <summary>
/// String message saying the write method has not been implemented and should not be called
/// </summary>
public static string WriteNotImplemented = "Not implemented, should not be called";
/// <summary>
/// String message saying the given object is unexpected
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnexpectedJsonObject(JObject jObject)
{
return $"Unexpected json object: '{jObject.ToString(Formatting.None)}'";
}
}
}
}
@@ -0,0 +1,88 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Optimizer.Objectives"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing common messages for the <see cref="Optimizer.Objectives"/> namespace classes
/// </summary>
public static class OptimizerObjectivesCommon
{
/// <summary>
/// String message saying the backtest result can not be null or empty
/// </summary>
public static string NullOrEmptyBacktestResult = "Backtest result can not be null or empty.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Optimizer.Objectives.Constraint"/> class and its consumers or related classes
/// </summary>
public static class Constraint
{
/// <summary>
/// String message saying the constraint target value is not specified
/// </summary>
public static string ConstraintTargetValueNotSpecified = "Constraint target value is not specified";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Optimizer.Objectives.ExtremumJsonConverter"/> class and its consumers or related classes
/// </summary>
public static class ExtremumJsonConverter
{
/// <summary>
/// String message saying it could not recognize target direction
/// </summary>
public static string UnrecognizedTargetDirection = "Could not recognize target direction";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Optimizer.Objectives.Objective"/> class and its consumers or related classes
/// </summary>
public static class Objective
{
/// <summary>
/// Null or empty Objective string message
/// </summary>
public static string NullOrEmptyObjective = "Objective can not be null or empty";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Optimizer.Objectives.Target"/> class and its consumers or related classes
/// </summary>
public static class Target
{
/// <summary>
/// Parses a Target object into a string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Optimizer.Objectives.Target instance)
{
if (instance.TargetValue.HasValue)
{
return $"Target: {instance.Target} TargetValue: {instance.TargetValue.Value} at: {instance.Current}";
}
return $"Target: {instance.Target} at: {instance.Current}";
}
}
}
}
@@ -0,0 +1,70 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Optimizer.Parameters"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Optimizer.Parameters.OptimizationParameterJsonConverter"/> class and its consumers or related classes
/// </summary>
public static class OptimizationParameterJsonConverter
{
/// <summary>
/// String message saying optimization parameter name is not specified
/// </summary>
public static string OptimizationParameterNotSpecified = "Optimization parameter name is not specified.";
/// <summary>
/// String message saying optimization parameter is not currently supported
/// </summary>
public static string OptimizationParameterNotSupported = "Optimization parameter is not currently supported.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="Optimizer.Parameters.OptimizationStepParameter"/> class and its consumers or related classes
/// </summary>
public static class OptimizationStepParameter
{
/// <summary>
/// String message saying the step should be great or equal than minStep
/// </summary>
public static string StepLessThanMinStep = $"step should be great or equal than minStep";
/// <summary>
/// Returns a string message saying the step range is invalid
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidStepRange(decimal min, decimal max)
{
return $"Minimum value ({min}) should be less or equal than maximum ({max})";
}
/// <summary>
/// Returns a string message saying the step should be positive value
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NonPositiveStepValue(string stepVarName, decimal value)
{
return $"{stepVarName} should be positive value; but was {value}";
}
}
}
}
+150
View File
@@ -0,0 +1,150 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
using QuantConnect.Securities;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Orders.Fees"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Fees.FeeModel"/> class and its consumers or related classes
/// </summary>
public static class FeeModel
{
/// <summary>
/// Returns a string message saying the type of the given security is unsupported
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedSecurityType(Securities.Security security)
{
return Invariant($"Unsupported security type: {security.Type}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Fees.AlphaStreamsFeeModel"/> class and its consumers or related classes
/// </summary>
public static class AlphaStreamsFeeModel
{
/// <summary>
/// Returns a string message saying the given market is unexpected
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnexpectedEquityMarket(string market)
{
return Invariant($"AlphaStreamsFeeModel(): unexpected equity Market {market}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Fees.ExanteFeeModel"/> class and its consumers or related classes
/// </summary>
public static class ExanteFeeModel
{
/// <summary>
/// Returns a string message saying the market associated with the given order symbol is unsupported
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedExchange(Orders.Order order)
{
return Invariant($"Unsupported exchange: ${order.Symbol.ID.Market}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Fees.InteractiveBrokersFeeModel"/> class and its consumers or related classes
/// </summary>
public static class InteractiveBrokersFeeModel
{
/// <summary>
/// Returns a string message saying the given option market was unexpected
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnexpectedOptionMarket(string market)
{
return Invariant($"InteractiveBrokersFeeModel(): unexpected option Market {market}");
}
/// <summary>
/// Returns a string message saying the given future market was unexpected
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnexpectedFutureMarket(string market)
{
return Invariant($"InteractiveBrokersFeeModel(): unexpected future Market {market}");
}
/// <summary>
/// Returns a string message saying the given equity market was unexpected
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnexpectedEquityMarket(string market)
{
return Invariant($"InteractiveBrokersFeeModel(): unexpected equity Market {market}");
}
/// <summary>
/// Returns a string message saying the type of the given security was unsupported
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnitedStatesFutureFeesUnsupportedSecurityType(Securities.Security security)
{
return Invariant($"InteractiveBrokersFeeModel.UnitedStatesFutureFees(): Unsupported security type: {security.Type}");
}
/// <summary>
/// Returns a string message saying the type of the given security was unsupported
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string EUREXFutureFeesUnsupportedSecurityType(Securities.Security security)
{
return Invariant($"InteractiveBrokersFeeModel.EUREXFutureFees(): Unsupported security type: {security.Type}");
}
/// <summary>
/// Returns a string message saying the quote currency of the given security was
/// unexpected for Hong Kong futures exchange
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string HongKongFutureFeesUnexpectedQuoteCurrency(Securities.Security security)
{
return Invariant($"Unexpected quote currency {security.QuoteCurrency.Symbol} for Hong Kong futures exchange");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Fees.TDAmeritradeFeeModel"/> class and its consumers or related classes
/// </summary>
public static class TDAmeritradeFeeModel
{
/// <summary>
/// Returns a string message for unsupported security types in TDAmeritradeFeeModel
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnsupportedSecurityType(SecurityType securityType)
{
return $"TDAmeritradeFeeModel doesn't return correct fee model for SecurityType = {nameof(securityType)}";
}
}
}
}
+210
View File
@@ -0,0 +1,210 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using QuantConnect.Data.Market;
using QuantConnect.Orders;
using QuantConnect.Orders.Fills;
using QuantConnect.Securities;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Orders.Fills"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Fills.FillModel"/> class and its consumers or related classes
/// </summary>
public static class FillModel
{
/// <summary>
/// Returns a string message warning saying the order was filled at stale price
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledAtStalePrice(Securities.Security security, Prices prices)
{
return Invariant($"Warning: fill at stale price ({prices.EndTime.ToStringInvariant()} {security.Exchange.TimeZone})");
}
/// <summary>
/// Returns a string message saying the market never closes for the given symbol, and that an order of the given
/// type cannot be submitted
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MarketNeverCloses(Securities.Security security, OrderType orderType)
{
return Invariant($"Market never closes for this symbol {security.Symbol}, can no submit a {nameof(orderType)} order.");
}
/// <summary>
/// Returns a string message containing the given subscribedTypes
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string SubscribedTypesToString(HashSet<Type> subscribedTypes)
{
return subscribedTypes == null
? string.Empty
: Invariant($" SubscribedTypes: [{string.Join(",", subscribedTypes.Select(type => type.Name))}]");
}
/// <summary>
/// Returns a string message saying it was impossible to get ask price to perform the fill for the given security symbol because
/// no market data was found
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NoMarketDataToGetAskPriceForFilling(Securities.Security security, HashSet<Type> subscribedTypes = null)
{
return Invariant($"Cannot get ask price to perform fill for {security.Symbol} because no market data was found.") +
SubscribedTypesToString(subscribedTypes);
}
/// <summary>
/// Returns a string message saying it was impossible to get bid price to perform the fill for the given security symbol because
/// no market data was found
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NoMarketDataToGetBidPriceForFilling(Securities.Security security, HashSet<Type> subscribedTypes = null)
{
return Invariant($"Cannot get bid price to perform fill for {security.Symbol} because no market data was found.") +
SubscribedTypesToString(subscribedTypes);
}
/// <summary>
/// Returns a string message saying it was impossible to perform a fill for the given security symbol because
/// no data subscription was found
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NoDataSubscriptionFoundForFilling(Securities.Security security)
{
return Invariant($"Cannot perform fill for {security.Symbol} because no data subscription were found.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Fills.EquityFillModel"/> class and its consumers or related classes
/// </summary>
public static class EquityFillModel
{
/// <summary>
/// String message saying: No trade with the OfficialOpen or OpeningPrints flag within the 1-minute timeout
/// </summary>
public static string MarketOnOpenFillNoOfficialOpenOrOpeningPrintsWithinOneMinute =
"No trade with the OfficialOpen or OpeningPrints flag within the 1-minute timeout.";
/// <summary>
/// String message saying: No trade with the OfficialClose or ClosingPrints flag within the 1-minute timeout
/// </summary>
public static string MarketOnCloseFillNoOfficialCloseOrClosingPrintsWithinOneMinute =
"No trade with the OfficialClose or ClosingPrints flag within the 1-minute timeout.";
/// <summary>
/// String message saying: No trade with the OfficialClose or ClosingPrints flag for data that does not include
/// extended market hours
/// </summary>
public static string MarketOnCloseFillNoOfficialCloseOrClosingPrintsWithoutExtendedMarketHours =
"No trade with the OfficialClose or ClosingPrints flag for data that does not include extended market hours.";
/// <summary>
/// Returns a string message saying the last data (of the given tick type) has been used to fill
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithLastTickTypeData(Tick tick)
{
return Invariant($"Fill with last {tick.TickType} data.");
}
/// <summary>
/// Returns a string message warnning the user that no trade information was available, so the order was filled
/// using quote data
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithQuoteData(Securities.Security security)
{
return Invariant($@"Warning: No trade information available at {security.LocalTime.ToStringInvariant()} {
security.Exchange.TimeZone}, order filled using Quote data");
}
/// <summary>
/// Returns a string message warning the user that the fill is at stale price and that the order will
/// be filled using quote tick data
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithQuoteTickData(Securities.Security security, Tick quoteTick)
{
return Invariant($@"Warning: fill at stale price ({quoteTick.EndTime.ToStringInvariant()} {
security.Exchange.TimeZone}), using Quote Tick data.");
}
/// <summary>
/// Returns a string message warning the user that no quote information was available, so the order
/// was filled using trade tick data
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithTradeTickData(Securities.Security security, Tick tradeTick)
{
return Invariant($@"Warning: No quote information available at {tradeTick.EndTime.ToStringInvariant()} {
security.Exchange.TimeZone}, order filled using Trade Tick data");
}
/// <summary>
/// Returns a string message warning the user that the fill was at stale price, so quote bar data
/// was used to fill the order
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithQuoteBarData(Securities.Security security, QuoteBar quoteBar)
{
return Invariant($@"Warning: fill at stale price ({quoteBar.EndTime.ToStringInvariant()} {
security.Exchange.TimeZone}), using QuoteBar data.");
}
/// <summary>
/// Returns a string message warning the user that no quote information was available, so that trade bar
/// data was used to fill the order
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithTradeBarData(Securities.Security security, TradeBar tradeBar)
{
return Invariant($@"Warning: No quote information available at {tradeBar.EndTime.ToStringInvariant()} {
security.Exchange.TimeZone}, order filled using TradeBar data");
}
/// <summary>
/// Returns a string message saying that the order was filled using the open price due to a favorable gap
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithOpenDueToFavorableGap(Securities.Security security, TradeBar tradeBar)
{
return Invariant($@"Due to a favorable gap at {tradeBar.EndTime.ToStringInvariant()} {security.Exchange.TimeZone}, order filled using the open price ({tradeBar.Open})");
}
/// <summary>
/// Returns a string message saying that the order was filled using the open price due to an unfavorable gap
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FilledWithOpenDueToUnfavorableGap(Securities.Security security, TradeBar tradeBar)
{
return Invariant($@"Due to an unfavorable gap at {tradeBar.EndTime.ToStringInvariant()} {security.Exchange.TimeZone}, order filled using the open price ({tradeBar.Open})");
}
}
}
}
@@ -0,0 +1,56 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
using QuantConnect.Securities.Option;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Orders.OptionExercise"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.OptionExercise.DefaultExerciseModel"/> class and its consumers or related classes
/// </summary>
public static class DefaultExerciseModel
{
/// <summary>
/// String message saying: Option Assignment
/// </summary>
public static string OptionAssignment = "Option Assignment";
/// <summary>
/// String message saying: Option exercise
/// </summary>
public static string OptionExercise = "Option Exercise";
/// <summary>
/// Returns a string message containing basic information such as if it's
/// an assignment or an exercise, if it's ITM or OTM and the underlying option price
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ContractHoldingsAdjustmentFillTag(bool inTheMoney, bool isAssignment, Option option)
{
var action = isAssignment ? "Assigned" : "Automatic Exercise";
var tag = inTheMoney ? action : "OTM";
return $"{tag}. Underlying: {option.Underlying.Price.ToStringInvariant()}";
}
}
}
}
@@ -0,0 +1,64 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.CompilerServices;
using QuantConnect.Data;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Orders.Slippage"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Slippage.VolumeShareSlippageModel"/> class and its consumers or related classes
/// </summary>
public static class VolumeShareSlippageModel
{
/// <summary>
/// Returns a message for an invalid market data type in Volume Share Slippage Model
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidMarketDataType(BaseData data)
{
return $"VolumeShareSlippageModel.GetSlippageApproximation(): Cannot use this model with market data type {data.GetType()}";
}
/// <summary>
/// Returns a message for a volume not reported for market data type in Volume Share Slippage Model
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string VolumeNotReportedForMarketDataType(SecurityType securityType)
{
return Invariant($"VolumeShareSlippageModel.GetSlippageApproximation(): {securityType} security type often ") +
"does not report volume. If you intend to model slippage beyond the spread, please consider another model.";
}
/// <summary>
/// Returns a message for a negative or zero bar volume in Volume Share Slippage Model
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NegativeOrZeroBarVolume(decimal barVolume, decimal slippagePercent)
{
return Invariant($@"VolumeShareSlippageModel.GetSlippageApproximation: Bar volume cannot be zero or negative. Volume: {
barVolume}. Using maximum slippage percentage of {slippagePercent}");
}
}
}
}
+572
View File
@@ -0,0 +1,572 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using QuantConnect.Orders;
using QuantConnect.Securities;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Orders"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.CancelOrderRequest"/> class and its consumers or related classes
/// </summary>
public static class CancelOrderRequest
{
/// <summary>
/// Parses the given CancelOrderRequest into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.CancelOrderRequest request)
{
return Invariant($@"{request.Time.ToStringInvariant()} UTC: Cancel Order: ({request.OrderId}) - {
request.Tag} Status: {request.Status}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.GroupOrderExtensions"/> class and its consumers or related classes
/// </summary>
public static class GroupOrderExtensions
{
/// <summary>
/// Returns a string message saying there is insufficient buying power to complete the given orders
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InsufficientBuyingPowerForOrders(Dictionary<Orders.Order, Securities.Security> securities,
HasSufficientBuyingPowerForOrderResult hasSufficientBuyingPowerResult)
{
var ids = string.Join(",", securities.Keys.Select(o => o.Id));
var values = string.Join(",", securities.Select(o => o.Key.GetValue(o.Value).SmartRounding()));
return $@"Order Error: ids: [{ids}], Insufficient buying power to complete orders (Value:[{values}]), Reason: {
hasSufficientBuyingPowerResult.Reason}.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.LimitIfTouchedOrder"/> class and its consumers or related classes
/// </summary>
public static class LimitIfTouchedOrder
{
/// <summary>
/// Returns an empty string tag
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Tag(Orders.LimitIfTouchedOrder order)
{
// No additional information to display
return string.Empty;
}
/// <summary>
/// Parses the given LimitIfTouched order to a string message containing basic information
/// about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.LimitIfTouchedOrder order)
{
var currencySymbol = QuantConnect.Currencies.GetCurrencySymbol(order.PriceCurrency);
return Invariant($@"{Order.ToString(order)} at trigger {currencySymbol}{order.TriggerPrice.SmartRounding()
} limit {currencySymbol}{order.LimitPrice.SmartRounding()}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.LimitOrder"/> class and its consumers or related classes
/// </summary>
public static class LimitOrder
{
/// <summary>
/// Returns an empty string tag
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Tag(Orders.LimitOrder order)
{
// No additional information to display
return string.Empty;
}
/// <summary>
/// Parses a Limit order to a string message with basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.LimitOrder order)
{
var currencySymbol = QuantConnect.Currencies.GetCurrencySymbol(order.PriceCurrency);
return Invariant($"{Order.ToString(order)} at limit {currencySymbol}{order.LimitPrice.SmartRounding()}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.Order"/> class and its consumers or related classes
/// </summary>
public static class Order
{
/// <summary>
/// Parses the given order into a string message with basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.Order order)
{
var tag = string.IsNullOrEmpty(order.Tag) ? string.Empty : $": {order.Tag}";
return Invariant($@"OrderId: {order.Id} (BrokerId: {string.Join(",", order.BrokerId)}) {order.Status} {
order.Type} order for {order.Quantity} unit{(order.Quantity == 1 ? "" : "s")} of {order.Symbol}{tag}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.OrderEvent"/> class and its consumers or related classes
/// </summary>
public static class OrderEvent
{
/// <summary>
/// Parses the given order event into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.OrderEvent orderEvent)
{
var message = Invariant($@"Time: {orderEvent.UtcTime} OrderID: {orderEvent.OrderId} EventID: {
orderEvent.Id} Symbol: {orderEvent.Symbol.Value} Status: {orderEvent.Status} Quantity: {orderEvent.Quantity}");
var currencySymbol = QuantConnect.Currencies.GetCurrencySymbol(orderEvent.FillPriceCurrency);
if (orderEvent.FillQuantity != 0)
{
message += Invariant($@" FillQuantity: {orderEvent.FillQuantity
} FillPrice: {currencySymbol}{orderEvent.FillPrice.SmartRounding()}");
}
if (orderEvent.LimitPrice.HasValue)
{
message += Invariant($" LimitPrice: {currencySymbol}{orderEvent.LimitPrice.Value.SmartRounding()}");
}
if (orderEvent.StopPrice.HasValue)
{
message += Invariant($" StopPrice: {currencySymbol}{orderEvent.StopPrice.Value.SmartRounding()}");
}
if (orderEvent.TrailingAmount.HasValue)
{
var trailingAmountString = TrailingStopOrder.TrailingAmount(orderEvent.TrailingAmount.Value,
orderEvent.TrailingAsPercentage ?? false, currencySymbol);
message += $" TrailingAmount: {trailingAmountString}";
}
if (orderEvent.TriggerPrice.HasValue)
{
message += Invariant($" TriggerPrice: {currencySymbol}{orderEvent.TriggerPrice.Value.SmartRounding()}");
}
// attach the order fee so it ends up in logs properly.
if (orderEvent.OrderFee.Value.Amount != 0m)
{
message += Invariant($" OrderFee: {orderEvent.OrderFee}");
}
// add message from brokerage
if (!string.IsNullOrEmpty(orderEvent.Message))
{
message += Invariant($" Message: {orderEvent.Message}");
}
if (orderEvent.Symbol.SecurityType.IsOption())
{
message += Invariant($" IsAssignment: {orderEvent.IsAssignment}");
}
return message;
}
/// <summary>
/// Parses the given order event into a string message which summarizes the basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ShortToString(Orders.OrderEvent orderEvent)
{
var message = Invariant($"{orderEvent.UtcTime} OID:{orderEvent.OrderId} {orderEvent.Symbol.Value} {orderEvent.Status} Q:{orderEvent.Quantity}");
var currencySymbol = QuantConnect.Currencies.GetCurrencySymbol(orderEvent.FillPriceCurrency);
if (orderEvent.FillQuantity != 0)
{
message += Invariant($" FQ:{orderEvent.FillQuantity} FP:{currencySymbol}{orderEvent.FillPrice.SmartRounding()}");
}
if (orderEvent.LimitPrice.HasValue)
{
message += Invariant($" LP:{currencySymbol}{orderEvent.LimitPrice.Value.SmartRounding()}");
}
if (orderEvent.StopPrice.HasValue)
{
message += Invariant($" SP:{currencySymbol}{orderEvent.StopPrice.Value.SmartRounding()}");
}
if (orderEvent.TrailingAmount.HasValue)
{
var trailingAmountString = TrailingStopOrder.TrailingAmount(orderEvent.TrailingAmount.Value,
orderEvent.TrailingAsPercentage ?? false, currencySymbol);
message += $" TA: {trailingAmountString}";
}
if (orderEvent.TriggerPrice.HasValue)
{
message += Invariant($" TP:{currencySymbol}{orderEvent.TriggerPrice.Value.SmartRounding()}");
}
// attach the order fee so it ends up in logs properly.
if (orderEvent.OrderFee.Value.Amount != 0m)
{
message += Invariant($" OF:{currencySymbol}{orderEvent.OrderFee}");
}
// add message from brokerage
if (!string.IsNullOrEmpty(orderEvent.Message))
{
message += Invariant($" M:{orderEvent.Message}");
}
if (orderEvent.Symbol.SecurityType.IsOption())
{
message += Invariant($" IA:{orderEvent.IsAssignment}");
}
return message;
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.OrderRequest"/> class and its consumers or related classes
/// </summary>
public static class OrderRequest
{
/// <summary>
/// Parses the given order request into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.OrderRequest request)
{
return Invariant($"{request.Time} UTC: Order: ({request.OrderId}) - {request.Tag} Status: {request.Status}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.OrderResponse"/> class and its consumers or related classes
/// </summary>
public static class OrderResponse
{
/// <summary>
/// String message saying: An unexpected error occurred
/// </summary>
public static string DefaultErrorMessage = "An unexpected error occurred.";
/// <summary>
/// String message saying: The request has not yet been processed
/// </summary>
public static string UnprocessedOrderResponseErrorMessage = "The request has not yet been processed.";
/// <summary>
/// Parses the given order response into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.OrderResponse response)
{
if (response == Orders.OrderResponse.Unprocessed)
{
return "Unprocessed";
}
if (response.IsError)
{
return Invariant($"Error: {response.ErrorCode} - {response.ErrorMessage}");
}
return "Success";
}
/// <summary>
/// Returns a string message saying it was impossible to udpate the order with the id
/// from the given request because it already had the status of the given order
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidStatus(Orders.OrderRequest request, Orders.Order order)
{
return Invariant($"Unable to update order with id {request.OrderId} because it already has {order.Status} status.");
}
/// <summary>
/// Returns a string message saying it was impossible to update or cancel the order with the
/// id from the given request because the submit confirmation had not been received yet
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidNewStatus(Orders.OrderRequest request, Orders.Order order)
{
return Invariant($@"Unable to update or cancel order with id {
request.OrderId} and status {order.Status} because the submit confirmation has not been received yet.");
}
/// <summary>
/// Returns a string message saying it was impossible to locate the order with the id from the
/// given request
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnableToFindOrder(Orders.OrderRequest request)
{
return Invariant($"Unable to locate order with id {request.OrderId}.");
}
/// <summary>
/// Returns a string message saying it was impossible to process the given order request
/// that has zero quantity
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ZeroQuantity(Orders.OrderRequest request)
{
return Invariant($"Unable to {request.OrderRequestType.ToLower()} order with id {request.OrderId} that has zero quantity.");
}
/// <summary>
/// Returns a string message saying the user has not requested data for the symbol of the given
/// request. It also advises the user on how to add this data
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MissingSecurity(Orders.SubmitOrderRequest request)
{
return Invariant($"You haven't requested {request.Symbol} data. Add this with {FormatCode("AddSecurity")}() in the {FormatCode("Initialize")}() method.");
}
/// <summary>
/// Returns a string message saying the given order request operation is not allowed
/// in Initialize or during warm up. It also advises the user on where it is allowed
/// to make it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string WarmingUp(Orders.OrderRequest request)
{
return Invariant($@"This operation is not allowed in {FormatCode("Initialize")} or during warm up: OrderRequest.{
FormatCode(request.OrderRequestType)}. Please move this code to the {FormatCode("OnWarmupFinished")}() method.");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.OrderTicket"/> class and its consumers or related classes
/// </summary>
public static class OrderTicket
{
/// <summary>
/// Returns a string message saying it was impossible to get the given field on the order type from the given
/// ticket
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetFieldError(Orders.OrderTicket ticket, OrderField field)
{
return Invariant($"Unable to get field {field} on order of type {ticket.SubmitRequest.OrderType}");
}
/// <summary>
/// Returns a string message saying the order associated with the given ticket has already received a
/// cancellation request
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string CancelRequestAlreadySubmitted(Orders.OrderTicket ticket)
{
return Invariant($"Order {ticket.OrderId} has already received a cancellation request.");
}
/// <summary>
/// Parses the given order ticket into a string message containing basic information about it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.OrderTicket ticket, Orders.Order order, int requestCount, int responseCount)
{
var counts = Invariant($"Request Count: {requestCount} Response Count: {responseCount}");
if (order != null)
{
return Invariant($"{ticket.OrderId}: {order} {counts}");
}
return Invariant($"{ticket.OrderId}: {counts}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.StopLimitOrder"/> class and its consumers or related classes
/// </summary>
public static class StopLimitOrder
{
/// <summary>
/// Returns an empty string as a tag
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Tag(Orders.StopLimitOrder order)
{
// No additional information to display
return string.Empty;
}
/// <summary>
/// Parses the given StopLimitOrder object into a string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.StopLimitOrder order)
{
var currencySymbol = QuantConnect.Currencies.GetCurrencySymbol(order.PriceCurrency);
return Invariant($@"{Order.ToString(order)} at stop {currencySymbol}{order.StopPrice.SmartRounding()
} limit {currencySymbol}{order.LimitPrice.SmartRounding()}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.StopMarketOrder"/> class and its consumers or related classes
/// </summary>
public static class StopMarketOrder
{
/// <summary>
/// Returns an empty string as a tag
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Tag(Orders.StopMarketOrder order)
{
// No additional information to display
return string.Empty;
}
/// <summary>
/// Parses a given StopMarketOrder object into a string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.StopMarketOrder order)
{
var currencySymbol = QuantConnect.Currencies.GetCurrencySymbol(order.PriceCurrency);
return Invariant($"{Order.ToString(order)} at stop {currencySymbol}{order.StopPrice.SmartRounding()}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.TrailingStopOrder"/> class and its consumers or related classes
/// </summary>
public static class TrailingStopOrder
{
/// <summary>
/// Returns a tag message for the given TrailingStopOrder
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string Tag(Orders.TrailingStopOrder order)
{
return Invariant($"Trailing Amount: {TrailingAmount(order)}");
}
/// <summary>
/// Parses a TrailingStopOrder into a string
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.TrailingStopOrder order)
{
var currencySymbol = QuantConnect.Currencies.GetCurrencySymbol(order.PriceCurrency);
return Invariant($@"{Order.ToString(order)} at stop {currencySymbol}{order.StopPrice.SmartRounding()}. Trailing amount: {
TrailingAmountImpl(order, currencySymbol)}");
}
/// <summary>
/// Returns a TrailingAmount string representation for the given TrailingStopOrder
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TrailingAmount(Orders.TrailingStopOrder order)
{
return TrailingAmountImpl(order, QuantConnect.Currencies.GetCurrencySymbol(order.PriceCurrency));
}
/// <summary>
/// Returns a message for the given TrailingAmount and PriceCurrency values taking into account if the trailing is as percentage
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TrailingAmount(decimal trailingAmount, bool trailingAsPercentage, string priceCurrency)
{
return trailingAsPercentage ? Invariant($"{trailingAmount * 100}%") : Invariant($"{priceCurrency}{trailingAmount}");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string TrailingAmountImpl(Orders.TrailingStopOrder order, string currencySymbol)
{
return TrailingAmount(order.TrailingAmount, order.TrailingAsPercentage, currencySymbol);
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.SubmitOrderRequest"/> class and its consumers or related classes
/// </summary>
public static class SubmitOrderRequest
{
/// <summary>
/// Parses a given SubmitOrderRequest object to a string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.SubmitOrderRequest request)
{
// create a proxy order object to steal its ToString method
var proxy = Orders.Order.CreateOrder(request);
return Invariant($"{request.Time} UTC: Submit Order: ({request.OrderId}) - {proxy} {request.Tag} Status: {request.Status} Async: {request.Asynchronous}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="Orders.UpdateOrderRequest"/> class and its consumers or related classes
/// </summary>
public static class UpdateOrderRequest
{
/// <summary>
/// Parses an UpdateOrderRequest to a string
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(Orders.UpdateOrderRequest request)
{
var updates = new List<string>(4);
if (request.Quantity.HasValue)
{
updates.Add(Invariant($"Quantity: {request.Quantity.Value}"));
}
if (request.LimitPrice.HasValue)
{
updates.Add(Invariant($"LimitPrice: {request.LimitPrice.Value.SmartRounding()}"));
}
if (request.StopPrice.HasValue)
{
updates.Add(Invariant($"StopPrice: {request.StopPrice.Value.SmartRounding()}"));
}
if (request.TrailingAmount.HasValue)
{
updates.Add(Invariant($"TrailingAmount: {request.TrailingAmount.Value.SmartRounding()}"));
}
if (request.TriggerPrice.HasValue)
{
updates.Add(Invariant($"TriggerPrice: {request.TriggerPrice.Value.SmartRounding()}"));
}
return Invariant($@"{request.Time} UTC: Update Order: ({request.OrderId}) - {string.Join(", ", updates)} {
request.Tag} Status: {request.Status}");
}
}
}
}
+267
View File
@@ -0,0 +1,267 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.IO;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using Python.Runtime;
using System;
using System.Linq;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Python"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing common messages for the <see cref="Python"/> namespace classes
/// </summary>
public static class PythonCommon
{
/// <summary>
/// Returns a string message saying the given attribute must be implemented on the given Python type
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string AttributeNotImplemented(string attribute, PyType pythonType)
{
return $"{attribute} must be implemented. Please implement this missing method on {pythonType}";
}
}
/// <summary>
/// Provides user-facing common messages for the <see cref="Python.MarginCallModelPythonWrapper"/> namespace classes
/// </summary>
public static class MarginCallModelPythonWrapper
{
/// <summary>
/// String message saying: Must return a tuple, where the first item is a list and the second a boolean
/// </summary>
public static string GetMarginCallOrdersMustReturnTuple = "Must return a tuple, where the first item is a list and the second a boolean";
}
/// <summary>
/// Provides user-facing common messages for the <see cref="Python.PandasConverter"/> namespace classes
/// </summary>
public static class PandasConverter
{
/// <summary>
/// String message saying: Pandas module was not imported
/// </summary>
public static string PandasModuleNotImported = "pandas module was not imported.";
/// <summary>
/// Returns a string message saying ConvertToDictionary() method cannot be used to convert the given source
/// type into the given target type. It also contains the reason why this method cannot be used
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ConvertToDictionaryFailed(string sourceType, string targetType, string reason)
{
return $"ConvertToDictionary cannot be used to convert a {sourceType} into {targetType}. Reason: {reason}";
}
}
/// <summary>
/// Provides user-facing common messages for the <see cref="Python.PandasData"/> namespace classes
/// </summary>
public static class PandasData
{
/// <summary>
/// Returns a string message saying the given key was duplicated in the given
/// type class
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string DuplicateKey(string duplicateKey, string type)
{
return $"More than one '{duplicateKey}' member was found in '{type}' class.";
}
/// <summary>
/// Returns a string message saying the given key does not exist in series dictionary
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string KeyNotFoundInSeries(string key)
{
return $"{key} key does not exist in series dictionary.";
}
}
/// <summary>
/// Provides user-facing common messages for the <see cref="Python.PythonInitializer"/> namespace classes
/// </summary>
public static class PythonInitializer
{
/// <summary>
/// String message saying: start
/// </summary>
public static string Start = "start";
/// <summary>
/// String message saying: ended
/// </summary>
public static string Ended = "ended";
/// <summary>
/// Returns a string message saying it was impossible to find algorithm location path
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnableToLocateAlgorithm(string algorithmLocation)
{
return $"Unable to find algorithm location path: {algorithmLocation}.";
}
/// <summary>
/// Returns a string message saying the given path to virtual environment does not exist
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string VirutalEnvironmentNotFound(string virtualEnvPath)
{
return $"Path {virtualEnvPath} to virtual environment does not exist.";
}
/// <summary>
/// Returns a string message saying it was impossible to find system package configuration
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FailedToFindSystemPackagesConfiguration(string virtualEnvPath, FileInfo configFile)
{
return $@"virtual env '{virtualEnvPath}'. Failed to find system packages configuration. ConfigFile.Exits: {
configFile.Exists}. Will default to true.";
}
/// <summary>
/// Returns a string message saying the Python Initializer will use the system packages found
/// in the virtual environment path
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SystemPackagesConfigurationFound(string virtualEnvPath, bool includeSystemPackages)
{
return $"virtual env '{virtualEnvPath}'. Will use system packages: {includeSystemPackages}";
}
/// <summary>
/// Returns a string message saying it was impossible to find the given python path
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string PythonPathNotFound(string pythonPath)
{
return $"Unable to find python path: {pythonPath}. Skipping.";
}
}
/// <summary>
/// Provides user-facing common messages for the <see cref="Python.PythonWrapper"/> namespace classes
/// </summary>
public static class PythonWrapper
{
/// <summary>
/// String message saying: expected and interface type parameter
/// </summary>
public static string ExpectedInterfaceTypeParameter = "expected an interface type parameter.";
/// <summary>
/// Returns a string message saying the given interface must be fully implemented. It also advises the user
/// on the missing methods in its interface
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InterfaceNotFullyImplemented(string interfaceName, string pythonTypeName, IEnumerable<string> missingMembers)
{
return $@"{interfaceName} must be fully implemented. Please implement these missing methods on {
pythonTypeName}: {string.Join(", ", missingMembers)}";
}
}
/// <summary>
/// Provides user-facing common messages for the <see cref="Python.BasePythonWrapper{TInterface}"/> class
/// </summary>
public static class BasePythonWrapper
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidDictionaryValueType(string pythonMethodName, Type expectedType, PyType actualPyType)
{
return InvalidDictionaryItemType(pythonMethodName, expectedType, actualPyType, isKey: false);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidDictionaryKeyType(string pythonMethodName, Type expectedType, PyType actualPyType)
{
return InvalidDictionaryItemType(pythonMethodName, expectedType, actualPyType, isKey: true);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidReturnTypeForMethodWithOutParameters(string pythonMethodName, PyType pyValueType)
{
return $"Invalid return type from method '{pythonMethodName.ToSnakeCase()}'. Expected a tuple type but was " +
$"'{GetPythonTypeName(pyValueType)}'. The tuple must contain the return value as the first item, " +
$"with the remaining ones being the out parameters.";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidReturnTypeTupleSizeForMethodWithOutParameters(string pythonMethodName, long expectedSize, long actualSize)
{
return $"Invalid return type from method '{pythonMethodName.ToSnakeCase()}'. Expected a tuple with at least " +
$"'{expectedSize}' items but only '{actualSize}' were returned. " +
$"The tuple must contain the return value as the first item, with the remaining ones being the out parameters.";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidOutParameterType(string pythonMethodName, int index, Type expectedType, PyType actualPyType)
{
return $"Invalid out parameter type in method '{pythonMethodName.ToSnakeCase()}'. Out parameter in position {index} " +
$"expected type is '{expectedType.Name}' but was '{GetPythonTypeName(actualPyType)}'.";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidReturnType(string pythonName, Type expectedType, PyType actualPyType, bool isMethod = true)
{
var message = isMethod
? $"Invalid return type from method '{pythonName.ToSnakeCase()}'. "
: $"Invalid type for property '{pythonName.ToSnakeCase()}'. ";
message += $"Expected a type convertible to '{expectedType.Name}' but was '{GetPythonTypeName(actualPyType)}'";
return message;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidIterable(string pythonMethodName, Type expectedType, PyType actualPyType)
{
return $"Invalid return type from method '{pythonMethodName.ToSnakeCase()}'. " +
$"Expected an iterable type of '{expectedType.Name}' items but was '{GetPythonTypeName(actualPyType)}'";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidMethodIterableItemType(string pythonMethodName, Type expectedType, PyType actualPyType)
{
return $"Invalid return type from method '{pythonMethodName.ToSnakeCase()}'. Expected all the items in the iterator to be of type " +
$"'{expectedType.Name}' but found one of type ' {GetPythonTypeName(actualPyType)}'";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string InvalidDictionaryItemType(string pythonMethodName, Type expectedType, PyType actualPyType, bool isKey = true)
{
return $"Invalid value type from method or property '{pythonMethodName.ToSnakeCase()}'. " +
$"Expected all the {(isKey ? "keys" : "values")} in the dictionary to be of type '{expectedType.Name}' " +
$"but found one of type '{GetPythonTypeName(actualPyType)}'";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string GetPythonTypeName(PyType pyType)
{
return pyType.Name.Split('.').Last();
}
}
}
}
+988
View File
@@ -0,0 +1,988 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Python.Runtime;
using QuantConnect.Interfaces;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="QuantConnect"/> namespace
/// </summary>
public static partial class Messages
{
private static Language _algorithmLanguage = Language.CSharp;
/// <summary>
/// Sets the algorithm language used to format code identifiers in error messages.
/// </summary>
public static void SetAlgorithmLanguage(Language language)
{
_algorithmLanguage = language;
}
/// <summary>
/// Returns the code identifier formatted for the current algorithm language.
/// For Python, converts PascalCase/camelCase to snake_case.
/// </summary>
private static string FormatCode(string code)
{
return _algorithmLanguage switch
{
Language.Python => code.ToSnakeCase(),
_ => code
};
}
private static string FormatCodeRoot(string code)
{
return _algorithmLanguage switch
{
Language.Python => "self." + code.ToSnakeCase(),
_ => code
};
}
private static string FormatCode<T>(T value) where T : Enum
{
return FormatCode(value.ToString());
}
private static string AlgorithmPrefix()
{
return _algorithmLanguage == Language.Python ? "self" : "QCAlgorithm";
}
/// <summary>
/// Provides user-facing messages for the <see cref="AlphaRuntimeStatistics"/> class and its consumers or related classes
/// </summary>
public static class AlphaRuntimeStatistics
{
/// <summary>
/// Returns a string message saying: Return Over Maximum Drawdown
/// </summary>
public static string ReturnOverMaximumDrawdownKey = "Return Over Maximum Drawdown";
/// <summary>
/// Returns a string message saying: Portfolio Turnover
/// </summary>
public static string PortfolioTurnoverKey = "Portfolio Turnover";
/// <summary>
/// Returns a string message saying: Total Insights Generated
/// </summary>
public static string TotalInsightsGeneratedKey = "Total Insights Generated";
/// <summary>
/// Returns a string message saying: Total Insights Closed
/// </summary>
public static string TotalInsightsClosedKey = "Total Insights Closed";
/// <summary>
/// Returns a string message saying: Total Insights Analysis Completed
/// </summary>
public static string TotalInsightsAnalysisCompletedKey = "Total Insights Analysis Completed";
/// <summary>
/// Returns a string message saying: Long Insight Count
/// </summary>
public static string LongInsightCountKey = "Long Insight Count";
/// <summary>
/// Returns a string message saying: Short Insight Count
/// </summary>
public static string ShortInsightCountKey = "Short Insight Count";
/// <summary>
/// Returns a string message saying: Long/Short Ratio
/// </summary>
public static string LongShortRatioKey = "Long/Short Ratio";
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Chart"/> class and its consumers or related classes
/// </summary>
public static class Chart
{
/// <summary>
/// Returns a string message saying Chart series name already exists
/// </summary>
public static string ChartSeriesAlreadyExists = "Chart series name already exists";
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.ChartPoint"/> class and its consumers or related classes
/// </summary>
public static class ChartPoint
{
/// <summary>
/// Parses a given ChartPoint object into a string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(QuantConnect.ChartPoint instance)
{
return Invariant($"{instance.Time:o} - {instance.y}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Candlestick"/> class and its consumers or related classes
/// </summary>
public static class Candlestick
{
/// <summary>
/// Parses a given Candlestick object into a string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(QuantConnect.Candlestick instance)
{
return Invariant($@"{instance.Time:o} - (O:{instance.Open} H: {instance.High} L: {instance.Low} C: {instance.Close})");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Currencies"/> class and its consumers or related classes
/// </summary>
public static class Currencies
{
/// <summary>
/// Returns a string message saying the given value cannot be converted to a decimal number
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FailedConversionToDecimal(string value)
{
return $"The value {value} cannot be converted to a decimal number";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.ExtendedDictionary{T}"/> class and its consumers or related classes
/// </summary>
public static class ExtendedDictionary
{
/// <summary>
/// Returns a string message saying the types deriving from ExtendedDictionary must implement the void Clear() method
/// </summary>
public static string ClearMethodNotImplemented = "Types deriving from 'ExtendedDictionary' must implement the 'void Clear() method.";
/// <summary>
/// Returns a string message saying the types deriving from ExtendedDictionary must implement the void Remove(Symbol) method
/// </summary>
public static string RemoveMethodNotImplemented =
"Types deriving from 'ExtendedDictionary' must implement the 'void Remove(Symbol) method.";
/// <summary>
/// Returns a string message saying the types deriving from ExtendedDictionary must implement the T this[Symbol] method
/// </summary>
public static string IndexerBySymbolNotImplemented =
"Types deriving from 'ExtendedDictionary' must implement the 'T this[Symbol] method.";
/// <summary>
/// Returns a string with the error message we receive from Python when we try to pop a key with a null value in the ExtendedDictionary. It also shows a recommendation for solving this problem
/// </summary>
public static string KeyNotFoundDueToNone = $"KeyError: None. Please check if the key is None before trying to access it or use data.pop(key, default) to return a default value instead of raising an exception.";
/// <summary>
/// Returns a string message saying Clear/clear method call is an invalid operation. It also says that the given instance
/// is a read-only collection
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ClearInvalidOperation<TKey, TValue>(ExtendedDictionary<TKey, TValue> instance)
{
return $"Clear/clear method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
}
/// <summary>
/// Returns a string message saying that Remove/pop call method is an invalid operation. It also says that the given instance
/// is a read-only collection
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string RemoveInvalidOperation<TKey, TValue>(ExtendedDictionary<TKey, TValue> instance)
{
return $"Remove/pop method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
}
/// <summary>
/// Returns a string message saying that the given ticker was not found in the SymbolCache. It also gives a recommendation
/// for solving this problem
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TickerNotFoundInSymbolCache(string ticker)
{
return $"The ticker {ticker} was not found in the SymbolCache. Use the Symbol object as key instead. " +
$"Accessing the securities collection/slice object by string ticker is only available for securities added with " +
$"the {FormatCode("AddSecurity")}-family methods. For more details, please check out the documentation.";
}
/// <summary>
/// Returns a string message saying that the popitem method is not supported for the given instance
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string PopitemMethodNotSupported<TKey, TValue>(ExtendedDictionary<TKey, TValue> instance)
{
return $"popitem method is not supported for {instance.GetType().Name}";
}
/// <summary>
/// Returns a string message saying that the given symbol wasn't found in the give instance object. It also shows
/// a recommendation for solving this problem
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string KeyNotFoundDueToNoData<TKey, TValue>(ExtendedDictionary<TKey, TValue> instance, TKey key)
{
return $"'{key}' wasn't found in the {instance.GetType().Name} object, likely because there was no-data at this moment in " +
"time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with " +
$"data.ContainsKey(\"{key}\"). The collection is read-only, cannot set default.";
}
/// <summary>
/// Returns a string message saying the update method call is an invalid operation. It also mentions that the given
/// instance is a read-only collection
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UpdateInvalidOperation<TKey, TValue>(ExtendedDictionary<TKey, TValue> instance)
{
return $"update method call is an invalid operation. {instance.GetType().Name} is a read-only collection.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Extensions"/> class and its consumers or related classes
/// </summary>
public static class Extensions
{
/// <summary>
/// Returns a string message saying adjusting a symbol by an offset is currently only supported for non canonical futures
/// </summary>
public static string ErrorAdjustingSymbolByOffset =
"Adjusting a symbol by an offset is currently only supported for non canonical futures";
/// <summary>
/// Returns a string message saying the provided DataProvider instance is null
/// </summary>
public static string NullDataProvider =
$"The provided '{nameof(IDataProvider)}' instance is null. Are you missing some initialization step?";
/// <summary>
/// Returns a string message saying the source cannot be null or empty
/// </summary>
public static string NullOrEmptySourceToConvertToHexString = "Source cannot be null or empty.";
/// <summary>
/// Returns a string message saying the CreateOptionChain method requires an option symbol
/// </summary>
public static string CreateOptionChainRequiresOptionSymbol = "CreateOptionChain requires an option symbol.";
/// <summary>
/// Returns a string message saying the CreateFutureChain method requires a future symbol
/// </summary>
public static string CreateFutureChainRequiresFutureSymbol = "CreateFutureChain requires a future symbol.";
/// <summary>
/// Returns a string message saying the list of values cannot be empty
/// </summary>
public static string GreatestCommonDivisorEmptyList = "The list of values cannot be empty";
/// <summary>
/// Returns a string message saying that the symbol for which a mirror contract is being created is not a valid option symbol
/// </summary>
public static string NotAValidOptionSymbolForMirror = "Cannot create mirror contract for non-option symbol or canonical option symbol";
/// <summary>
/// Returns a string message saying the process of downloading data from the given url failed
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string DownloadDataFailed(string url)
{
return $"failed for: '{url}'";
}
/// <summary>
/// Returns a string message saying the security does not have an accurate price as it has not yet received
/// a bar of data, as well as some recommendations
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ZeroPriceForSecurity(QuantConnect.Symbol symbol)
{
return $"{symbol}: The security does not have an accurate price as it has not yet received a bar of data. " +
$"Before placing a trade (or using {FormatCode("SetHoldings")}) warm up your algorithm with {FormatCode("SetWarmup")}, or use slice.{FormatCode("Contains")}(symbol) " +
"to confirm the Slice object has price before using the data. Data does not necessarily all arrive at the same " +
"time so your algorithm should confirm the data is ready before using it. In live trading this can mean you do " +
"not have an active subscription to the asset class you're trying to trade. If using custom data make sure you've " +
"set the 'Value' property.";
}
/// <summary>
/// Returns a string message saying: Waiting for the given thread to stop
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string WaitingForThreadToStopSafely(string threadName)
{
return $"Waiting for '{threadName}' thread to stop...";
}
/// <summary>
/// Returns a string message saying: Timeout waiting for the given thread to stop
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TimeoutWaitingForThreadToStopSafely(string threadName)
{
return $"Timeout waiting for '{threadName}' thread to stop";
}
/// <summary>
/// Returns a string message saying the given data type is missing a parameterless constructor
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string DataTypeMissingParameterlessConstructor(Type type)
{
return $"Data type '{type.Name}' missing parameterless constructor. E.g. public {type.Name}() {{ }}";
}
/// <summary>
/// Returns a string message saying the process of creating an instance of the given type failed
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FailedToCreateInstanceOfType(Type type)
{
return $"Failed to create instance of type '{type.Name}'";
}
/// <summary>
/// Returns a string message saying the given data type does not inherit the required BaseData
/// methods and/or attributes
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TypeIsNotBaseData(Type type)
{
return $"Data type '{type.Name}' does not inherit required {nameof(Data.BaseData)}";
}
/// <summary>
/// Returns a string message saying it is impossible to cast the given non-finite floating-point value
/// as a decimal
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string CannotCastNonFiniteFloatingPointValueToDecimal(double input)
{
return Invariant($@"It is not possible to cast a non-finite floating-point value ({input}) as decimal. Please review math operations and verify the result is valid.");
}
/// <summary>
/// Returns a string message saying it was not able to exactly convert the given time span to resolution
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnableToConvertTimeSpanToResolution(TimeSpan timeSpan)
{
return Invariant($"Unable to exactly convert time span ('{timeSpan}') to resolution.");
}
/// <summary>
/// Returns a string message saying it was attempted to parse the given unknown security type
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnableToParseUnknownSecurityType(string value)
{
return $"Attempted to parse unknown SecurityType: {value}";
}
/// <summary>
/// Returns a string message saying the given security type has no default OptionStyle, because it has no options
/// available for it
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NoDefaultOptionStyleForSecurityType(SecurityType securityType)
{
return Invariant($"The SecurityType {securityType} has no default OptionStyle, because it has no options available for it");
}
/// <summary>
/// Returns a string message saying the given OptionStyle was unexpected/unknown
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnknownOptionStyle(string value)
{
return $"Unexpected OptionStyle: {value}";
}
/// <summary>
/// Returns a string message saying the given OptionStyle was unexpected/unknown
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnknownOptionStyle(OptionStyle value)
{
return $"Unexpected OptionStyle: {value}";
}
/// <summary>
/// Returns a string message saying the given OptionRight was unexpected/unknown
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnknownOptionRight(string value)
{
return $"Unexpected OptionRight: {value}";
}
/// <summary>
/// Returns a string message saying the given OptionRight was unexpected/unknown
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnknownOptionRight(OptionRight value)
{
return $"Unexpected OptionRight: {value}";
}
/// <summary>
/// Returns a string message saying the given DataMappingMode was unexpected/unknown
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnknownDataMappingMode(string value)
{
return $"Unexpected DataMappingMode: {value}";
}
/// <summary>
/// Returns a string message saying the method ConvertToDictionary cannot be used to convert a given source
/// type into another given target type. It also specifies the reason.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ConvertToDictionaryFailed(string sourceType, string targetType, string reason)
{
return $"ConvertToDictionary cannot be used to convert a {sourceType} into {targetType}. Reason: {reason}";
}
/// <summary>
/// Returns a string message saying the given argument type should Symbol or a list of Symbol. It also
/// shows the given item as well as its Python type
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ConvertToSymbolEnumerableFailed(PyObject item)
{
return $"Argument type should be Symbol or a list of Symbol. Object: {item}. Type: {item.GetPythonType()}";
}
/// <summary>
/// Returns a string message saying the given object is not a C# type
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ObjectFromPythonIsNotACSharpType(string objectRepr)
{
return $"{objectRepr} is not a C# Type.";
}
/// <summary>
/// Returns a string message saying there was a RuntimeError at a given time in UTC. It also
/// shows the given context
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string RuntimeError(IAlgorithm algorithm, string context)
{
return Invariant($"RuntimeError at {algorithm.UtcTime} UTC. Context: {context}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Holding"/> class and its consumers or related classes
/// </summary>
public static class Holding
{
/// <summary>
/// Parses a Holding object into a string message
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString(QuantConnect.Holding instance)
{
var currencySymbol = instance.CurrencySymbol;
if (string.IsNullOrEmpty(currencySymbol))
{
currencySymbol = "$";
}
var value = Invariant($@"{instance.Symbol?.Value}: {instance.Quantity} @ {currencySymbol}{instance.AveragePrice} - Market: {currencySymbol}{instance.MarketPrice}");
if (instance.ConversionRate.HasValue && instance.ConversionRate != 1m)
{
value += Invariant($" - Conversion: {instance.ConversionRate}");
}
return value;
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.AlgorithmControl"/> class and its consumers or related classes
/// </summary>
public static class AlgorithmControl
{
/// <summary>
/// Returns a string message saying: Strategy Equity
/// </summary>
public static string ChartSubscription = "Strategy Equity";
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Isolator"/> class and its consumers or related classes
/// </summary>
public static class Isolator
{
/// <summary>
/// Returns a string message saying: Execution Security Error: Memory Usage Maxed out, with the max memory capacity
/// and a last sample of the usage
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MemoryUsageMaxedOut(string memoryCap, string lastSample)
{
return $"Execution Security Error: Memory Usage Maxed Out - {memoryCap}MB max, with last sample of {lastSample}MB.";
}
/// <summary>
/// Returns a string message saying: Execution Security Error: Memory usage over 80% capacity, and the last sample taken
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MemoryUsageOver80Percent(double lastSample)
{
return Invariant($"Execution Security Error: Memory usage over 80% capacity. Sampled at {lastSample}");
}
/// <summary>
/// Returns a string message with useful information about the memory usage, such us the memory used, the last sample
/// the current memory used by the given app and the CPU usage
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MemoryUsageInfo(string memoryUsed, string lastSample, string memoryUsedByApp, TimeSpan currentTimeStepElapsed,
int cpuUsage)
{
return Invariant($@"Used: {memoryUsed}, Sample: {lastSample}, App: {memoryUsedByApp}, CurrentTimeStepElapsed: {currentTimeStepElapsed:mm':'ss'.'fff}. CPU: {cpuUsage}%");
}
/// <summary>
/// Returns a string message saying: Execution Security Error: Operation timed out, with the maximum amount of minutes
/// allowed
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MemoryUsageMonitorTaskTimedOut(TimeSpan timeout)
{
return $@"Execution Security Error: Operation timed out - {timeout.TotalMinutes.ToStringInvariant()} minutes max. Check for recursive loops.";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Market"/> class and its consumers or related classes
/// </summary>
public static class Market
{
/// <summary>
/// Returns a string message saying the market identifier is limited to positive values less than the given maximum market identifier
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidMarketIdentifier(int maxMarketIdentifier)
{
return $"The market identifier is limited to positive values less than {maxMarketIdentifier.ToStringInvariant()}.";
}
/// <summary>
/// Returns a string message saying it was attempted to add an already added market with a different identifier
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TriedToAddExistingMarketWithDifferentIdentifier(string market)
{
return $"Attempted to add an already added market with a different identifier. Market: {market}";
}
/// <summary>
/// Returns a string message saying it was attempted to add a market identifier that is already in use
/// </summary>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string TriedToAddExistingMarketIdentifier(string market, string existingMarket)
{
return $"Attempted to add a market identifier that is already in use. New Market: {market} Existing Market: {existingMarket}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.OS"/> class and its consumers or related classes
/// </summary>
public static class OS
{
/// <summary>
/// CPU Usage string
/// </summary>
public static string CPUUsageKey = "CPU Usage";
/// <summary>
/// Used RAM (MB) string
/// </summary>
public static string UsedRAMKey = "Used RAM (MB)";
/// <summary>
/// Total RAM (MB) string
/// </summary>
public static string TotalRAMKey = "Total RAM (MB)";
/// <summary>
/// Hostname string
/// </summary>
public static string HostnameKey = "Hostname";
/// <summary>
/// LEAN Version string
/// </summary>
public static string LEANVersionKey = "LEAN Version";
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Parse"/> class and its consumers or related classes
/// </summary>
public static class Parse
{
/// <summary>
/// Returns a string message saying the provided input was not parseable as the given target type
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ValueIsNotParseable(string input, Type targetType)
{
return $"The provided value ({input}) was not parseable as {targetType.Name}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.SecurityIdentifier"/> class and its consumers or related classes
/// </summary>
public static class SecurityIdentifier
{
/// <summary>
/// Returns a string message saying no underlying was specified for certain identifier
/// </summary>
public static string NoUnderlyingForIdentifier =
"No underlying specified for this identifier. Check that HasUnderlying is true before accessing the Underlying property.";
/// <summary>
/// Returns a string message saying Date is only defined for SecurityType.Equity, SecurityType.Option, SecurityType.Future, SecurityType.FutureOption, SecurityType.IndexOption, and SecurityType.Base
/// </summary>
public static string DateNotSupportedBySecurityType =
"Date is only defined for SecurityType.Equity, SecurityType.Option, SecurityType.Future, SecurityType.FutureOption, SecurityType.IndexOption, and SecurityType.Base";
/// <summary>
/// Returns a string message saying StrikePrice is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption
/// </summary>
public static string StrikePriceNotSupportedBySecurityType =
"StrikePrice is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
/// <summary>
/// Returns a string message saying OptionRight is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption
/// </summary>
public static string OptionRightNotSupportedBySecurityType =
"OptionRight is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
/// <summary>
/// Returns a string message saying OptionStyle is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption
/// </summary>
public static string OptionStyleNotSupportedBySecurityType =
"OptionStyle is only defined for SecurityType.Option, SecurityType.FutureOption, and SecurityType.IndexOption";
/// <summary>
/// Returns a string message saying SecurityIdentifier requires a non-null string 'symbol'
/// </summary>
public static string NullSymbol = "SecurityIdentifier requires a non-null string 'symbol'";
/// <summary>
/// Returns a string message saying Symbol must not contain the characters '|' or ' '
/// </summary>
public static string SymbolWithInvalidCharacters = "Symbol must not contain the characters '|' or ' '.";
/// <summary>
/// Returns a string message saying the provided properties do not match with a valid SecurityType
/// </summary>
public static string PropertiesDoNotMatchAnySecurityType = $"The provided properties do not match with a valid {nameof(SecurityType)}";
/// <summary>
/// Returns a string message saying the string must be splittable on space into two parts
/// </summary>
public static string StringIsNotSplittable = "The string must be splittable on space into two parts.";
/// <summary>
/// Returns a string message saying object must be of type SecurityIdentifier
/// </summary>
public static string UnexpectedTypeToCompareTo = $"Object must be of type {nameof(SecurityIdentifier)}";
/// <summary>
/// Returns a string message saying the given parameter must be between 0 and 99
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidSecurityType(string parameterName)
{
return $"{parameterName} must be between 0 and 99";
}
/// <summary>
/// Returns a string message saying the given parameter must be either 0 or 1
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidOptionRight(string parameterName)
{
return $"{parameterName} must be either 0 or 1";
}
/// <summary>
/// Returns a string message saying the specified strike price's precision is too high
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidStrikePrice(decimal strikePrice)
{
return Invariant($"The specified strike price's precision is too high: {strikePrice}");
}
/// <summary>
/// Returns a string message saying there was an error parsing SecurityIdentifier. It also says the given error and exception
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ErrorParsingSecurityIdentifier(string value, Exception exception)
{
return Invariant($"Error parsing SecurityIdentifier: '{value}', Exception: {exception}");
}
/// <summary>
/// Returns a string message saying the given market could not be found in the markets lookup
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MarketNotFound(string market)
{
return $@"The specified market wasn't found in the markets lookup. Requested: {market}. You can add markets by calling QuantConnect.Market.{FormatCode("Add")}(string,int)";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.StringExtensions"/> class and its consumers or related classes
/// </summary>
public static class StringExtensions
{
/// <summary>
/// Returns a string message saying StringExtensinos.ConvertInvariant does not support converting to the given TypeCode
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ConvertInvariantCannotConvertTo(TypeCode targetTypeCode)
{
return $"StringExtensions.ConvertInvariant does not support converting to TypeCode.{targetTypeCode}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Symbol"/> class and its consumers or related classes
/// </summary>
public static class Symbol
{
/// <summary>
/// Returns a string message saying there is insufficient information for creating certain future option symbol
/// </summary>
public static string InsufficientInformationToCreateFutureOptionSymbol =
"Cannot create future option Symbol using this method (insufficient information). Use `CreateOption(Symbol, ...)` instead.";
/// <summary>
/// Returns a string message saying Canonical is only defined for SecurityType.Option, SecurityType.Future, SecurityType.FutureOption
/// </summary>
public static string CanonicalNotDefined =
"Canonical is only defined for SecurityType.Option, SecurityType.Future, SecurityType.FutureOption";
/// <summary>
/// Returns a string message saying certain object must be of type Symbol or string
/// </summary>
public static string UnexpectedObjectTypeToCompareTo = "Object must be of type Symbol or string.";
/// <summary>
/// Returns a string message saying the given security type has not been implemented yet
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SecurityTypeNotImplementedYet(SecurityType securityType)
{
return Invariant($"The security type has not been implemented yet: {securityType}");
}
/// <summary>
/// Returns a string message saying the given security can not be mapped
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SecurityTypeCannotBeMapped(SecurityType securityType)
{
return Invariant($"SecurityType {securityType} can not be mapped.");
}
/// <summary>
/// Returns a string message saying no option type exists for the given underlying SecurityType
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NoOptionTypeForUnderlying(SecurityType securityType)
{
return Invariant($"No option type exists for underlying SecurityType: {securityType}");
}
/// <summary>
/// Returns a string message saying no underlying type exists for the given option SecurityType
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NoUnderlyingForOption(SecurityType securityType)
{
return Invariant($"No underlying type exists for option SecurityType: {securityType}");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SidNotForOption(QuantConnect.SecurityIdentifier sid)
{
return Invariant($"The provided SecurityIdentifier is not for an option: {sid}");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnderlyingSidDoesNotMatch(QuantConnect.SecurityIdentifier sid, QuantConnect.Symbol underlying)
{
return Invariant($"The provided SecurityIdentifier does not match the underlying symbol: {sid} != {underlying.ID}");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.SymbolCache"/> class and its consumers or related classes
/// </summary>
public static class SymbolCache
{
/// <summary>
/// Returns a string message saying the given ticker could not be localized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnableToLocateTicker(string ticker)
{
return $"We were unable to locate the ticker '{ticker}'.";
}
/// <summary>
/// Returns a string message saying mutiple potentially matching tickers were localized
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MultipleMatchingTickersLocated(IEnumerable<string> tickers)
{
return "We located multiple potentially matching tickers. " +
"For custom data, be sure to append a dot followed by the custom data type name. " +
$"For example: 'BTC.Bitcoin'. Potential Matches: {string.Join(", ", tickers)}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.SymbolRepresentation"/> class and its consumers or related classes
/// </summary>
public static class SymbolRepresentation
{
/// <summary>
/// Returns a string message saying SymbolRepresentation failed to get market for the given ticker and underlying
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string FailedToGetMarketForTickerAndUnderlying(string ticker, string underlying)
{
return $"Failed to get market for future '{ticker}' and underlying '{underlying}'";
}
/// <summary>
/// Returns a string message saying no market was found for the given ticker
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string NoMarketFound(string ticker)
{
return $"No market found for '{ticker}'";
}
/// <summary>
/// Returns a string message saying an unexpected security type was received by the given method name
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string UnexpectedSecurityTypeForMethod(string methodName, SecurityType securityType)
{
return Invariant($"{methodName} expects symbol to be an option, received {securityType}.");
}
/// <summary>
/// Returns a string message saying the given ticker is not in the expected OSI format
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidOSITickerFormat(string ticker)
{
return $"Invalid ticker format {ticker}";
}
/// <summary>
/// Returns a string message saying the given security type is not implemented
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SecurityTypeNotImplemented(SecurityType securityType)
{
return Invariant($"Security type {securityType} not implemented");
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.SymbolValueJsonConverter"/> class and its consumers or related classes
/// </summary>
public static class SymbolValueJsonConverter
{
/// <summary>
/// String message saying converter is write only
/// </summary>
public static string ConverterIsWriteOnly = "The SymbolValueJsonConverter is write-only.";
/// <summary>
/// String message saying converter is intended to be directly decorated in member
/// </summary>
public static string ConverterIsIntendedToBeDirectlyDecoratedInMember =
"The SymbolValueJsonConverter is intended to be decorated on the appropriate member directly.";
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.Time"/> class and its consumers or related classes
/// </summary>
public static class Time
{
/// <summary>
/// Invalid Bar Size string message
/// </summary>
public static string InvalidBarSize = "barSize must be greater than TimeSpan.Zero";
/// <summary>
/// Returns a string message containing the number of securities
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string SecurityCount(int count)
{
return $"Security Count: {count}";
}
}
/// <summary>
/// Provides user-facing messages for the <see cref="QuantConnect.TradingCalendar"/> class and its consumers or related classes
/// </summary>
public static class TradingCalendar
{
/// <summary>
/// Returns a string message for invalid total days
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidTotalDays(int totalDays)
{
return Invariant($@"Total days is negative ({totalDays}), indicating reverse start and end times. Check your usage of TradingCalendar to ensure proper arrangement of variables");
}
}
}
}
@@ -0,0 +1,49 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Securities.Positions;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using static QuantConnect.StringExtensions;
namespace QuantConnect
{
/// <summary>
/// Provides user-facing message construction methods and static messages for the <see cref="Securities.Positions"/> namespace
/// </summary>
public static partial class Messages
{
/// <summary>
/// Provides user-facing messages for the <see cref="Securities.Positions.PositionGroup"/> class and its consumers or related classes
/// </summary>
public static class PositionGroup
{
/// <summary>
/// Returns a string message saying the given quantity is invalid. It also contains the quantities from the
/// given positions as well as the unit quantities
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string InvalidQuantity(decimal quantity, IEnumerable<IPosition> positions)
{
return Invariant($@"The given quantity {quantity
} must be equal to the ratio between the quantity and unit quantity for each position. Quantities were {
string.Join(", ", positions.Select(position => position.Quantity))}. Unit quantities were {
string.Join(", ", positions.Select(position => position.UnitQuantity))}.");
}
}
}
}
File diff suppressed because it is too large Load Diff