/// <summary> /// Generate the returns per trade plot using the python libraries. /// </summary> public override string Render() { var backtestPercentagePerTrade = new List <double>(); if (_backtest?.TotalPerformance?.ClosedTrades != null) { foreach (var trade in _backtest.TotalPerformance.ClosedTrades) { if (trade.EntryPrice == 0m) { Log.Error($"ReturnsPerTradeReportElement.Render(): Encountered entry price of 0 in trade with entry time: {trade.EntryTime:yyyy-MM-dd HH:mm:ss} - Exit time: {trade.ExitTime:yyyy-MM-dd HH::mm:ss}"); continue; } backtestPercentagePerTrade.Add((Convert.ToDouble(trade.ExitPrice) - Convert.ToDouble(trade.EntryPrice)) / Convert.ToDouble(trade.EntryPrice)); } } // TODO: LiveResult does not contain a TotalPerformance field, so skip live mode for now var base64 = ""; using (Py.GIL()) { // Charting library does not expect values to be in whole percentage values (i.e. not 1% == 1.0, but rather 1% == 0.01), base64 = Charting.GetReturnsPerTrade(backtestPercentagePerTrade.ToPython()); } return(base64); }