-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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 Ability to make cones with multiple shades stdev regions #168
Changes from 3 commits
aab448f
b81e207
3cffef4
efcf5ae
8da2192
8300be5
b3c2215
2a0c49c
cf83da2
50540ff
62958f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -611,10 +611,18 @@ def plot_rolling_returns( | |
label='Live', ax=ax, **kwargs) | ||
|
||
if cone_std is not None: | ||
cone_df = timeseries.cone_rolling( | ||
returns, | ||
num_stdev=cone_std, | ||
cone_fit_end_date=live_start_date) | ||
# check to see if we're just rendering a single cone, or multiple | ||
# cones at various stddevs, defined as elements of cone_std | ||
if type(cone_std) is list: | ||
cone_df = timeseries.cone_rolling( | ||
returns, | ||
num_stdev=cone_std[0], | ||
cone_fit_end_date=live_start_date) | ||
else: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can just replace There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing that out (I actually didn't realize i could re-use a parameter variable like that. Is this only possible because the parameter does not have risk of actually just being a pointer to an upstream variable? I'm always confused as to when Python treats an input parameter as merely a pointer to the upstream variable) |
||
cone_df = timeseries.cone_rolling( | ||
returns, | ||
num_stdev=cone_std, | ||
cone_fit_end_date=live_start_date) | ||
|
||
cone_df_fit = cone_df[cone_df.index < live_start_date] | ||
|
||
|
@@ -641,7 +649,25 @@ def plot_rolling_returns( | |
ax.fill_between(cone_df_live.index, | ||
cone_df_live.sd_down, | ||
cone_df_live.sd_up, | ||
color='red', alpha=0.30) | ||
color='steelblue', alpha=0.25) | ||
|
||
if type(cone_std) is list: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't we generate the cones in one loop? |
||
for cone_i in list(range(1, len(cone_std))): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
cone_df = timeseries.cone_rolling( | ||
returns, | ||
num_stdev=cone_std[cone_i], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
cone_fit_end_date=live_start_date) | ||
|
||
cone_df_fit = cone_df[cone_df.index < live_start_date] | ||
|
||
cone_df_live = cone_df[cone_df.index > live_start_date] | ||
temp_keep_days = cone_df_live.index < returns.index[-1] | ||
cone_df_live = cone_df_live[temp_keep_days] | ||
|
||
ax.fill_between(cone_df_live.index, | ||
cone_df_live.sd_down, | ||
cone_df_live.sd_up, | ||
color='steelblue', alpha=0.25) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would take this whole logic and put it into a local function ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I basically did the quickest implementation to touch the least amount of code so yea it can definitely be cleaned up further. I figured it's not that computationally expensive so went to simple rather than elegant route There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's worth our time to go the elegant route. Technical debt has a very high interest rate. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok that makes sense - Yeah I can do this tonight most likely. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I committed the update that factors out the cone rendering into a local draw_cone. definitely cleaner! by cleaning it up it also let me easily turn off the cone in the volatility match case -- was only a 3 "word" change so I snuck it in here instead of its own PR--yeah I know not great practice ;) Sent from iPhone On Tue, Oct 13, 2015 at 1:58 PM -0700, "Thomas Wiecki" notifications@github.com wrote: In pyfolio/plotting.py:
I think it's worth our time to go the elegant route. Technical debt has a very high interest rate. — |
||
|
||
ax.axhline(1.0, linestyle='--', color='black', lw=2) | ||
ax.set_ylabel('Cumulative returns') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,7 @@ def create_full_tear_sheet(returns, positions=None, transactions=None, | |
benchmark_rets=None, | ||
gross_lev=None, | ||
live_start_date=None, bayesian=False, | ||
cone_std=1.0, set_context=True): | ||
cone_std=[1.0, 1.5, 2.0], set_context=True): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor stylistic but I'd change these to be tuples. |
||
""" | ||
Generate a number of tear sheets that are useful | ||
for analyzing a strategy's performance. | ||
|
@@ -140,7 +140,7 @@ def create_full_tear_sheet(returns, positions=None, transactions=None, | |
|
||
@plotting_context | ||
def create_returns_tear_sheet(returns, live_start_date=None, | ||
cone_std=1.0, | ||
cone_std=[1.0, 1.5, 2.0], | ||
benchmark_rets=None, | ||
return_fig=False): | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having separate logic for list and float case. I would convert every float to a list, then have one loop.