/// <summary> /// The generated output string to be injected /// </summary> public override string Render() { var backtestPoints = ResultsUtil.EquityPoints(_backtest); var backtestBenchmarkPoints = ResultsUtil.BenchmarkPoints(_backtest); var backtestSeries = new Series <DateTime, double>(backtestPoints.Keys, backtestPoints.Values); var backtestBenchmarkSeries = new Series <DateTime, double>(backtestBenchmarkPoints.Keys, backtestBenchmarkPoints.Values); var html = new List <string>(); foreach (var crisisEvent in Crisis.Events) { using (Py.GIL()) { var crisis = crisisEvent.Value; var data = new PyList(); var frame = Frame.CreateEmpty <DateTime, string>(); // The two following operations are equivalent to Pandas' `df.resample("D").sum()` frame["Backtest"] = backtestSeries.ResampleEquivalence(date => date.Date, s => s.LastValue()); frame["Benchmark"] = backtestBenchmarkSeries.ResampleEquivalence(date => date.Date, s => s.LastValue()); var crisisFrame = frame.Where(kvp => kvp.Key >= crisis.Start && kvp.Key <= crisis.End); crisisFrame = crisisFrame.Join("BacktestPercent", crisisFrame["Backtest"].CumulativeReturns()); crisisFrame = crisisFrame.Join("BenchmarkPercent", crisisFrame["Benchmark"].CumulativeReturns()); // Pad out all missing values to start from 0 for nice plots crisisFrame = crisisFrame.FillMissing(Direction.Forward).FillMissing(0.0); data.Append(crisisFrame.RowKeys.ToList().ToPython()); data.Append(crisisFrame["BacktestPercent"].Values.ToList().ToPython()); data.Append(crisisFrame["BenchmarkPercent"].Values.ToList().ToPython()); var base64 = (string)Charting.GetCrisisEventsPlots(data, crisis.Name.Replace("/", "").Replace(".", "").Replace(" ", "")); if (base64 == _emptyChart) { continue; } if (!crisisFrame.IsEmpty) { var contents = _template.Replace(ReportKey.CrisisTitle, crisis.ToString(crisisFrame.GetRowKeyAt(0), crisisFrame.GetRowKeyAt(crisisFrame.RowCount - 1))); contents = contents.Replace(ReportKey.CrisisContents, base64); html.Add(contents); } } } if (Key == ReportKey.CrisisPageStyle) { if (html.Count == 0) { return("display: none;"); } return(string.Empty); } return(string.Join("\n", html)); }