/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Linq;
using Deedle;
using Python.Runtime;
using QuantConnect.Packets;
namespace QuantConnect.Report.ReportElements
{
internal sealed class AnnualReturnsReportElement : ChartReportElement
{
private LiveResult _live;
private BacktestResult _backtest;
///
/// Create a new plot of annual returns
///
/// Name of the widget
/// Location of injection
/// Backtest result object
/// Live result object
public AnnualReturnsReportElement(string name, string key, BacktestResult backtest, LiveResult live)
{
_live = live;
_backtest = backtest;
Name = name;
Key = key;
}
///
/// Generate the annual returns plot using the python libraries.
///
public override string Render()
{
var backtestReturns = ResultsUtil.EquityPoints(_backtest);
var liveReturns = ResultsUtil.EquityPoints(_live);
var backtestTime = backtestReturns.Keys.ToList();
var backtestStrategy = backtestReturns.Values.ToList();
var liveTime = liveReturns.Keys.ToList();
var liveStrategy = liveReturns.Values.ToList();
var base64 = "";
using (Py.GIL())
{
var backtestList = new PyList();
var liveList = new PyList();
// We need to set the datetime index first before we resample
//var backtestSeries = Pandas.Series(backtestStrategy.ToPython());
var backtestSeries = new Series(backtestTime, backtestStrategy);
// Get the annual returns for the strategy
// ResampleEquivalence works similarly to Pandas' DataFrame.resample(...) method
// Here we transform the series to resample to the year's start, then we get the aggregate return from the year.
// Pandas equivalent:
//
// df.pct_change().resample('AS').sum().mul(100)
var backtestAnnualReturns = backtestSeries.ResampleEquivalence(date => new DateTime(date.Year, 1, 1), agg => agg.TotalReturns() * 100).DropMissing();
// We need to set the datetime index first before we resample
var liveSeries = new Series(liveTime, liveStrategy);
// Get the annual returns for the live strategy.
// Same as above, this is equivalent to:
//
// df.pct_change().resample('AS').sum().mul(100)
var liveAnnualReturns = liveSeries.ResampleEquivalence(date => new DateTime(date.Year, 1, 1), agg => agg.TotalReturns() * 100).DropMissing();
// Select only the year number and pass it to the plotting library
backtestList.Append(backtestAnnualReturns.Keys.Select(x => x.Year).ToList().ToPython());
backtestList.Append(backtestAnnualReturns.Values.ToList().ToPython());
liveList.Append(liveAnnualReturns.Keys.Select(x => x.Year).ToList().ToPython());
liveList.Append(liveAnnualReturns.Values.ToList().ToPython());
base64 = Charting.GetAnnualReturns(backtestList, liveList);
}
return base64;
}
}
}