Skip to content

Commit 957d5cc

Browse files
authored
Merge pull request #328 from luca-s/new_pandas
MAINT: code refactoring to make it compatible with pandas 0.23.4
2 parents e67d2b5 + b499773 commit 957d5cc

File tree

4 files changed

+51
-19
lines changed

4 files changed

+51
-19
lines changed

alphalens/performance.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,6 @@ def to_weights(group, _demeaned, _equal_weight):
201201
if group_adjust:
202202
weights = weights.groupby(level='date').apply(to_weights, False, False)
203203

204-
# preserve freq, which contains trading calendar information
205-
weights.index.levels[0].freq = factor_data.index.levels[0].freq
206204
return weights
207205

208206

@@ -253,8 +251,6 @@ def factor_returns(factor_data,
253251
else:
254252
returns = weighted_returns.groupby(level='date').sum()
255253

256-
# preserve freq, which contains trading calendar information
257-
returns.index.freq = factor_data.index.levels[0].freq
258254
return returns
259255

260256

alphalens/plotting.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ def plot_monthly_ic_heatmap(mean_monthly_ic, ax=None):
711711
return ax
712712

713713

714-
def plot_cumulative_returns(factor_returns, period, title=None, ax=None):
714+
def plot_cumulative_returns(factor_returns, period, freq, title=None, ax=None):
715715
"""
716716
Plots the cumulative returns of the returns series passed in.
717717
@@ -724,6 +724,11 @@ def plot_cumulative_returns(factor_returns, period, title=None, ax=None):
724724
Length of period for which the returns are computed (e.g. 1 day)
725725
if 'period' is a string it must follow pandas.Timedelta constructor
726726
format (e.g. '1 days', '1D', '30m', '3h', '1D1h', etc)
727+
freq : pandas DateOffset
728+
Used to specify a particular trading calendar e.g. BusinessDay or Day
729+
Usually this is inferred from utils.infer_trading_calendar, which is
730+
called by either get_clean_factor_and_forward_returns or
731+
compute_forward_returns
727732
title: string, optional
728733
Custom title
729734
ax : matplotlib.Axes, optional
@@ -737,7 +742,7 @@ def plot_cumulative_returns(factor_returns, period, title=None, ax=None):
737742
if ax is None:
738743
f, ax = plt.subplots(1, 1, figsize=(18, 6))
739744

740-
factor_returns = perf.cumulative_returns(factor_returns, period)
745+
factor_returns = perf.cumulative_returns(factor_returns, period, freq)
741746

742747
factor_returns.plot(ax=ax, lw=3, color='forestgreen', alpha=0.6)
743748
ax.set(ylabel='Cumulative Returns',
@@ -751,6 +756,7 @@ def plot_cumulative_returns(factor_returns, period, title=None, ax=None):
751756

752757
def plot_cumulative_returns_by_quantile(quantile_returns,
753758
period,
759+
freq,
754760
ax=None):
755761
"""
756762
Plots the cumulative returns of various factor quantiles.
@@ -763,6 +769,11 @@ def plot_cumulative_returns_by_quantile(quantile_returns,
763769
Length of period for which the returns are computed (e.g. 1 day)
764770
if 'period' is a string it must follow pandas.Timedelta constructor
765771
format (e.g. '1 days', '1D', '30m', '3h', '1D1h', etc)
772+
freq : pandas DateOffset
773+
Used to specify a particular trading calendar e.g. BusinessDay or Day
774+
Usually this is inferred from utils.infer_trading_calendar, which is
775+
called by either get_clean_factor_and_forward_returns or
776+
compute_forward_returns
766777
ax : matplotlib.Axes, optional
767778
Axes upon which to plot.
768779
@@ -776,7 +787,7 @@ def plot_cumulative_returns_by_quantile(quantile_returns,
776787

777788
ret_wide = quantile_returns.unstack('factor_quantile')
778789

779-
cum_ret = ret_wide.apply(perf.cumulative_returns, period=period)
790+
cum_ret = ret_wide.apply(perf.cumulative_returns, period=period, freq=freq)
780791
cum_ret = cum_ret.loc[:, ::-1] # we want negative quantiles as 'red'
781792

782793
cum_ret.plot(lw=2, ax=ax, cmap=cm.coolwarm)

alphalens/tears.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import matplotlib.gridspec as gridspec
1818
import matplotlib.pyplot as plt
1919
import pandas as pd
20+
import warnings
2021

2122
from . import plotting
2223
from . import performance as perf
@@ -249,21 +250,35 @@ def create_returns_tear_sheet(factor_data,
249250
ylim_percentiles=(1, 99),
250251
ax=gf.next_row())
251252

253+
trading_calendar = factor_data.index.levels[0].freq
254+
if trading_calendar is None:
255+
trading_calendar = pd.tseries.offsets.BDay()
256+
warnings.warn(
257+
"'freq' not set in factor_data index: assuming business day",
258+
UserWarning
259+
)
260+
252261
for p in factor_returns:
253262

254263
title = ('Factor Weighted '
255264
+ ('Group Neutral ' if group_neutral else '')
256265
+ ('Long/Short ' if long_short else '')
257266
+ "Portfolio Cumulative Return ({} Period)".format(p))
258267

259-
plotting.plot_cumulative_returns(factor_returns[p],
260-
period=p,
261-
title=title,
262-
ax=gf.next_row())
268+
plotting.plot_cumulative_returns(
269+
factor_returns[p],
270+
period=p,
271+
freq=trading_calendar,
272+
title=title,
273+
ax=gf.next_row()
274+
)
263275

264-
plotting.plot_cumulative_returns_by_quantile(mean_quant_ret_bydate[p],
265-
period=p,
266-
ax=gf.next_row())
276+
plotting.plot_cumulative_returns_by_quantile(
277+
mean_quant_ret_bydate[p],
278+
period=p,
279+
freq=trading_calendar,
280+
ax=gf.next_row()
281+
)
267282

268283
ax_mean_quantile_returns_spread_ts = [gf.next_row()
269284
for x in range(fr_cols)]
@@ -665,11 +680,22 @@ def create_event_study_tear_sheet(factor_data,
665680
ylim_percentiles=(1, 99),
666681
ax=gf.next_row())
667682

683+
trading_calendar = factor_data.index.levels[0].freq
684+
if trading_calendar is None:
685+
trading_calendar = pd.tseries.offsets.BDay()
686+
warnings.warn(
687+
"'freq' not set in factor_data index: assuming business day",
688+
UserWarning
689+
)
690+
668691
for p in factor_returns:
669692

670-
plotting.plot_cumulative_returns(factor_returns[p],
671-
period=p,
672-
ax=gf.next_row())
693+
plotting.plot_cumulative_returns(
694+
factor_returns[p],
695+
period=p,
696+
freq=trading_calendar,
697+
ax=gf.next_row()
698+
)
673699

674700
plt.show()
675701
gf.close()

alphalens/tests/test_performance.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,9 +747,8 @@ def test_cumulative_returns(self, returns, ret_freq, period_len,
747747
period_len = Timedelta(period_len)
748748
index = date_range('1/1/1999', periods=len(returns), freq=ret_freq)
749749
returns = Series(returns, index=index)
750-
returns.index.freq = ret_freq_class
751750

752-
cum_ret = cumulative_returns(returns, period_len)
751+
cum_ret = cumulative_returns(returns, period_len, ret_freq_class)
753752

754753
expected = Series(expected_vals, index=cum_ret.index)
755754

0 commit comments

Comments
 (0)