/// <summary> /// Generate the monthly returns plot using the python libraries. /// </summary> public override string Render() { var backtestPoints = ResultsUtil.EquityPoints(_backtest); var livePoints = ResultsUtil.EquityPoints(_live); var backtestSeries = new Series <DateTime, double>(backtestPoints.Keys, backtestPoints.Values); var liveSeries = new Series <DateTime, double>(livePoints.Keys, livePoints.Values); // Equivalent to python pandas line: `backtestSeries.resample('M').apply(lambda x: x.pct_change().sum())` var backtestMonthlyReturns = backtestSeries.ResampleEquivalence(date => new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1)) .Select(kvp => kvp.Value.PercentChange().Sum()); var liveMonthlyReturns = liveSeries.ResampleEquivalence(date => new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1)) .Select(kvp => kvp.Value.PercentChange().Sum()); var base64 = ""; using (Py.GIL()) { var backtestResults = new PyDict(); foreach (var kvp in backtestMonthlyReturns.GroupBy(kvp => kvp.Key.Year).GetObservations()) { var key = kvp.Key.ToStringInvariant(); var values = (kvp.Value * 100).Values.ToList(); while (values.Count != 12) { values.Add(double.NaN); } backtestResults.SetItem(key.ToPython(), values.ToPython()); } var liveResults = new PyDict(); foreach (var kvp in liveMonthlyReturns.GroupBy(kvp => kvp.Key.Year).GetObservations()) { var key = kvp.Key.ToStringInvariant(); var values = (kvp.Value * 100).Values.ToList(); while (values.Count != 12) { values.Add(double.NaN); } liveResults.SetItem(key.ToPython(), values.ToPython()); } base64 = Charting.GetMonthlyReturns(backtestResults, liveResults); } return(base64); }
/// <summary> /// Generate the monthly returns plot using the python libraries. /// </summary> public override string Render() { var backtestPoints = ResultsUtil.EquityPoints(_backtest); var livePoints = ResultsUtil.EquityPoints(_live); var backtestSeries = new Series <DateTime, double>(backtestPoints.Keys, backtestPoints.Values); var liveSeries = new Series <DateTime, double>(livePoints.Keys, livePoints.Values); // Equivalent to python pandas line: `backtestSeries.resample('M').apply(lambda x: x.pct_change().sum())` var backtestMonthlyReturns = backtestSeries.ResampleEquivalence(date => new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1)) .Select(kvp => kvp.Value.TotalReturns()); var liveMonthlyReturns = liveSeries.ResampleEquivalence(date => new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1)) .Select(kvp => kvp.Value.TotalReturns()); var base64 = ""; using (Py.GIL()) { var backtestResults = new PyDict(); foreach (var kvp in backtestMonthlyReturns.GroupBy(kvp => kvp.Key.Year).GetObservations()) { var key = kvp.Key.ToStringInvariant(); var monthlyReturns = kvp.Value * 100; var values = new List <double>(); for (var i = 1; i <= 12; i++) { var returns = monthlyReturns.Where(row => row.Key.Month == i); if (!returns.IsEmpty) { values.Add(returns.FirstValue()); continue; } values.Add(double.NaN); } backtestResults.SetItem(key.ToPython(), values.ToPython()); } var liveResults = new PyDict(); foreach (var kvp in liveMonthlyReturns.GroupBy(kvp => kvp.Key.Year).GetObservations()) { var key = kvp.Key.ToStringInvariant(); var monthlyReturns = kvp.Value * 100; var values = new List <double>(); for (var i = 1; i <= 12; i++) { var returns = monthlyReturns.Where(row => row.Key.Month == i); if (!returns.IsEmpty) { values.Add(returns.FirstValue()); continue; } values.Add(double.NaN); } liveResults.SetItem(key.ToPython(), values.ToPython()); } base64 = Charting.GetMonthlyReturns(backtestResults, liveResults); } return(base64); }