diff --git a/Algorithm/QCAlgorithm.History.cs b/Algorithm/QCAlgorithm.History.cs index 41caa59528cc..077b4cbda32f 100644 --- a/Algorithm/QCAlgorithm.History.cs +++ b/Algorithm/QCAlgorithm.History.cs @@ -1474,7 +1474,7 @@ private void SetWarmup(int? barCount, TimeSpan? timeSpan, Resolution? resolution { if (_locked) { - throw new InvalidOperationException("QCAlgorithm.SetWarmup(): This method cannot be used after algorithm initialized"); + throw new InvalidOperationException(Messages.QCAlgorithm.SetWarmupAlreadyInitialized()); } _warmupTimeSpan = timeSpan; diff --git a/Algorithm/QCAlgorithm.cs b/Algorithm/QCAlgorithm.cs index 28ae1f6e0802..28f1c352f359 100644 --- a/Algorithm/QCAlgorithm.cs +++ b/Algorithm/QCAlgorithm.cs @@ -1315,7 +1315,7 @@ public void SetTimeZone(DateTimeZone timeZone) { if (_locked) { - throw new InvalidOperationException("Algorithm.SetTimeZone(): Cannot change time zone after algorithm running."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetTimeZoneAlreadyRunning()); } if (timeZone == null) throw new ArgumentNullException(nameof(timeZone)); @@ -1450,7 +1450,7 @@ public void SetBenchmark(SecurityType securityType, string symbol) { if (_locked) { - throw new InvalidOperationException("Algorithm.SetBenchmark(): Cannot change Benchmark after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetBenchmarkAlreadyInitialized()); } var market = GetMarket(null, symbol, securityType, defaultMarket: Market.USA); @@ -1503,7 +1503,7 @@ public void SetBenchmark(Symbol symbol) { if (_locked) { - throw new InvalidOperationException("Algorithm.SetBenchmark(): Cannot change Benchmark after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetBenchmarkAlreadyInitialized()); } // Create our security benchmark @@ -1522,7 +1522,7 @@ public void SetBenchmark(Func benchmark) { if (_locked) { - throw new InvalidOperationException("Algorithm.SetBenchmark(): Cannot change Benchmark after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetBenchmarkAlreadyInitialized()); } Benchmark = new FuncBenchmark(benchmark); @@ -1599,8 +1599,7 @@ public void SetAccountCurrency(string accountCurrency, decimal? startingCash = n { if (_locked) { - throw new InvalidOperationException("Algorithm.SetAccountCurrency(): " + - "Cannot change AccountCurrency after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetAccountCurrencyAlreadyInitialized()); } if (startingCash == null) @@ -1653,7 +1652,7 @@ public void SetCash(decimal startingCash) } else { - throw new InvalidOperationException("Algorithm.SetCash(): Cannot change cash available after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetCashAlreadyInitialized()); } } @@ -1672,7 +1671,7 @@ public void SetCash(string symbol, decimal startingCash, decimal conversionRate } else { - throw new InvalidOperationException("Algorithm.SetCash(): Cannot change cash available after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetCashAlreadyInitialized()); } } @@ -1778,7 +1777,7 @@ public void SetStartDate(DateTime start) } else { - throw new InvalidOperationException("Algorithm.SetStartDate(): Cannot change start date after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetStartDateAlreadyInitialized()); } } @@ -1797,7 +1796,7 @@ public void SetEndDate(DateTime end) //1. Check not locked already: if (_locked) { - throw new InvalidOperationException("Algorithm.SetEndDate(): Cannot change end date after algorithm initialized."); + throw new InvalidOperationException(Messages.QCAlgorithm.SetEndDateAlreadyInitialized()); } //Validate: diff --git a/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs b/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs index 6af94c1b877b..642f1a1918d0 100644 --- a/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs +++ b/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs @@ -901,7 +901,7 @@ public void OnMarginCall(List requests) // If the method does not return or returns a non-iterable PyObject, throw an exception if (result == null || !result.IsIterable()) { - throw new Exception("OnMarginCall must return a non-empty list of SubmitOrderRequest"); + throw new Exception(Messages.AlgorithmPythonWrapper.OnMarginCallMustReturnNonEmptyList()); } requests.Clear(); @@ -919,7 +919,7 @@ public void OnMarginCall(List requests) // If the PyObject is an empty list or its items are not SubmitOrderRequest objects, throw an exception if (requests.Count == 0) { - throw new Exception("OnMarginCall must return a non-empty list of SubmitOrderRequest"); + throw new Exception(Messages.AlgorithmPythonWrapper.OnMarginCallMustReturnNonEmptyList()); } } } diff --git a/Common/Messages/Messages.Algorithm.Framework.Portfolio.cs b/Common/Messages/Messages.Algorithm.Framework.Portfolio.cs index 18e71e6036dd..8c40abb2af5c 100644 --- a/Common/Messages/Messages.Algorithm.Framework.Portfolio.cs +++ b/Common/Messages/Messages.Algorithm.Framework.Portfolio.cs @@ -39,8 +39,8 @@ public static class PortfolioTarget public static string InvalidTargetPercent(IAlgorithm algorithm, decimal percent) { return Invariant($@"The portfolio target percent: { - percent}, does not comply with the current 'Algorithm.Settings' 'MaxAbsolutePortfolioTargetPercentage': { - algorithm.Settings.MaxAbsolutePortfolioTargetPercentage} or 'MinAbsolutePortfolioTargetPercentage': { + percent}, does not comply with the current '{FormatCodeRoot("Settings")}.{FormatCode("MaxAbsolutePortfolioTargetPercentage")}': { + algorithm.Settings.MaxAbsolutePortfolioTargetPercentage} or '{FormatCodeRoot("Settings")}.{FormatCode("MinAbsolutePortfolioTargetPercentage")}': { algorithm.Settings.MinAbsolutePortfolioTargetPercentage}. Skipping"); } diff --git a/Common/Messages/Messages.Algorithm.cs b/Common/Messages/Messages.Algorithm.cs new file mode 100644 index 000000000000..1f4b3e50fb17 --- /dev/null +++ b/Common/Messages/Messages.Algorithm.cs @@ -0,0 +1,110 @@ +/* + * 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 +{ + /// + /// Provides user-facing message construction methods and static messages for the namespace + /// + public static partial class Messages + { + /// + /// Provides user-facing messages for the class and its consumers or related classes + /// + public static class QCAlgorithm + { + /// + /// Returns a string message saying the time zone cannot be changed after the algorithm is running + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SetTimeZoneAlreadyRunning() + { + return $"{AlgorithmPrefix()}.{FormatCode("SetTimeZone")}(): Cannot change time zone after algorithm running."; + } + + /// + /// Returns a string message saying the benchmark cannot be changed after the algorithm is initialized + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SetBenchmarkAlreadyInitialized() + { + return $"{AlgorithmPrefix()}.{FormatCode("SetBenchmark")}(): Cannot change Benchmark after algorithm initialized."; + } + + /// + /// Returns a string message saying the account currency cannot be changed after the algorithm is initialized + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SetAccountCurrencyAlreadyInitialized() + { + return $"{AlgorithmPrefix()}.{FormatCode("SetAccountCurrency")}(): Cannot change AccountCurrency after algorithm initialized."; + } + + /// + /// Returns a string message saying the cash cannot be changed after the algorithm is initialized + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SetCashAlreadyInitialized() + { + return $"{AlgorithmPrefix()}.{FormatCode("SetCash")}(): Cannot change cash available after algorithm initialized."; + } + + /// + /// Returns a string message saying the start date cannot be changed after the algorithm is initialized + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SetStartDateAlreadyInitialized() + { + return $"{AlgorithmPrefix()}.{FormatCode("SetStartDate")}(): Cannot change start date after algorithm initialized."; + } + + /// + /// Returns a string message saying the end date cannot be changed after the algorithm is initialized + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SetEndDateAlreadyInitialized() + { + return $"{AlgorithmPrefix()}.{FormatCode("SetEndDate")}(): Cannot change end date after algorithm initialized."; + } + + /// + /// Returns a string message saying SetWarmup cannot be used after the algorithm is initialized + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string SetWarmupAlreadyInitialized() + { + return $"{AlgorithmPrefix()}.{FormatCode("SetWarmup")}(): This method cannot be used after algorithm initialized"; + } + } + + /// + /// Provides user-facing messages for the class + /// and its consumers or related classes + /// + public static class AlgorithmPythonWrapper + { + /// + /// Returns a string message saying OnMarginCall must return a non-empty list of SubmitOrderRequest + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string OnMarginCallMustReturnNonEmptyList() + { + return $"{FormatCode("OnMarginCall")} must return a non-empty list of SubmitOrderRequest"; + } + } + } +} diff --git a/Common/Messages/Messages.Brokerages.cs b/Common/Messages/Messages.Brokerages.cs index b1095cacbef5..e5528f99d851 100644 --- a/Common/Messages/Messages.Brokerages.cs +++ b/Common/Messages/Messages.Brokerages.cs @@ -163,7 +163,7 @@ 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 DailyPreciseEndTime = false or using {nameof(Schedule)}.{nameof(Schedule.On)}."); + 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))}."); } } @@ -411,7 +411,7 @@ public static class FxcmBrokerageModel [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string InvalidOrderQuantityForLotSize(Securities.Security security) { - return Invariant($"The order quantity must be a multiple of LotSize: [{security.SymbolProperties.LotSize}]."); + return Invariant($"The order quantity must be a multiple of {FormatCode("LotSize")}: [{security.SymbolProperties.LotSize}]."); } /// diff --git a/Common/Messages/Messages.Orders.cs b/Common/Messages/Messages.Orders.cs index 47033d5192eb..749d51416bd3 100644 --- a/Common/Messages/Messages.Orders.cs +++ b/Common/Messages/Messages.Orders.cs @@ -354,7 +354,7 @@ public static string ZeroQuantity(Orders.OrderRequest request) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string MissingSecurity(Orders.SubmitOrderRequest request) { - return Invariant($"You haven't requested {request.Symbol} data. Add this with AddSecurity() in the Initialize() Method."); + return Invariant($"You haven't requested {request.Symbol} data. Add this with {FormatCode("AddSecurity")}() in the {FormatCode("Initialize")}() method."); } /// @@ -365,8 +365,8 @@ public static string MissingSecurity(Orders.SubmitOrderRequest request) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string WarmingUp(Orders.OrderRequest request) { - return Invariant($@"This operation is not allowed in Initialize or during warm up: OrderRequest.{ - request.OrderRequestType}. Please move this code to the OnWarmupFinished() method."); + 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."); } } diff --git a/Common/Messages/Messages.QuantConnect.cs b/Common/Messages/Messages.QuantConnect.cs index 05743b63cd4e..e0380df49c88 100644 --- a/Common/Messages/Messages.QuantConnect.cs +++ b/Common/Messages/Messages.QuantConnect.cs @@ -30,6 +30,48 @@ namespace QuantConnect /// public static partial class Messages { + private static Language _algorithmLanguage = Language.CSharp; + + /// + /// Sets the algorithm language used to format code identifiers in error messages. + /// + public static void SetAlgorithmLanguage(Language language) + { + _algorithmLanguage = language; + } + + /// + /// Returns the code identifier formatted for the current algorithm language. + /// For Python, converts PascalCase/camelCase to snake_case. + /// + 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 value) where T : Enum + { + return FormatCode(value.ToString()); + } + + private static string AlgorithmPrefix() + { + return _algorithmLanguage == Language.Python ? "self" : "QCAlgorithm"; + } + /// /// Provides user-facing messages for the class and its consumers or related classes /// @@ -187,8 +229,8 @@ public static string RemoveInvalidOperation(ExtendedDictionary @@ -282,7 +324,7 @@ public static string DownloadDataFailed(string url) 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 SetHoldings) warm up your algorithm with SetWarmup, or use slice.Contains(symbol) " + + $"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 " + @@ -724,7 +766,7 @@ public static string ErrorParsingSecurityIdentifier(string value, Exception exce [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.Add(string,int)"; + 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)"; } } diff --git a/Common/Messages/Messages.Securities.cs b/Common/Messages/Messages.Securities.cs index f2301b68c1b3..2e844357aad6 100644 --- a/Common/Messages/Messages.Securities.cs +++ b/Common/Messages/Messages.Securities.cs @@ -110,7 +110,7 @@ public static string TargetOrderMarginNotAboveMinimum(decimal absDifferenceOfMar public static string TargetOrderMarginNotAboveMinimum() { return "Warning: Portfolio rebalance result ignored as it resulted in a single share trade recommendation which can generate high fees." + - " To disable minimum order size checks please set Settings.MinimumOrderMarginPortfolioPercentage = 0."; + $" To disable minimum order size checks please set {FormatCodeRoot("Settings")}.{FormatCode("MinimumOrderMarginPortfolioPercentage")} = 0."; } /// @@ -886,8 +886,11 @@ public static class SecurityPortfolioManager /// Returns a string message saying the AccountCurrency cannot be changed after adding a Security and that the method /// SetAccountCurrency() should be moved before AddSecurity() /// - public static string CannotChangeAccountCurrencyAfterAddingSecurity = - "Cannot change AccountCurrency after adding a Security. Please move SetAccountCurrency() before AddSecurity()."; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string CannotChangeAccountCurrencyAfterAddingSecurity() + { + return $"Cannot change AccountCurrency after adding a Security. Please move {FormatCode("SetAccountCurrency")}() before {FormatCode("AddSecurity")}()."; + } /// /// Returns a string message saying the AccountCurrency has been changed after setting cash, reporting the @@ -970,8 +973,11 @@ public static class SecurityTransactionManager /// /// Returns a string message saying CancelOpenOrders operation is not allowed in Initialize or during warm up /// - public static string CancelOpenOrdersNotAllowedOnInitializeOrWarmUp = - "This operation is not allowed in Initialize or during warm up: CancelOpenOrders. Please move this code to the OnWarmupFinished() method."; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string CancelOpenOrdersNotAllowedOnInitializeOrWarmUp() + { + return $"This operation is not allowed in {FormatCode("Initialize")} or during warm up: {FormatCode("CancelOpenOrders")}. Please move this code to the {FormatCode("OnWarmupFinished")}() method."; + } /// /// Returns a string message saying the order was canceled by the CancelOpenOrders() at the given time @@ -1009,17 +1015,29 @@ public static class SymbolProperties /// /// String message saying the SymbolProperties LotSize can not be less than or equal to 0 /// - public static string InvalidLotSize = "SymbolProperties LotSize can not be less than or equal to 0"; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string InvalidLotSize() + { + return $"{FormatCode("SymbolProperties")} {FormatCode("LotSize")} can not be less than or equal to 0"; + } /// /// String message saying the SymbolProperties PriceMagnifier can not be less than or equal to 0 /// - public static string InvalidPriceMagnifier = "SymbolProprties PriceMagnifier can not be less than or equal to 0"; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string InvalidPriceMagnifier() + { + return $"{FormatCode("SymbolProperties")} {FormatCode("PriceMagnifier")} can not be less than or equal to 0"; + } /// /// String message saying the SymbolProperties StrikeMultiplier can not be less than or equal to 0 /// - public static string InvalidStrikeMultiplier = "SymbolProperties StrikeMultiplier can not be less than or equal to 0"; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string InvalidStrikeMultiplier() + { + return $"{FormatCode("SymbolProperties")} {FormatCode("StrikeMultiplier")} can not be less than or equal to 0"; + } /// /// Parses a given SymbolProperties object into a string message diff --git a/Common/Securities/SecurityPortfolioManager.cs b/Common/Securities/SecurityPortfolioManager.cs index 49638f6b3bac..66fa8dd9b084 100644 --- a/Common/Securities/SecurityPortfolioManager.cs +++ b/Common/Securities/SecurityPortfolioManager.cs @@ -648,7 +648,7 @@ public void SetAccountCurrency(string accountCurrency, decimal? startingCash = n if (Securities.Count > 0) { throw new InvalidOperationException("SecurityPortfolioManager.SetAccountCurrency(): " + - Messages.SecurityPortfolioManager.CannotChangeAccountCurrencyAfterAddingSecurity); + Messages.SecurityPortfolioManager.CannotChangeAccountCurrencyAfterAddingSecurity()); } // Capture the previous base cash and amount if SetCash() was called earlier so we can diff --git a/Common/Securities/SecurityTransactionManager.cs b/Common/Securities/SecurityTransactionManager.cs index 4917cd2048f9..6c19823fafc2 100644 --- a/Common/Securities/SecurityTransactionManager.cs +++ b/Common/Securities/SecurityTransactionManager.cs @@ -251,7 +251,7 @@ public List CancelOpenOrders() { if (_algorithm != null && _algorithm.IsWarmingUp) { - throw new InvalidOperationException(Messages.SecurityTransactionManager.CancelOpenOrdersNotAllowedOnInitializeOrWarmUp); + throw new InvalidOperationException(Messages.SecurityTransactionManager.CancelOpenOrdersNotAllowedOnInitializeOrWarmUp()); } var cancelledOrders = new List(); @@ -273,7 +273,7 @@ public List CancelOpenOrders(Symbol symbol, string tag = null) { if (_algorithm != null && _algorithm.IsWarmingUp) { - throw new InvalidOperationException(Messages.SecurityTransactionManager.CancelOpenOrdersNotAllowedOnInitializeOrWarmUp); + throw new InvalidOperationException(Messages.SecurityTransactionManager.CancelOpenOrdersNotAllowedOnInitializeOrWarmUp()); } var cancelledOrders = new List(); diff --git a/Common/Securities/SymbolProperties.cs b/Common/Securities/SymbolProperties.cs index 9c3db7e38b65..d17642b4f27a 100644 --- a/Common/Securities/SymbolProperties.cs +++ b/Common/Securities/SymbolProperties.cs @@ -171,7 +171,7 @@ public SymbolPropertiesHolder(string description, string quoteCurrency, decimal if (LotSize <= 0) { - throw new ArgumentException(Messages.SymbolProperties.InvalidLotSize); + throw new ArgumentException(Messages.SymbolProperties.InvalidLotSize()); } MarketTicker = marketTicker; @@ -180,13 +180,13 @@ public SymbolPropertiesHolder(string description, string quoteCurrency, decimal PriceMagnifier = priceMagnifier; if (PriceMagnifier <= 0) { - throw new ArgumentException(Messages.SymbolProperties.InvalidPriceMagnifier); + throw new ArgumentException(Messages.SymbolProperties.InvalidPriceMagnifier()); } StrikeMultiplier = strikeMultiplier; if (strikeMultiplier <= 0) { - throw new ArgumentException(Messages.SymbolProperties.InvalidStrikeMultiplier); + throw new ArgumentException(Messages.SymbolProperties.InvalidStrikeMultiplier()); } } } diff --git a/Engine/Engine.cs b/Engine/Engine.cs index b3f9a15fe8dd..6de6c7237dbf 100644 --- a/Engine/Engine.cs +++ b/Engine/Engine.cs @@ -91,8 +91,9 @@ public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemb try { + Messages.SetAlgorithmLanguage(job.Language); Log.Trace($"Engine.Run(): Resource limits '{job.Controls.CpuAllocation}' CPUs. {job.Controls.RamAllocation} MB RAM."); - TextSubscriptionDataSourceReader.SetCacheSize((int) (job.RamAllocation * 0.4)); + TextSubscriptionDataSourceReader.SetCacheSize((int)(job.RamAllocation * 0.4)); //Reset thread holders. var initializeComplete = false; @@ -101,7 +102,7 @@ public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemb SystemHandlers.Notify.SetAuthentication(job); //-> Set the result handler type for this algorithm job, and launch the associated result thread. - AlgorithmHandlers.Results.Initialize(new (job, SystemHandlers.Notify, SystemHandlers.Api, AlgorithmHandlers.Transactions, AlgorithmHandlers.MapFileProvider)); + AlgorithmHandlers.Results.Initialize(new(job, SystemHandlers.Notify, SystemHandlers.Api, AlgorithmHandlers.Transactions, AlgorithmHandlers.MapFileProvider)); IBrokerage brokerage = null; DataManager dataManager = null; @@ -186,7 +187,7 @@ public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemb AlgorithmHandlers.FactorFileProvider, AlgorithmHandlers.DataProvider, dataManager, - (IDataFeedTimeProvider) synchronizer, + (IDataFeedTimeProvider)synchronizer, AlgorithmHandlers.DataPermissionsManager.DataChannelProvider); // set the history provider before setting up the algorithm @@ -359,7 +360,7 @@ public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemb } Log.Trace("Engine.Run(): Exiting Algorithm Manager"); - }, job.Controls.RamAllocation, workerThread:workerThread, sleepIntervalMillis: algorithm.LiveMode ? 10000 : 1000); + }, job.Controls.RamAllocation, workerThread: workerThread, sleepIntervalMillis: algorithm.LiveMode ? 10000 : 1000); if (!complete) { @@ -396,7 +397,7 @@ public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemb //Diagnostics Completed, Send Result Packet: var totalSeconds = (DateTime.UtcNow - startTime).TotalSeconds; var dataPoints = algorithmManager.DataPoints + algorithm.HistoryProvider.DataPointCount; - var kps = dataPoints / (double) 1000 / totalSeconds; + var kps = dataPoints / (double)1000 / totalSeconds; AlgorithmHandlers.Results.DebugMessage($"Algorithm Id:({job.AlgorithmId}) completed in {totalSeconds:F2} seconds at {kps:F0}k data points per second. Processing total of {dataPoints:N0} data points."); } } @@ -426,7 +427,7 @@ public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemb || (AlgorithmHandlers.Transactions != null && AlgorithmHandlers.Transactions.IsActive) || (AlgorithmHandlers.DataFeed != null && AlgorithmHandlers.DataFeed.IsActive) || (AlgorithmHandlers.RealTime != null && AlgorithmHandlers.RealTime.IsActive)) - && millisecondTotalWait < 30*1000) + && millisecondTotalWait < 30 * 1000) { Thread.Sleep(millisecondInterval); if (millisecondTotalWait % (millisecondInterval * 10) == 0) diff --git a/Research/QuantBook.cs b/Research/QuantBook.cs index c3266e4a7533..dafdea31339e 100644 --- a/Research/QuantBook.cs +++ b/Research/QuantBook.cs @@ -92,6 +92,7 @@ public QuantBook() : base() { try { + Messages.SetAlgorithmLanguage(_isPythonNotebook ? Language.Python : Language.CSharp); using (Py.GIL()) { _pandas = Py.Import("pandas"); diff --git a/Tests/Common/Orders/OrderTicketTests.cs b/Tests/Common/Orders/OrderTicketTests.cs index 86a07f11486a..e15963cad5f0 100644 --- a/Tests/Common/Orders/OrderTicketTests.cs +++ b/Tests/Common/Orders/OrderTicketTests.cs @@ -26,10 +26,16 @@ public class OrderTicketTests { private DateTime _requestTime = new DateTime(2022, 08, 25, 15, 0, 0); + [TearDown] + public void TearDown() + { + Messages.SetAlgorithmLanguage(Language.CSharp); + } + [Test] public void TestInvalidUpdateOrderId() { - var updateFields = new UpdateOrderFields { Quantity = 99, Tag = "Pepe", StopPrice = 77 , LimitPrice = 55 }; + var updateFields = new UpdateOrderFields { Quantity = 99, Tag = "Pepe", StopPrice = 77, LimitPrice = 55 }; var updateRequest = new UpdateOrderRequest(_requestTime, 11, updateFields); var ticket = OrderTicket.InvalidUpdateOrderId(null, updateRequest); Assert.AreEqual(11, ticket.OrderId); @@ -101,6 +107,10 @@ public void TestInvalidWarmingUp() Assert.AreEqual(1000, ticket.SubmitRequest.Quantity); Assert.AreEqual("Pepe", ticket.SubmitRequest.Tag); Assert.AreEqual("This operation is not allowed in Initialize or during warm up: OrderRequest.Submit. Please move this code to the OnWarmupFinished() method.", ticket.SubmitRequest.Response.ErrorMessage); + // Verify Python snake_case formatting + Messages.SetAlgorithmLanguage(Language.Python); + var pythonResponse = OrderResponse.WarmingUp(orderRequest); + Assert.AreEqual("This operation is not allowed in initialize or during warm up: OrderRequest.submit. Please move this code to the on_warmup_finished() method.", pythonResponse.ErrorMessage); } [TestCase(8, 0, true, Description = "8 AM - valid submission")]