From d723a20ea10fd084550ec2c5ca83307085f20155 Mon Sep 17 00:00:00 2001 From: Justin Lent Date: Tue, 3 Nov 2015 11:37:03 -0800 Subject: [PATCH 1/3] ENH implement plot_monthly_returns_timeseries in plotting.py to render monthly bars representing monthly returns of an algo --- pyfolio/plotting.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/pyfolio/plotting.py b/pyfolio/plotting.py index 79813772..59dcffdf 100644 --- a/pyfolio/plotting.py +++ b/pyfolio/plotting.py @@ -1344,3 +1344,48 @@ def show_worst_drawdown_periods(returns, top=5): drawdown_df['net drawdown in %'] = list( map(utils.round_two_dec_places, drawdown_df['net drawdown in %'])) print(drawdown_df.sort('net drawdown in %', ascending=False)) + + +def plot_monthly_returns_timeseries(returns, ax=None, **kwargs): + """ + Plots monthly returns as a timeseries. + + Parameters + ---------- + returns : pd.Series + Daily returns of the strategy, noncumulative. + - See full explanation in tears.create_full_tear_sheet. + ax : matplotlib.Axes, optional + Axes upon which to plot. + **kwargs, optional + Passed to seaborn plotting function. + + Returns + ------- + ax : matplotlib.Axes + The axes that were plotted on. + """ + + if ax is None: + ax = plt.gca() + + monthly_ret_table = timeseries.aggregate_returns(returns, 'monthly') + monthly_ret_table = monthly_ret_table.reset_index() + monthly_ret_table.columns = ['year', 'month', 'returns'] + + # Generate month-year labels for the x-axis corresponding to + # the returns plotted + date_labels = [str(i[1]) + ' - ' + str(i[0]) for i in + zip(monthly_ret_table.year.values, + monthly_ret_table.month.values)] + + sns.barplot(x=date_labels, + y=monthly_ret_table.returns, + color='steelblue') + locs, labels = plt.xticks() + plt.setp(labels, rotation=90) + + ax.set_ylabel('Return') + ax.set_xlabel('Month') + ax.set_title("Monthly Returns") + return ax From f8c3f94adafb00bd8266309f6445fc02729a1436 Mon Sep 17 00:00:00 2001 From: Justin Lent Date: Tue, 3 Nov 2015 15:53:44 -0800 Subject: [PATCH 2/3] ENH only show yearly boundary on x-axis in monthly returns timeseries plot --- pyfolio/plotting.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pyfolio/plotting.py b/pyfolio/plotting.py index 59dcffdf..a1869be6 100644 --- a/pyfolio/plotting.py +++ b/pyfolio/plotting.py @@ -1388,4 +1388,19 @@ def plot_monthly_returns_timeseries(returns, ax=None, **kwargs): ax.set_ylabel('Return') ax.set_xlabel('Month') ax.set_title("Monthly Returns") + + # only show x-labels on year boundary + xticks_coord = [] + xticks_label = [] + count = 0 + for i in monthly_ret_table.month: + if int(i) == 1: + xticks_label.append(date_labels[count]) + xticks_coord.append(count) + + count += 1 + + ax.set_xticks(xticks_coord) + ax.set_xticklabels(xticks_label) + return ax From ab34514474f66baf89ada4daefe983e68b1d468d Mon Sep 17 00:00:00 2001 From: Justin Lent Date: Wed, 4 Nov 2015 11:52:00 -0800 Subject: [PATCH 3/3] ENH re-implement using PeriodIndex. Plot yearly boundary lines. --- pyfolio/plotting.py | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/pyfolio/plotting.py b/pyfolio/plotting.py index a1869be6..57ebd0b3 100644 --- a/pyfolio/plotting.py +++ b/pyfolio/plotting.py @@ -1366,40 +1366,35 @@ def plot_monthly_returns_timeseries(returns, ax=None, **kwargs): The axes that were plotted on. """ + def cumulate_returns(x): + return timeseries.cum_returns(x)[-1] + if ax is None: ax = plt.gca() - monthly_ret_table = timeseries.aggregate_returns(returns, 'monthly') - monthly_ret_table = monthly_ret_table.reset_index() - monthly_ret_table.columns = ['year', 'month', 'returns'] - - # Generate month-year labels for the x-axis corresponding to - # the returns plotted - date_labels = [str(i[1]) + ' - ' + str(i[0]) for i in - zip(monthly_ret_table.year.values, - monthly_ret_table.month.values)] + monthly_rets = returns.resample('M', how=cumulate_returns).to_period() - sns.barplot(x=date_labels, - y=monthly_ret_table.returns, + sns.barplot(x=monthly_rets.index, + y=monthly_rets.values, color='steelblue') + locs, labels = plt.xticks() plt.setp(labels, rotation=90) - ax.set_ylabel('Return') - ax.set_xlabel('Month') - ax.set_title("Monthly Returns") - # only show x-labels on year boundary xticks_coord = [] xticks_label = [] count = 0 - for i in monthly_ret_table.month: - if int(i) == 1: - xticks_label.append(date_labels[count]) + for i in monthly_rets.index: + if i.month == 1: + xticks_label.append(i) xticks_coord.append(count) + # plot yearly boundary line + ax.axvline(count, color='gray', ls='--', alpha=0.3) count += 1 + ax.axhline(0.0, color='darkgray', ls='-') ax.set_xticks(xticks_coord) ax.set_xticklabels(xticks_label)