Lean  $LEAN_TAG$
AnnualReturnsReportElement.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.Linq;
18 using Deedle;
19 using Python.Runtime;
20 using QuantConnect.Packets;
21 
23 {
24  internal sealed class AnnualReturnsReportElement : ChartReportElement
25  {
26  private LiveResult _live;
27  private BacktestResult _backtest;
28 
29  /// <summary>
30  /// Create a new plot of annual returns
31  /// </summary>
32  /// <param name="name">Name of the widget</param>
33  /// <param name="key">Location of injection</param>
34  /// <param name="backtest">Backtest result object</param>
35  /// <param name="live">Live result object</param>
36  public AnnualReturnsReportElement(string name, string key, BacktestResult backtest, LiveResult live)
37  {
38  _live = live;
39  _backtest = backtest;
40  Name = name;
41  Key = key;
42  }
43 
44  /// <summary>
45  /// Generate the annual returns plot using the python libraries.
46  /// </summary>
47  public override string Render()
48  {
49  var backtestReturns = ResultsUtil.EquityPoints(_backtest);
50  var liveReturns = ResultsUtil.EquityPoints(_live);
51 
52  var backtestTime = backtestReturns.Keys.ToList();
53  var backtestStrategy = backtestReturns.Values.ToList();
54 
55  var liveTime = liveReturns.Keys.ToList();
56  var liveStrategy = liveReturns.Values.ToList();
57 
58  var base64 = "";
59  using (Py.GIL())
60  {
61  var backtestList = new PyList();
62  var liveList = new PyList();
63 
64  // We need to set the datetime index first before we resample
65  //var backtestSeries = Pandas.Series(backtestStrategy.ToPython());
66  var backtestSeries = new Series<DateTime, double>(backtestTime, backtestStrategy);
67 
68  // Get the annual returns for the strategy
69  // ResampleEquivalence works similarly to Pandas' DataFrame.resample(...) method
70  // Here we transform the series to resample to the year's start, then we get the aggregate return from the year.
71  // Pandas equivalent:
72  //
73  // df.pct_change().resample('AS').sum().mul(100)
74  var backtestAnnualReturns = backtestSeries.ResampleEquivalence(date => new DateTime(date.Year, 1, 1), agg => agg.TotalReturns() * 100).DropMissing();
75 
76  // We need to set the datetime index first before we resample
77  var liveSeries = new Series<DateTime, double>(liveTime, liveStrategy);
78 
79  // Get the annual returns for the live strategy.
80  // Same as above, this is equivalent to:
81  //
82  // df.pct_change().resample('AS').sum().mul(100)
83  var liveAnnualReturns = liveSeries.ResampleEquivalence(date => new DateTime(date.Year, 1, 1), agg => agg.TotalReturns() * 100).DropMissing();
84 
85  // Select only the year number and pass it to the plotting library
86  backtestList.Append(backtestAnnualReturns.Keys.Select(x => x.Year).ToList().ToPython());
87  backtestList.Append(backtestAnnualReturns.Values.ToList().ToPython());
88  liveList.Append(liveAnnualReturns.Keys.Select(x => x.Year).ToList().ToPython());
89  liveList.Append(liveAnnualReturns.Values.ToList().ToPython());
90 
91  base64 = Charting.GetAnnualReturns(backtestList, liveList);
92  }
93 
94  return base64;
95  }
96  }
97 }