/// <summary> /// Generate the top N drawdown plot using the python libraries. /// </summary> public override string Render() { var backtestPoints = ResultsUtil.EquityPoints(_backtest); var livePoints = ResultsUtil.EquityPoints(_live); var liveSeries = new Series <DateTime, double>(livePoints.Keys, livePoints.Values); var strategySeries = DrawdownCollection.NormalizeResults(_backtest, _live); var seriesUnderwaterPlot = DrawdownCollection.GetUnderwater(strategySeries).DropMissing(); var liveUnderwaterPlot = backtestPoints.Count == 0 ? seriesUnderwaterPlot : seriesUnderwaterPlot.After(backtestPoints.Last().Key); var drawdownCollection = DrawdownCollection.FromResult(_backtest, _live, periods: 5); var base64 = ""; using (Py.GIL()) { var backtestList = new PyList(); if (liveUnderwaterPlot.IsEmpty) { backtestList.Append(seriesUnderwaterPlot.Keys.ToList().ToPython()); backtestList.Append(seriesUnderwaterPlot.Values.ToList().ToPython()); } else { backtestList.Append(seriesUnderwaterPlot.Before(liveUnderwaterPlot.FirstKey()).Keys.ToList().ToPython()); backtestList.Append(seriesUnderwaterPlot.Before(liveUnderwaterPlot.FirstKey()).Values.ToList().ToPython()); } var liveList = new PyList(); liveList.Append(liveUnderwaterPlot.Keys.ToList().ToPython()); liveList.Append(liveUnderwaterPlot.Values.ToList().ToPython()); var worstList = new PyList(); var previousDrawdownPeriods = new List <KeyValuePair <DateTime, DateTime> >(); foreach (var group in drawdownCollection.Drawdowns) { // Skip drawdown periods that are overlapping if (previousDrawdownPeriods.Where(kvp => (group.Start >= kvp.Key && group.Start <= kvp.Value) || (group.End >= kvp.Key && group.End <= kvp.Value)).Any()) { continue; } var worst = new PyDict(); worst.SetItem("Begin", group.Start.ToPython()); worst.SetItem("End", group.End.ToPython()); worst.SetItem("Total", group.PeakToTrough.ToPython()); worstList.Append(worst); previousDrawdownPeriods.Add(new KeyValuePair <DateTime, DateTime>(group.Start, group.End)); } base64 = Charting.GetDrawdown(backtestList, liveList, worstList); } return(base64); }