private void UpdateRegressionStatisticsInSourceFile(BacktestResultPacket result) { if (!result.Results.Statistics.Any()) { Log.Error("Messaging.UpdateRegressionStatisticsInSourceFile(): No statistics generated. Skipping update."); return; } var algorithmSource = Directory.EnumerateFiles("../../../Algorithm.CSharp", $"{_job.AlgorithmId}.cs", SearchOption.AllDirectories).SingleOrDefault(); if (algorithmSource == null) { algorithmSource = Directory.EnumerateFiles("../../../Algorithm.CSharp", $"*{_job.AlgorithmId}.cs", SearchOption.AllDirectories).Single(); } var file = File.ReadAllLines(algorithmSource).ToList().GetEnumerator(); var lines = new List <string>(); while (file.MoveNext()) { var line = file.Current; if (line == null) { continue; } if (line.Contains("Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>") || line.Contains("Dictionary<string, string> ExpectedStatistics => new()")) { lines.Add(line); lines.Add(" {"); foreach (var pair in result.Results.Statistics) { lines.Add($" {{\"{pair.Key}\", \"{pair.Value}\"}},"); } // remove trailing comma var lastLine = lines[lines.Count - 1]; lines[lines.Count - 1] = lastLine.Substring(0, lastLine.Length - 1); // now we skip existing expected statistics in file while (file.MoveNext()) { line = file.Current; if (line != null && line.Contains("};")) { lines.Add(line); break; } } } else { lines.Add(line); } } file.DisposeSafely(); File.WriteAllLines(algorithmSource, lines); }
/// <summary> /// Send a final analysis result back to the IDE. /// </summary> /// <param name="job">Lean AlgorithmJob task</param> /// <param name="orders">Collection of orders from the algorithm</param> /// <param name="profitLoss">Collection of time-profit values for the algorithm</param> /// <param name="holdings">Current holdings state for the algorithm</param> /// <param name="statistics">Statistics information for the algorithm (empty if not finished)</param> /// <param name="banner">Runtime statistics banner information</param> public void SendFinalResult(AlgorithmNodePacket job, Dictionary <int, Order> orders, Dictionary <DateTime, decimal> profitLoss, Dictionary <string, Holding> holdings, Dictionary <string, string> statistics, Dictionary <string, string> banner) { try { //Convert local dictionary: var charts = new Dictionary <string, Chart>(Charts); _processingFinalPacket = true; //Create a result packet to send to the browser. BacktestResultPacket result = new BacktestResultPacket((BacktestNodePacket)job, new BacktestResult(charts, orders, profitLoss, statistics), 1m) { ProcessingTime = (DateTime.Now - _startTime).TotalSeconds, DateFinished = DateTime.Now, Progress = 1 }; //Place result into storage. StoreResult(result); //Truncate packet to fit within 32kb of messaging limits. result.Results = new BacktestResult(); //Second, send the truncated packet: Engine.Notify.BacktestResult(result, finalPacket: true); Log.Trace("BacktestingResultHandler.SendAnalysisResult(): Processed final packet"); } catch (Exception err) { Log.Error("Algorithm.Worker.SendResult(): " + err.Message); } }
/// <summary> /// Raise a backtest result event safely. /// </summary> protected virtual void OnBacktestResultEvent(BacktestResultPacket packet) { var handler = BacktestResultEvent; if (handler != null) { handler(packet); } }
/// <summary> /// Backtest result packet /// </summary> /// <param name="packet"></param> private void MessagingOnBacktestResultEvent(BacktestResultPacket packet) { if (packet.Progress != 1) { return; } //Remove previous event handler: var url = GetUrl(_job, _liveMode, true); //Generate JSON: var jObj = new JObject(); var dateFormat = "yyyy-MM-dd HH:mm:ss"; dynamic final = jObj; final.dtPeriodStart = packet.PeriodStart.ToString(dateFormat); final.dtPeriodFinished = packet.PeriodFinish.AddDays(1).ToString(dateFormat); dynamic resultData = new JObject(); resultData.version = "3"; resultData.results = JObject.FromObject(packet.Results); resultData.statistics = JObject.FromObject(packet.Results.Statistics); resultData.iTradeableDates = 1; resultData.ranking = null; final.oResultData = resultData; var json = JsonConvert.SerializeObject(final); //GECKO RESULT SET: #if !__MonoCS__ _geckoBrowser.DOMContentLoaded += (sender, args) => { var executor = new JQueryExecutor(_geckoBrowser.Window); executor.ExecuteJQuery("window.jnBacktest = JSON.parse('" + json + "');"); executor.ExecuteJQuery("$.holdReady(false)"); }; _geckoBrowser.Navigate(url); #else //MONO WEB BROWSER RESULT SET: _monoBrowser.DocumentCompleted += (sender, args) => { if (_monoBrowser.Document == null) { return; } _monoBrowser.Document.InvokeScript("eval", new object[] { "window.jnBacktest = JSON.parse('" + json + "');" }); _monoBrowser.Document.InvokeScript("eval", new object[] { "$.holdReady(false)" }); }; _monoBrowser.Navigate(url); #endif foreach (var pair in packet.Results.Statistics) { _logging.Trace("STATISTICS:: " + pair.Key + " " + pair.Value); } }
/// <summary> /// Send a final analysis result back to the IDE. /// </summary> protected void SendFinalResult() { try { BacktestResultPacket result; // could happen if algorithm failed to init if (Algorithm != null) { //Convert local dictionary: var charts = new Dictionary <string, Chart>(Charts); var orders = new Dictionary <int, Order>(TransactionHandler.Orders); var profitLoss = new SortedDictionary <DateTime, decimal>(Algorithm.Transactions.TransactionRecord); var statisticsResults = GenerateStatisticsResults(charts, profitLoss, _capacityEstimate); var runtime = GetAlgorithmRuntimeStatistics(statisticsResults.Summary, capacityEstimate: _capacityEstimate); FinalStatistics = statisticsResults.Summary; // clear the trades collection before placing inside the backtest result foreach (var ap in statisticsResults.RollingPerformances.Values) { ap.ClosedTrades.Clear(); } var orderEvents = TransactionHandler.OrderEvents.ToList(); //Create a result packet to send to the browser. result = new BacktestResultPacket(_job, new BacktestResult(new BacktestResultParameters(charts, orders, profitLoss, statisticsResults.Summary, runtime, statisticsResults.RollingPerformances, orderEvents, statisticsResults.TotalPerformance, AlphaRuntimeStatistics)), Algorithm.EndDate, Algorithm.StartDate); } else { result = BacktestResultPacket.CreateEmpty(_job); } var utcNow = DateTime.UtcNow; result.ProcessingTime = (utcNow - StartTime).TotalSeconds; result.DateFinished = DateTime.Now; result.Progress = 1; //Place result into storage. StoreResult(result); result.Results.ServerStatistics = GetServerStatistics(utcNow); //Second, send the truncated packet: MessagingHandler.Send(result); Log.Trace("BacktestingResultHandler.SendAnalysisResult(): Processed final packet"); } catch (Exception err) { Log.Error(err); } }
/// <summary> /// Send a final analysis result back to the IDE. /// </summary> public void SendFinalResult() { try { _processingFinalPacket = true; //Convert local dictionary: var charts = new Dictionary <string, Chart>(Charts); var orders = new Dictionary <int, Order>(TransactionHandler.Orders); var profitLoss = new SortedDictionary <DateTime, decimal>(Algorithm.Transactions.TransactionRecord); var statisticsResults = GenerateStatisticsResults(charts, profitLoss); var runtime = GetAlgorithmRuntimeStatistics(statisticsResults.Summary); FinalStatistics = statisticsResults.Summary; // clear the trades collection before placing inside the backtest result foreach (var ap in statisticsResults.RollingPerformances.Values) { ap.ClosedTrades.Clear(); } //Create a result packet to send to the browser. var result = new BacktestResultPacket(_job, new BacktestResult(charts, orders, profitLoss, statisticsResults.Summary, runtime, statisticsResults.RollingPerformances, statisticsResults.TotalPerformance) { AlphaRuntimeStatistics = AlphaRuntimeStatistics }) { ProcessingTime = (DateTime.UtcNow - StartTime).TotalSeconds, DateFinished = DateTime.Now, Progress = 1 }; //Place result into storage. StoreResult(result); //Second, send the truncated packet: MessagingHandler.Send(result); Log.Trace("BacktestingResultHandler.SendAnalysisResult(): Processed final packet"); } catch (Exception err) { Log.Error(err); } }
/// <summary> /// Send a final analysis result back to the IDE. /// </summary> /// <param name="job">Lean AlgorithmJob task</param> /// <param name="orders">Collection of orders from the algorithm</param> /// <param name="profitLoss">Collection of time-profit values for the algorithm</param> /// <param name="holdings">Current holdings state for the algorithm</param> /// <param name="cashbook">Cashbook for the holdingss</param> /// <param name="statisticsResults">Statistics information for the algorithm (empty if not finished)</param> /// <param name="banner">Runtime statistics banner information</param> public void SendFinalResult(AlgorithmNodePacket job, Dictionary <int, Order> orders, Dictionary <DateTime, decimal> profitLoss, Dictionary <string, Holding> holdings, CashBook cashbook, StatisticsResults statisticsResults, Dictionary <string, string> banner) { try { FinalStatistics = statisticsResults.Summary; //Convert local dictionary: var charts = new Dictionary <string, Chart>(Charts); _processingFinalPacket = true; // clear the trades collection before placing inside the backtest result foreach (var ap in statisticsResults.RollingPerformances.Values) { ap.ClosedTrades.Clear(); } //Create a result packet to send to the browser. var result = new BacktestResultPacket((BacktestNodePacket)job, new BacktestResult(Algorithm.IsFrameworkAlgorithm, charts, orders, profitLoss, statisticsResults.Summary, banner, statisticsResults.RollingPerformances, statisticsResults.TotalPerformance) { AlphaRuntimeStatistics = AlphaRuntimeStatistics }) { ProcessingTime = (DateTime.UtcNow - _startTime).TotalSeconds, DateFinished = DateTime.Now, Progress = 1 }; //Place result into storage. StoreResult(result); //Second, send the truncated packet: _messagingHandler.Send(result); Log.Trace("BacktestingResultHandler.SendAnalysisResult(): Processed final packet"); } catch (Exception err) { Log.Error(err); } }
private static void CalcPeriods(BacktestResultPacket packet) { if (packet.PeriodStart > DateTime.MinValue && packet.PeriodFinish > DateTime.MinValue) { return; } long _startDate = long.MaxValue, _endDate = -1; foreach (var chart in packet.Results.Charts.Values) { foreach (var series in chart.Series.Values) { if (series.Values.Count == 0) { continue; } var mindt = series.Values.Min(x => x.x); var maxdt = series.Values.Max(x => x.x); if (_startDate > mindt) { _startDate = mindt; } if (_endDate < maxdt) { _endDate = maxdt; } } } if (_endDate < 0) { return; } packet.PeriodStart = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(_startDate); packet.PeriodFinish = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(_endDate); }
} // End Run(); /// <summary> /// Send a backtest update to the browser taking a latest snapshot of the charting data. /// </summary> public void ProcessSeriesUpdate() { try { //Sometimes don't run the update, if not ready or we're ending. if (Algorithm == null || Algorithm.Transactions == null || _processingFinalPacket) { return; } if (DateTime.Now <= _nextUpdate || !(_daysProcessed > (_lastDaysProcessed + 1))) { return; } //Debugging.. //Logging.Log.Debug("BacktestingResultHandler.ProcessSeriesUpdate(): Sending Update (" + _lastDaysProcessed + ") : " + DateTime.Now.ToLongTimeString()); //Extract the orders since last update var deltaOrders = new Dictionary <int, Order>(); try { deltaOrders = (from order in Algorithm.Transactions.Orders where order.Value.Time.Date >= _lastUpdate && order.Value.Status == OrderStatus.Filled select order).ToDictionary(t => t.Key, t => t.Value); } catch (Exception err) { Log.Error("BacktestingResultHandler().ProcessSeriesUpdate(): Transactions: " + err.Message); } //Limit length of orders we pass back dynamically to avoid flooding. if (deltaOrders.Count > 50) { deltaOrders.Clear(); } //Reset loop variables: try { _lastUpdate = AlgorithmManager.Frontier.Date; _lastDaysProcessed = _daysProcessed; _nextUpdate = DateTime.Now.AddSeconds(0.5); } catch (Exception err) { Log.Error("BacktestingResultHandler.ProcessSeriesUpdate(): Can't update variables: " + err.Message); } var deltaCharts = new Dictionary <string, Chart>(); lock (_chartLock) { //Get the updates since the last chart foreach (var chart in Charts.Values) { deltaCharts.Add(chart.Name, chart.GetUpdates()); } } //Profit Loss Changes: var deltaProfitLoss = new Dictionary <DateTime, decimal>(); var deltaStatistics = new Dictionary <string, string>(); var progress = Convert.ToDecimal(_daysProcessed / _jobDays); if (progress > 0.999m) { progress = 0.999m; } //1. Cloud Upload -> Upload the whole packet to S3 Immediately: var completeResult = new BacktestResult(Charts, Algorithm.Transactions.Orders, Algorithm.Transactions.TransactionRecord, new Dictionary <string, string>()); var complete = new BacktestResultPacket(_job, completeResult, progress); if (DateTime.Now > _nextS3Update) { _nextS3Update = DateTime.Now.AddSeconds(30); StoreResult(complete, false); } //2. Backtest Update -> Send the truncated packet to the backtester: var packet = new BacktestResultPacket(_job, new BacktestResult(deltaCharts, deltaOrders, deltaProfitLoss, deltaStatistics), progress); packet.DateRequested = _timeRequested; Engine.Notify.BacktestResult(packet); } catch (Exception err) { Log.Error("BacktestingResultHandler().ProcessSeriesUpdate(): " + err.Message + " >> " + err.StackTrace); } }
} // End Run(); /// <summary> /// Send a backtest update to the browser taking a latest snapshot of the charting data. /// </summary> public void Update() { try { //Sometimes don't run the update, if not ready or we're ending. if (Algorithm == null || Algorithm.Transactions == null || _processingFinalPacket) { return; } if (DateTime.Now <= _nextUpdate || !(_daysProcessed > (_lastDaysProcessed + 1))) { return; } //Extract the orders since last update var deltaOrders = new Dictionary <int, Order>(); try { deltaOrders = (from order in _transactionHandler.Orders where order.Value.Time.Date >= _lastUpdate && order.Value.Status == OrderStatus.Filled select order).ToDictionary(t => t.Key, t => t.Value); } catch (Exception err) { Log.Error(err, "Transactions"); } //Limit length of orders we pass back dynamically to avoid flooding. if (deltaOrders.Count > 50) { deltaOrders.Clear(); } //Reset loop variables: try { _lastUpdate = Algorithm.Time.Date; _lastDaysProcessed = _daysProcessed; _nextUpdate = DateTime.Now.AddSeconds(0.5); } catch (Exception err) { Log.Error(err, "Can't update variables"); } var deltaCharts = new Dictionary <string, Chart>(); lock (_chartLock) { //Get the updates since the last chart foreach (var chart in Charts.Values) { deltaCharts.Add(chart.Name, chart.GetUpdates()); } } //Get the runtime statistics from the user algorithm: var runtimeStatistics = new Dictionary <string, string>(); lock (_runtimeLock) { foreach (var pair in _runtimeStatistics) { runtimeStatistics.Add(pair.Key, pair.Value); } } runtimeStatistics.Add("Unrealized", "$" + _algorithm.Portfolio.TotalUnrealizedProfit.ToString("N2")); runtimeStatistics.Add("Fees", "-$" + _algorithm.Portfolio.TotalFees.ToString("N2")); runtimeStatistics.Add("Net Profit", "$" + (_algorithm.Portfolio.TotalProfit - _algorithm.Portfolio.TotalFees).ToString("N2")); runtimeStatistics.Add("Return", ((_algorithm.Portfolio.TotalPortfolioValue - _setupHandler.StartingPortfolioValue) / _setupHandler.StartingPortfolioValue).ToString("P")); runtimeStatistics.Add("Equity", "$" + _algorithm.Portfolio.TotalPortfolioValue.ToString("N2")); //Profit Loss Changes: var progress = Convert.ToDecimal(_daysProcessed / _jobDays); if (progress > 0.999m) { progress = 0.999m; } //1. Cloud Upload -> Upload the whole packet to S3 Immediately: var completeResult = new BacktestResult(Charts, _transactionHandler.Orders, Algorithm.Transactions.TransactionRecord, new Dictionary <string, string>(), runtimeStatistics, new Dictionary <string, AlgorithmPerformance>()); var complete = new BacktestResultPacket(_job, completeResult, progress); if (DateTime.Now > _nextS3Update) { _nextS3Update = DateTime.Now.AddSeconds(30); StoreResult(complete, false); } //2. Backtest Update -> Send the truncated packet to the backtester: var splitPackets = SplitPackets(deltaCharts, deltaOrders, runtimeStatistics, progress); foreach (var backtestingPacket in splitPackets) { _messagingHandler.Send(backtestingPacket); } } catch (Exception err) { Log.Error(err); } }
public void MessageHandler_SendsCorrectPackets_ToCorrectRoutes() { //Allow proper decoding of orders. JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = { new OrderJsonConverter() } }; // Create list of packets to test var debug = new DebugPacket(); var log = new LogPacket(); var backtest = new BacktestResultPacket(); var handled = new HandledErrorPacket(); var error = new RuntimeErrorPacket(); var packetList = new List <Packet> { log, debug, backtest, handled, error }; using (var pullSocket = new PullSocket(">tcp://localhost:" + _port)) { var count = 0; while (count < packetList.Count) { _messageHandler.Send(packetList[count]); var message = pullSocket.ReceiveMultipartMessage(); var payload = message[0].ConvertToString(); var packet = JsonConvert.DeserializeObject <Packet>(payload); Assert.IsTrue(message.FrameCount == 1); if (PacketType.Debug == packet.Type) { Assert.IsTrue(payload == JsonConvert.SerializeObject(debug)); } if (PacketType.HandledError == packet.Type) { Assert.IsTrue(payload == JsonConvert.SerializeObject(handled)); } if (PacketType.BacktestResult == packet.Type) { Assert.IsTrue(payload == JsonConvert.SerializeObject(backtest)); } if (PacketType.RuntimeError == packet.Type) { Assert.IsTrue(payload == JsonConvert.SerializeObject(error)); } if (PacketType.Log == packet.Type) { Assert.IsTrue(payload == JsonConvert.SerializeObject(log)); } count++; } } }
//HACK: calculate and retain full statistics but not store result public void SendFinalResult() { if (_hasError) { FullResults = null; return; } try { //_processingFinalPacket = true; _shadowType.GetField("_processingFinalPacket", _flags).SetValue(_shadow, true); var charts = new Dictionary <string, Chart>(_shadow.Charts); //var orders = new Dictionary<int, Order>(_shadow.TransactionHandler.Orders); var transactionHandler = (ITransactionHandler)_shadowType.GetField("TransactionHandler", _flags).GetValue(_shadow); var orders = new Dictionary <int, Order>(transactionHandler.Orders); var profitLoss = new SortedDictionary <DateTime, decimal>(Algorithm.Transactions.TransactionRecord); //var statisticsResults = GenerateStatisticsResults(charts, profitLoss); var statisticsResults = (StatisticsResults)_shadowType.InvokeMember("GenerateStatisticsResults", _flags | BindingFlags.InvokeMethod, null, _shadow, new object[] { charts, profitLoss }); //var runtime = GetAlgorithmRuntimeStatistics(statisticsResults.Summary); var runtime = (Dictionary <string, string>) typeof(BaseResultsHandler).InvokeMember("GetAlgorithmRuntimeStatistics", _flags | BindingFlags.InvokeMethod, Type.DefaultBinder, _shadow, new object[] { statisticsResults.Summary, null }); FullResults = StatisticsAdapter.Transform(statisticsResults.TotalPerformance, statisticsResults.Summary); //FinalStatistics = statisticsResults.Summary; _shadowType.GetProperty("FinalStatistics").SetValue(_shadow, statisticsResults.Summary, _flags, null, null, null); foreach (var ap in statisticsResults.RollingPerformances.Values) { ap.ClosedTrades.Clear(); } //var result = new BacktestResultPacket(_job, // new BacktestResult(charts, orders, profitLoss, statisticsResults.Summary, runtime, statisticsResults.RollingPerformances, statisticsResults.TotalPerformance) // { AlphaRuntimeStatistics = AlphaRuntimeStatistics }, Algorithm.EndDate, Algorithm.StartDate) //{ // ProcessingTime = (DateTime.UtcNow - StartTime).TotalSeconds, // DateFinished = DateTime.Now, // Progress = 1 //}; var job = (BacktestNodePacket)_shadowType.GetField("_job", _flags).GetValue(_shadow); var startTime = (DateTime)_shadowType.GetProperty("StartTime", _flags).GetValue(_shadow); var alphaRuntimeStatistics = (AlphaRuntimeStatistics)_shadowType.GetProperty("AlphaRuntimeStatistics", _flags).GetValue(_shadow); var result = new BacktestResultPacket(job, new BacktestResult(charts, orders, profitLoss, statisticsResults.Summary, runtime, statisticsResults.RollingPerformances, statisticsResults.TotalPerformance) { AlphaRuntimeStatistics = alphaRuntimeStatistics }, Algorithm.EndDate, Algorithm.StartDate) { ProcessingTime = (DateTime.UtcNow - startTime).TotalSeconds, DateFinished = DateTime.Now, Progress = 1 }; //StoreResult(result); //do not store result //MessagingHandler.Send(result); var messagingHandler = (IMessagingHandler)_shadowType.GetField("MessagingHandler", _flags).GetValue(_shadow); messagingHandler.Send(result); } catch (Exception ex) { LogProvider.ErrorLogger.Error(ex); } }
/// <summary> /// Send a backtest result packet /// </summary> public void BacktestResult(BacktestResultPacket packet, bool finalPacket = false) { // }
private void UpdateRegressionStatisticsInSourceFile(BacktestResultPacket result) { if (!result.Results.Statistics.Any()) { Log.Error("Messaging.UpdateRegressionStatisticsInSourceFile(): No statistics generated. Skipping update."); return; } var algorithmSource = $"../../../Algorithm.CSharp/{_job.AlgorithmId}.cs"; var file = File.ReadAllLines(algorithmSource).ToList().GetEnumerator(); var lines = new List <string>(); var insideStats = false; while (file.MoveNext()) { var line = file.Current; if (line == null) { continue; } if (line.Contains("public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>")) { insideStats = true; lines.Add(line); lines.Add(" {"); } if (!insideStats) { lines.Add(line); } else { insideStats = false; foreach (var pair in result.Results.Statistics) { lines.Add($" {{\"{pair.Key}\", \"{pair.Value}\"}},"); } // remove trailing comma var lastLine = lines[lines.Count - 1]; lines[lines.Count - 1] = lastLine.Substring(0, lastLine.Length - 1); while (file.MoveNext()) { line = file.Current; if (line == null) { continue; } if (line.Contains("};")) { lines.Add(line); break; } } } } file.DisposeSafely(); File.WriteAllLines(algorithmSource, lines); }
/// <summary> /// Send a final analysis result back to the IDE. /// </summary> protected void SendFinalResult() { try { //Convert local dictionary: var charts = new Dictionary <string, Chart>(Charts); var orders = new Dictionary <int, Order>(TransactionHandler.Orders); var profitLoss = new SortedDictionary <DateTime, decimal>(Algorithm.Transactions.TransactionRecord); var statisticsResults = GenerateStatisticsResults(charts, profitLoss); var runtime = GetAlgorithmRuntimeStatistics(statisticsResults.Summary); FinalStatistics = statisticsResults.Summary; // clear the trades collection before placing inside the backtest result foreach (var ap in statisticsResults.RollingPerformances.Values) { ap.ClosedTrades.Clear(); } var orderEvents = TransactionHandler.OrderEvents.ToList(); //Create a result packet to send to the browser. var result = new BacktestResultPacket(_job, new BacktestResult(new BacktestResultParameters(charts, orders, profitLoss, statisticsResults.Summary, runtime, statisticsResults.RollingPerformances, orderEvents, statisticsResults.TotalPerformance, AlphaRuntimeStatistics)), Algorithm.EndDate, Algorithm.StartDate) { ProcessingTime = (DateTime.UtcNow - StartTime).TotalSeconds, DateFinished = DateTime.Now, Progress = 1 }; // Create new connection factory var factory = new ConnectionFactory() { HostName = "localhost" }; using (var connection = factory.CreateConnection()) using (var channel = connection.CreateModel()) { // Set up queue for RabbitMQ channel.QueueDeclare(queue: "rabbitBroker", durable: false, exclusive: false, autoDelete: false, arguments: null); // Create test message for RabbitMQProducer string producerMessage = JsonConvert.SerializeObject(FinalStatistics, Formatting.Indented); var producerBody = Encoding.UTF8.GetBytes(producerMessage); channel.BasicPublish(exchange: "", routingKey: "rabbitBroker", basicProperties: null, body: producerBody); } //Place result into storage. StoreResult(result); //Second, send the truncated packet: MessagingHandler.Send(result); Log.Trace("BacktestingResultHandler.SendAnalysisResult(): Processed final packet"); } catch (Exception err) { Log.Error(err); } }