diff --git a/Algorithm/QCAlgorithm.cs b/Algorithm/QCAlgorithm.cs index d495edb1dca4..37883f9e704e 100644 --- a/Algorithm/QCAlgorithm.cs +++ b/Algorithm/QCAlgorithm.cs @@ -152,7 +152,7 @@ public partial class QCAlgorithm : MarshalByRefObject, IAlgorithm private TimeSpan? _warmupTimeSpan; private int? _warmupBarCount; private Dictionary _parameters = new Dictionary(); - private bool _brokerageDataSet; + private bool _deploymentDetailsSet; private SecurityDefinitionSymbolResolver _securityDefinitionSymbolResolver; private SecurityDefinitionSymbolResolver SecurityDefinitionSymbolResolver @@ -750,11 +750,11 @@ public ConcurrentQueue ErrorMessages public ObjectStore ObjectStore { get; private set; } /// - /// Gets a read-only view of the brokerage data shared by the brokerage, data queue handler or any other component, + /// Gets a read-only view of the deployment details shared by the brokerage, data queue handler or any other component, /// for example account information. Usually empty when not running in live mode /// [DocumentationAttribute(LiveTrading)] - public ReadOnlyExtendedDictionary BrokerageData { get; private set; } = new(); + public ReadOnlyExtendedDictionary DeploymentDetails { get; private set; } = new(); /// /// The current statistics for the running algorithm. @@ -927,22 +927,22 @@ public ReadOnlyExtendedDictionary GetParameters() } /// - /// Sets the brokerage data read-only view. Can only be set once, it's shared by the engine + /// Sets the deployment details read-only view. Can only be set once, it's shared by the engine /// - /// The brokerage data + /// The deployment details [DocumentationAttribute(LiveTrading)] - public void SetBrokerageData(ReadOnlyExtendedDictionary brokerageData) + public void SetDeploymentDetails(ReadOnlyExtendedDictionary deploymentDetails) { - if (brokerageData == null) + if (deploymentDetails == null) { - throw new ArgumentNullException(nameof(brokerageData)); + throw new ArgumentNullException(nameof(deploymentDetails)); } - if (_brokerageDataSet && !ReferenceEquals(BrokerageData, brokerageData)) + if (_deploymentDetailsSet && !ReferenceEquals(DeploymentDetails, deploymentDetails)) { - throw new InvalidOperationException("QCAlgorithm.SetBrokerageData(): the brokerage data has already been set, it can only be set once"); + throw new InvalidOperationException("QCAlgorithm.SetDeploymentDetails(): the deployment details have already been set, they can only be set once"); } - BrokerageData = brokerageData; - _brokerageDataSet = true; + DeploymentDetails = deploymentDetails; + _deploymentDetailsSet = true; } /// diff --git a/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs b/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs index cf47abc0b929..5315c8a59ca3 100644 --- a/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs +++ b/AlgorithmFactory/Python/Wrappers/AlgorithmPythonWrapper.cs @@ -427,10 +427,10 @@ public Exception RunTimeError public ObjectStore ObjectStore => _baseAlgorithm.ObjectStore; /// - /// Gets a read-only view of the brokerage data shared by the brokerage, data queue handler or any other component, + /// Gets a read-only view of the deployment details shared by the brokerage, data queue handler or any other component, /// for example account information. Usually empty when not running in live mode /// - public ReadOnlyExtendedDictionary BrokerageData => _baseAlgorithm.BrokerageData; + public ReadOnlyExtendedDictionary DeploymentDetails => _baseAlgorithm.DeploymentDetails; /// /// Returns the current Slice object @@ -1171,10 +1171,10 @@ public void SetFinishedWarmingUp() public void SetParameters(Dictionary parameters) => _baseAlgorithm.SetParameters(parameters); /// - /// Sets the brokerage data read-only view + /// Sets the deployment details read-only view /// - /// The brokerage data - public void SetBrokerageData(ReadOnlyExtendedDictionary brokerageData) => _baseAlgorithm.SetBrokerageData(brokerageData); + /// The deployment details + public void SetDeploymentDetails(ReadOnlyExtendedDictionary deploymentDetails) => _baseAlgorithm.SetDeploymentDetails(deploymentDetails); /// /// Tries to convert a PyObject into a C# object diff --git a/Common/AlgorithmConfiguration.cs b/Common/AlgorithmConfiguration.cs index 2be4b733438f..4d330d00a5a3 100644 --- a/Common/AlgorithmConfiguration.cs +++ b/Common/AlgorithmConfiguration.cs @@ -63,10 +63,10 @@ public class AlgorithmConfiguration public IReadOnlyDictionary Parameters { get; set; } /// - /// The brokerage data used by the live algorithm, if any + /// The deployment details of the live algorithm, if any /// [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public IReadOnlyDictionary BrokerageData { get; set; } + public IReadOnlyDictionary DeploymentDetails { get; set; } /// /// Backtest maximum end date @@ -102,10 +102,10 @@ public class AlgorithmConfiguration public AlgorithmConfiguration(string name, ISet tags, string accountCurrency, BrokerageName brokerageName, AccountType accountType, IReadOnlyDictionary parameters, DateTime startDate, DateTime endDate, DateTime? outOfSampleMaxEndDate, int outOfSampleDays = 0, int tradingDaysPerYear = 0, - IReadOnlyDictionary brokerageData = null) + IReadOnlyDictionary deploymentDetails = null) { Name = name; - BrokerageData = brokerageData; + DeploymentDetails = deploymentDetails; Tags = tags; OutOfSampleMaxEndDate = outOfSampleMaxEndDate; TradingDaysPerYear = tradingDaysPerYear; @@ -149,7 +149,7 @@ public static AlgorithmConfiguration Create(IAlgorithm algorithm, BacktestNodePa // use value = 252 like default for backwards compatibility algorithm?.Settings?.TradingDaysPerYear ?? 252, // only included when set, live mode. We take a snapshot since the algorithm's instance can be updated later on - algorithm.BrokerageData?.Count > 0 ? new Dictionary(algorithm.BrokerageData) : null); + algorithm.DeploymentDetails?.Count > 0 ? new Dictionary(algorithm.DeploymentDetails) : null); } } } diff --git a/Common/Interfaces/IAlgorithm.cs b/Common/Interfaces/IAlgorithm.cs index b40311b1bed8..d388dcdbfd0c 100644 --- a/Common/Interfaces/IAlgorithm.cs +++ b/Common/Interfaces/IAlgorithm.cs @@ -407,10 +407,10 @@ InsightManager Insights ObjectStore ObjectStore { get; } /// - /// Gets a read-only view of the brokerage data shared by the brokerage, data queue handler or any other component, + /// Gets a read-only view of the deployment details shared by the brokerage, data queue handler or any other component, /// for example account information. Usually empty when not running in live mode /// - ReadOnlyExtendedDictionary BrokerageData { get; } + ReadOnlyExtendedDictionary DeploymentDetails { get; } /// /// Returns the current Slice object @@ -481,10 +481,10 @@ InsightManager Insights void SetParameters(Dictionary parameters); /// - /// Sets the brokerage data read-only view + /// Sets the deployment details read-only view /// - /// The brokerage data - void SetBrokerageData(ReadOnlyExtendedDictionary brokerageData); + /// The deployment details + void SetDeploymentDetails(ReadOnlyExtendedDictionary deploymentDetails); /// /// Determines if the Symbol is shortable at the brokerage diff --git a/Engine/Engine.cs b/Engine/Engine.cs index 089b260205db..61deaa74c56f 100644 --- a/Engine/Engine.cs +++ b/Engine/Engine.cs @@ -126,8 +126,8 @@ public void Run(AlgorithmNodePacket job, AlgorithmManager manager, string assemb algorithm.ProjectId = job.ProjectId; - // share the brokerage data with the algorithm right away so it's available during initialization - algorithm.SetBrokerageData(AlgorithmHandlers.Results.BrokerageData); + // share the deployment details with the algorithm right away so it's available during initialization + algorithm.SetDeploymentDetails(AlgorithmHandlers.Results.DeploymentDetails); // Set algorithm in ILeanManager SystemHandlers.LeanManager.SetAlgorithm(algorithm); diff --git a/Engine/Results/BaseResultsHandler.cs b/Engine/Results/BaseResultsHandler.cs index 7c0a73f3f7ee..59cebaab00db 100644 --- a/Engine/Results/BaseResultsHandler.cs +++ b/Engine/Results/BaseResultsHandler.cs @@ -250,14 +250,14 @@ protected Bar CurrentAlgorithmEquity protected Dictionary State { get; set; } /// - /// Brokerage data shared with the user and the algorithm, see + /// Deployment details shared with the user and the algorithm, see /// - private readonly Dictionary _brokerageData = new(); + private readonly Dictionary _deploymentDetails = new(); /// - /// Read only view of the brokerage data, see . Shared with the algorithm + /// Read only view of the deployment details, see . Shared with the algorithm /// - public ReadOnlyExtendedDictionary BrokerageData { get; } + public ReadOnlyExtendedDictionary DeploymentDetails { get; } /// /// The handler responsible for communicating messages to listeners @@ -338,7 +338,7 @@ protected BaseResultsHandler() Messages = new ConcurrentQueue(); RuntimeStatistics = new Dictionary(); // same instance, so any entries added later are visible through the view - BrokerageData = new ReadOnlyExtendedDictionary(_brokerageData, copy: false); + DeploymentDetails = new ReadOnlyExtendedDictionary(_deploymentDetails, copy: false); StartTime = DateTime.UtcNow; CompileId = ""; AlgorithmId = ""; @@ -557,32 +557,32 @@ public virtual void SetAlgorithm(IAlgorithm algorithm, decimal startingPortfolio } /// - /// Adds or updates a brokerage data entry. Key value pairs the brokerage, data queue handler or any other component + /// Adds or updates a deployment detail entry. Key value pairs the brokerage, data queue handler or any other component /// wants to share with the user, through the results, and the algorithm, for example account information. /// Sensitive data, like credentials, should never be added /// - /// The brokerage data key - /// The brokerage data value - public virtual void AddBrokerageData(string key, string value) + /// The deployment detail key + /// The deployment detail value + public virtual void AddDeploymentDetail(string key, string value) { if (string.IsNullOrEmpty(key)) { return; } - lock (_brokerageData) + lock (_deploymentDetails) { - _brokerageData[key] = value ?? string.Empty; + _deploymentDetails[key] = value ?? string.Empty; } } /// - /// Creates the algorithm configuration to include in the results, taking a snapshot of the current brokerage data + /// Creates the algorithm configuration to include in the results, taking a snapshot of the current deployment details /// /// The associated backtest node packet if any /// A new instance protected AlgorithmConfiguration CreateAlgorithmConfiguration(BacktestNodePacket backtestNodePacket = null) { - lock (_brokerageData) + lock (_deploymentDetails) { return AlgorithmConfiguration.Create(Algorithm, backtestNodePacket); } diff --git a/Engine/Results/DeploymentDetailsHelper.cs b/Engine/Results/DeploymentDetailsHelper.cs new file mode 100644 index 000000000000..51089337aaf5 --- /dev/null +++ b/Engine/Results/DeploymentDetailsHelper.cs @@ -0,0 +1,61 @@ +/* + * 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.Threading; +using QuantConnect.Util; +using QuantConnect.Logging; + +namespace QuantConnect.Lean.Engine.Results +{ + /// + /// Helper to share deployment details with the user and the algorithm, see + /// + public static class DeploymentDetailsHelper + { + private static int _missingResultHandlerLogged; + + /// + /// Adds or updates a deployment detail entry on the result handler loaded in the , if any. + /// Key value pairs the brokerage, data queue handler or any other component wants to share with the user, + /// through the results, and the algorithm, for example account information. + /// Sensitive data, like credentials, should never be added + /// + /// Will never throw, callers are not expected to handle any failure sharing a deployment detail + /// The deployment detail key + /// The deployment detail value + public static void Add(string key, string value) + { + try + { + var resultHandler = Composer.Instance.GetPart(); + if (resultHandler == null) + { + // we only log this once, else we would spam for every entry + if (Interlocked.Exchange(ref _missingResultHandlerLogged, 1) == 0) + { + Log.Error($"DeploymentDetailsHelper.Add(): no result handler was found, deployment details will be ignored"); + } + return; + } + resultHandler.AddDeploymentDetail(key, value); + } + catch (Exception exception) + { + Log.Error(exception, $"Failed to add deployment detail '{key}'"); + } + } + } +} diff --git a/Engine/Results/IResultHandler.cs b/Engine/Results/IResultHandler.cs index 59c28af4d1ca..a3a1ef8291db 100644 --- a/Engine/Results/IResultHandler.cs +++ b/Engine/Results/IResultHandler.cs @@ -143,18 +143,18 @@ bool IsActive void RuntimeStatistic(string key, string value); /// - /// Adds or updates a brokerage data entry. Key value pairs the brokerage, data queue handler or any other component + /// Adds or updates a deployment detail entry. Key value pairs the brokerage, data queue handler or any other component /// wants to share with the user, through the results, and the algorithm, for example account information. /// Sensitive data, like credentials, should never be added /// - /// The brokerage data key - /// The brokerage data value - void AddBrokerageData(string key, string value); + /// The deployment detail key + /// The deployment detail value + void AddDeploymentDetail(string key, string value); /// - /// Read only view of the brokerage data, see . Shared with the algorithm + /// Read only view of the deployment details, see . Shared with the algorithm /// - ReadOnlyExtendedDictionary BrokerageData { get; } + ReadOnlyExtendedDictionary DeploymentDetails { get; } /// /// Send a new order event. diff --git a/Tests/Common/AlgorithmConfigurationTests.cs b/Tests/Common/AlgorithmConfigurationTests.cs index 45215aaf32fe..8a6b2b8c4ca1 100644 --- a/Tests/Common/AlgorithmConfigurationTests.cs +++ b/Tests/Common/AlgorithmConfigurationTests.cs @@ -109,37 +109,37 @@ public void JsonRoundtrip(bool backwardsCompatible) } [Test] - public void BrokerageDataIsOnlyIncludedWhenSet() + public void DeploymentDetailsAreOnlyIncludedWhenSet() { var algorithm = new QCAlgorithm(); // not set, e.g. backtesting var algorithmConfiguration = AlgorithmConfiguration.Create(algorithm, null); - Assert.IsNull(algorithmConfiguration.BrokerageData); + Assert.IsNull(algorithmConfiguration.DeploymentDetails); var serialized = JsonConvert.SerializeObject(algorithmConfiguration); - Assert.IsFalse(serialized.Contains("BrokerageData", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsFalse(serialized.Contains("DeploymentDetails", StringComparison.InvariantCultureIgnoreCase)); // set, e.g. live trading - var brokerageData = new Dictionary { { "some-key", "some value" }, { "some-other-key", "another value" } }; - algorithm.SetBrokerageData(new ReadOnlyExtendedDictionary(brokerageData, copy: false)); + var deploymentDetails = new Dictionary { { "some-key", "some value" }, { "some-other-key", "another value" } }; + algorithm.SetDeploymentDetails(new ReadOnlyExtendedDictionary(deploymentDetails, copy: false)); algorithmConfiguration = AlgorithmConfiguration.Create(algorithm, null); - CollectionAssert.AreEquivalent(brokerageData, algorithmConfiguration.BrokerageData); + CollectionAssert.AreEquivalent(deploymentDetails, algorithmConfiguration.DeploymentDetails); // the configuration holds a snapshot, later changes are reflected by the algorithm but not by the existing configuration - brokerageData.Remove("some-other-key"); - brokerageData["some-key"] = ""; - Assert.AreEqual(2, algorithmConfiguration.BrokerageData.Count); - Assert.AreEqual("some value", algorithmConfiguration.BrokerageData["some-key"]); - CollectionAssert.AreEquivalent(brokerageData, algorithm.BrokerageData); + deploymentDetails.Remove("some-other-key"); + deploymentDetails["some-key"] = ""; + Assert.AreEqual(2, algorithmConfiguration.DeploymentDetails.Count); + Assert.AreEqual("some value", algorithmConfiguration.DeploymentDetails["some-key"]); + CollectionAssert.AreEquivalent(deploymentDetails, algorithm.DeploymentDetails); algorithmConfiguration = AlgorithmConfiguration.Create(algorithm, null); - CollectionAssert.AreEquivalent(brokerageData, algorithmConfiguration.BrokerageData); + CollectionAssert.AreEquivalent(deploymentDetails, algorithmConfiguration.DeploymentDetails); serialized = JsonConvert.SerializeObject(algorithmConfiguration); - Assert.IsTrue(serialized.Contains("\"BrokerageData\":{\"some-key\":\"\"}", StringComparison.InvariantCulture)); + Assert.IsTrue(serialized.Contains("\"DeploymentDetails\":{\"some-key\":\"\"}", StringComparison.InvariantCulture)); var deserialized = JsonConvert.DeserializeObject(serialized); - CollectionAssert.AreEquivalent(brokerageData, deserialized.BrokerageData); + CollectionAssert.AreEquivalent(deploymentDetails, deserialized.DeploymentDetails); } private static TestCaseData[] AlgorithmConfigurationTestCases => new[] diff --git a/Tests/Engine/AlgorithmManagerTests.cs b/Tests/Engine/AlgorithmManagerTests.cs index 7ecf3fe7b42d..9e9272b903f3 100644 --- a/Tests/Engine/AlgorithmManagerTests.cs +++ b/Tests/Engine/AlgorithmManagerTests.cs @@ -236,11 +236,11 @@ public void SendStatusUpdate(AlgorithmStatus status, string message = "") { } - public void AddBrokerageData(string key, string value) + public void AddDeploymentDetail(string key, string value) { } - public ReadOnlyExtendedDictionary BrokerageData { get; } = new(); + public ReadOnlyExtendedDictionary DeploymentDetails { get; } = new(); public void RuntimeStatistic(string key, string value) { diff --git a/Tests/Engine/Results/DeploymentDetailsHelperTests.cs b/Tests/Engine/Results/DeploymentDetailsHelperTests.cs new file mode 100644 index 000000000000..31483bb52d81 --- /dev/null +++ b/Tests/Engine/Results/DeploymentDetailsHelperTests.cs @@ -0,0 +1,46 @@ +/* + * 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 NUnit.Framework; +using QuantConnect.Util; +using QuantConnect.Lean.Engine.Results; + +namespace QuantConnect.Tests.Engine.Results +{ + [TestFixture] + public class DeploymentDetailsHelperTests + { + [Test] + public void AddsToTheResultHandlerInTheComposer() + { + // we explicitly use the result handler the composer resolves, adding one if there is none, + // instead of resetting the composer which would drop the parts other tests rely on + var resultHandler = Composer.Instance.GetPart(); + if (resultHandler == null) + { + resultHandler = new TestResultHandler(); + Composer.Instance.AddPart(resultHandler); + } + + DeploymentDetailsHelper.Add("account", "123"); + DeploymentDetailsHelper.Add("environment", "paper"); + // updates in place + DeploymentDetailsHelper.Add("account", "456"); + + Assert.AreEqual("456", resultHandler.DeploymentDetails["account"]); + Assert.AreEqual("paper", resultHandler.DeploymentDetails["environment"]); + } + } +} diff --git a/Tests/Engine/Results/LiveTradingResultHandlerTests.cs b/Tests/Engine/Results/LiveTradingResultHandlerTests.cs index d590475a86e1..4a090915f46e 100644 --- a/Tests/Engine/Results/LiveTradingResultHandlerTests.cs +++ b/Tests/Engine/Results/LiveTradingResultHandlerTests.cs @@ -526,14 +526,14 @@ public void StoredResultsCarryAlgorithmConfigurationFromTheStart() resultHandler.Initialize(new(job, messaging, api, transactionHandler, null)); // the engine shares the view right after creating the algorithm - algorithm.SetBrokerageData(resultHandler.BrokerageData); + algorithm.SetDeploymentDetails(resultHandler.DeploymentDetails); // e.g. the brokerage or data queue handler, which are created before the algorithm is set - resultHandler.AddBrokerageData("some-key", "some value"); + resultHandler.AddDeploymentDetail("some-key", "some value"); resultHandler.SetAlgorithm(algorithm, 100000); algorithm.SetLocked(); - var expectedBrokerageData = new Dictionary { { "some-key", "some value" } }; - CollectionAssert.AreEquivalent(expectedBrokerageData, algorithm.BrokerageData); + var expectedDeploymentDetails = new Dictionary { { "some-key", "some value" } }; + CollectionAssert.AreEquivalent(expectedDeploymentDetails, algorithm.DeploymentDetails); // the first update pass stores the status file and the complete results right away, no final result required var expected = new[] { $"{deployId}.json", $"{deployId}-{DateTime.UtcNow:yyyy-MM-dd}_minute.json" }; @@ -544,7 +544,7 @@ public void StoredResultsCarryAlgorithmConfigurationFromTheStart() foreach (var result in resultHandler.GetStoredResults(name)) { Assert.IsNotNull(result.AlgorithmConfiguration, $"'{name}' is missing the algorithm configuration"); - CollectionAssert.AreEquivalent(expectedBrokerageData, result.AlgorithmConfiguration.BrokerageData); + CollectionAssert.AreEquivalent(expectedDeploymentDetails, result.AlgorithmConfiguration.DeploymentDetails); Assert.AreEqual("10", result.AlgorithmConfiguration.Parameters["ema-fast"]); } } @@ -556,7 +556,7 @@ public void StoredResultsCarryAlgorithmConfigurationFromTheStart() } [Test] - public void BrokerageDataIsSharedWithTheAlgorithmAndTheResults() + public void DeploymentDetailsAreSharedWithTheAlgorithmAndTheResults() { using var api = new Api.Api(); using var messaging = new QuantConnect.Messaging.Messaging(); @@ -566,37 +566,37 @@ public void BrokerageDataIsSharedWithTheAlgorithmAndTheResults() var algorithm = new AlgorithmStub(); algorithm.SetFinishedWarmingUp(); - Assert.IsEmpty(algorithm.BrokerageData); - Assert.IsEmpty(resultHandler.BrokerageData); + Assert.IsEmpty(algorithm.DeploymentDetails); + Assert.IsEmpty(resultHandler.DeploymentDetails); // the engine shares the view right after creating the algorithm, so it's available during initialization - algorithm.SetBrokerageData(resultHandler.BrokerageData); - resultHandler.AddBrokerageData("account", "123"); - Assert.AreEqual("123", algorithm.BrokerageData["account"]); - Assert.AreEqual("123", resultHandler.BrokerageData["account"]); + algorithm.SetDeploymentDetails(resultHandler.DeploymentDetails); + resultHandler.AddDeploymentDetail("account", "123"); + Assert.AreEqual("123", algorithm.DeploymentDetails["account"]); + Assert.AreEqual("123", resultHandler.DeploymentDetails["account"]); resultHandler.SetAlgorithm(algorithm, 100000); - Assert.AreSame(resultHandler.BrokerageData, algorithm.BrokerageData); + Assert.AreSame(resultHandler.DeploymentDetails, algorithm.DeploymentDetails); // it's only set once by the engine: the same instance is fine, a different one is not - Assert.DoesNotThrow(() => algorithm.SetBrokerageData(resultHandler.BrokerageData)); - Assert.Throws(() => algorithm.SetBrokerageData(new ReadOnlyExtendedDictionary())); - Assert.AreSame(resultHandler.BrokerageData, algorithm.BrokerageData); + Assert.DoesNotThrow(() => algorithm.SetDeploymentDetails(resultHandler.DeploymentDetails)); + Assert.Throws(() => algorithm.SetDeploymentDetails(new ReadOnlyExtendedDictionary())); + Assert.AreSame(resultHandler.DeploymentDetails, algorithm.DeploymentDetails); - resultHandler.AddBrokerageData("environment", "paper"); - Assert.AreEqual("paper", algorithm.BrokerageData["environment"]); + resultHandler.AddDeploymentDetail("environment", "paper"); + Assert.AreEqual("paper", algorithm.DeploymentDetails["environment"]); // entries are updated in place, empty keys are ignored and null values are stored as empty - resultHandler.AddBrokerageData("account", "456"); - resultHandler.AddBrokerageData("", "ignored"); - resultHandler.AddBrokerageData(null, "ignored"); - resultHandler.AddBrokerageData("empty", null); - CollectionAssert.AreEquivalent(new Dictionary { { "account", "456" }, { "environment", "paper" }, { "empty", "" } }, algorithm.BrokerageData); + resultHandler.AddDeploymentDetail("account", "456"); + resultHandler.AddDeploymentDetail("", "ignored"); + resultHandler.AddDeploymentDetail(null, "ignored"); + resultHandler.AddDeploymentDetail("empty", null); + CollectionAssert.AreEquivalent(new Dictionary { { "account", "456" }, { "environment", "paper" }, { "empty", "" } }, algorithm.DeploymentDetails); // read only for the algorithm - Assert.Throws(() => algorithm.BrokerageData.Add("new-key", "new value")); - Assert.Throws(() => algorithm.BrokerageData.Remove("account")); - Assert.Throws(() => algorithm.BrokerageData["account"] = "new value"); + Assert.Throws(() => algorithm.DeploymentDetails.Add("new-key", "new value")); + Assert.Throws(() => algorithm.DeploymentDetails.Remove("account")); + Assert.Throws(() => algorithm.DeploymentDetails["account"] = "new value"); // the final result is stored on exit resultHandler.Exit(); @@ -604,7 +604,7 @@ public void BrokerageDataIsSharedWithTheAlgorithmAndTheResults() Assert.IsNotEmpty(stored); foreach (var result in stored) { - CollectionAssert.AreEquivalent(algorithm.BrokerageData, result.AlgorithmConfiguration.BrokerageData); + CollectionAssert.AreEquivalent(algorithm.DeploymentDetails, result.AlgorithmConfiguration.DeploymentDetails); } }