Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH implement plot_monthly_returns_timeseries in plotting.py to rende… #195

Merged
merged 3 commits into from
Nov 5, 2015
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions pyfolio/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -1344,3 +1344,63 @@ 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with the default labels of this plot? I suppose there's too many? How about just thinning those. The current approach feels a bit brittle.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep that's right, the defaults are super ugly because it prints the month/day/year of each rendered monthly bar and the plot becomes illegible if more than ~30 bars. 
As well, the defaults include the last business day of the month in each label (which just adds to the cluttered visual because the last business day of each month jumps around, 29, 30, 31, etc). My opinion is that including the day in the label is not really proper when labeling a monthly value, as well.
Pandas does not have a monthly frequency unit so I could not up-sample the DateTimeIndex to make it more elegant (which would have been best).
Given the above, and my desire to have an easily interpreted plot, how would you suggest improved pruning of the labels? I actually adapted my implementation from an accepted StackOverflow response
Sent from iPhone

_____________________________

From: Thomas Wiecki notifications@github.com
Sent: Wednesday, November 4, 2015 4:10 AM
Subject: Re: [pyfolio] ENH implement plot_monthly_returns_timeseries in plotting.py to rende… (#195)
To: quantopian/pyfolio pyfolio@noreply.github.com
Cc: Justin Lent justinlent@gmail.com

In pyfolio/plotting.py: > + 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

What's wrong with the default labels of this plot? I suppose there's too many? How about just thinning those. The current approach feels a bit brittle.


Reply to this email directly or view it on GitHub.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@twiecki ...Actually, my bad, looks like Pandas does support a Monthly unit, under the concept of a Period. so timestamps can be converted to periods to drop the concept of a "day" in monthly data and have plots generated properly. I'll go ahead and re-implement...  Ohhh Pandas, so convoluted sometimes...

Sent from iPhone

On Wed, Nov 4, 2015 at 4:10 AM -0800, "Thomas Wiecki" notifications@github.com wrote:

In pyfolio/plotting.py:

  • 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

What's wrong with the default labels of this plot? I suppose there's too many? How about just thinning those. The current approach feels a bit brittle.


Reply to this email directly or view it on GitHub.

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")

# 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