Skip to content

Commit

Permalink
Revert "Removed group_adjust/group_neutral flag from information anal…
Browse files Browse the repository at this point in the history
…ysis API"

This reverts commit 2eed755.

The original commit was a mistake as the IC is computed both on the full
factor and by sector, so the flags don't change the IC at sector level but
they are still needed when computed the IC for the full factor
  • Loading branch information
luca-s committed Nov 18, 2017
1 parent f21bbb5 commit dea4e1a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 15 deletions.
11 changes: 10 additions & 1 deletion alphalens/performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@


def factor_information_coefficient(factor_data,
group_adjust=False,
by_group=False):
"""
Computes the Spearman Rank Correlation based Information Coefficient (IC)
Expand All @@ -38,6 +39,8 @@ def factor_information_coefficient(factor_data,
each period, the factor quantile/bin that factor value belongs to, and
(optionally) the group the asset belongs to.
- See full explanation in utils.get_clean_factor_and_forward_returns
group_adjust : bool
Demean forward returns by group before computing IC.
by_group : bool
If True, compute period wise IC separately for each group.
Expand All @@ -58,6 +61,9 @@ def src_ic(group):

grouper = [factor_data.index.get_level_values('date')]

if group_adjust:
factor_data = utils.demean_forward_returns(factor_data,
grouper + ['group'])
if by_group:
grouper.append('group')

Expand All @@ -68,6 +74,7 @@ def src_ic(group):


def mean_information_coefficient(factor_data,
group_adjust=False,
by_group=False,
by_time=None):
"""
Expand All @@ -85,6 +92,8 @@ def mean_information_coefficient(factor_data,
each period, the factor quantile/bin that factor value belongs to, and
(optionally) the group the asset belongs to.
- See full explanation in utils.get_clean_factor_and_forward_returns
group_adjust : bool
Demean forward returns by group before computing IC.
by_group : bool
If True, take the mean IC for each group.
by_time : str (pd time_rule), optional
Expand All @@ -99,7 +108,7 @@ def mean_information_coefficient(factor_data,
forward price movement windows.
"""

ic = factor_information_coefficient(factor_data, by_group)
ic = factor_information_coefficient(factor_data, group_adjust, by_group)

grouper = []
if by_time is not None:
Expand Down
24 changes: 14 additions & 10 deletions alphalens/tears.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def call_w_context(*args, **kwargs):
kwargs['group_neutral'] = group_adjust
warnings.warn("create_full_tear_sheet: 'group_adjust' argument "
"is now deprecated and replaced by 'group_neutral'",
category=DeprecationWarning, stacklevel=3)
category=DeprecationWarning, stacklevel=2)
return func(*args, **kwargs)
return call_w_context

Expand All @@ -95,6 +95,7 @@ def create_information_tear_sheet_api_change_warning(func):
by_group=False)
New API:
create_information_tear_sheet(factor_data,
group_neutral=False,
by_group=False)
Eventually this function can be deleted
Expand All @@ -103,16 +104,11 @@ def create_information_tear_sheet_api_change_warning(func):
def call_w_context(*args, **kwargs):
group_adjust = kwargs.pop('group_adjust', None)
if group_adjust is not None:
kwargs['group_neutral'] = group_adjust
warnings.warn("create_information_tear_sheet: 'group_adjust' "
"argument is now deprecated.",
category=DeprecationWarning, stacklevel=2)
elif len(args) == 3 or (len(args) == 2 and args[1] is True):
warnings.warn("create_information_tear_sheet: 'group_adjust' "
"argument has been removed. Please consider using "
"keyword arguments instead of positional ones to "
"avoid unexpected behaviour.",
"argument is now deprecated and replaced by "
"'group_neutral'",
category=DeprecationWarning, stacklevel=2)

return func(*args, **kwargs)
return call_w_context

Expand Down Expand Up @@ -399,6 +395,7 @@ def create_returns_tear_sheet(factor_data,
@create_information_tear_sheet_api_change_warning
@plotting.customize
def create_information_tear_sheet(factor_data,
group_neutral=False,
by_group=False):
"""
Creates a tear sheet for information analysis of a factor.
Expand All @@ -411,11 +408,13 @@ def create_information_tear_sheet(factor_data,
each period, the factor quantile/bin that factor value belongs to, and
(optionally) the group the asset belongs to.
- See full explanation in utils.get_clean_factor_and_forward_returns
group_neutral : bool
Demean forward returns by group before computing IC.
by_group : bool
If True, display graphs separately for each group.
"""

ic = perf.factor_information_coefficient(factor_data)
ic = perf.factor_information_coefficient(factor_data, group_neutral)

plotting.plot_information_table(ic)

Expand All @@ -436,6 +435,7 @@ def create_information_tear_sheet(factor_data,

mean_monthly_ic = \
perf.mean_information_coefficient(factor_data,
group_adjust=group_neutral,
by_group=False,
by_time="M")
ax_monthly_ic_heatmap = [gf.next_cell() for x in range(fr_cols)]
Expand All @@ -445,6 +445,7 @@ def create_information_tear_sheet(factor_data,
if by_group:
mean_group_ic = \
perf.mean_information_coefficient(factor_data,
group_adjust=group_neutral,
by_group=True)

plotting.plot_ic_by_group(mean_group_ic, ax=gf.next_row())
Expand Down Expand Up @@ -523,6 +524,8 @@ def create_full_tear_sheet(factor_data,
Should this computation happen on a group neutral portfolio?
- See tears.create_returns_tear_sheet for details on how this flag
affects returns analysis
- See tears.create_information_tear_sheet for details on how this
flag affects information analysis
by_group : bool
If True, display graphs separately for each group.
"""
Expand All @@ -534,6 +537,7 @@ def create_full_tear_sheet(factor_data,
by_group,
set_context=False)
create_information_tear_sheet(factor_data,
group_neutral,
by_group,
set_context=False)
create_turnover_tear_sheet(factor_data, set_context=False)
Expand Down
20 changes: 17 additions & 3 deletions alphalens/tests/test_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,31 @@ class PerformanceTestCase(TestCase):
dtype="category")

@parameterized.expand([(factor_data, [4, 3, 2, 1, 1, 2, 3, 4],
False,
False, False,
dr,
[-1., -1.],
),
(factor_data, [1, 2, 3, 4, 4, 3, 2, 1],
False,
False, False,
dr,
[1., 1.],
),
(factor_data, [1, 2, 3, 4, 4, 3, 2, 1],
True,
False, True,
MultiIndex.from_product(
[dr, [1, 2]], names=['date', 'group']),
[1., 1., 1., 1.],
),
(factor_data, [1, 2, 3, 4, 4, 3, 2, 1],
True, True,
MultiIndex.from_product(
[dr, [1, 2]], names=['date', 'group']),
[1., 1., 1., 1.],
)])
def test_information_coefficient(self,
factor_data,
forward_returns,
group_adjust,
by_group,
expected_ix,
expected_ic_val):
Expand All @@ -83,6 +90,7 @@ def test_information_coefficient(self,
data=forward_returns)

ic = factor_information_coefficient(factor_data=factor_data,
group_adjust=group_adjust,
by_group=by_group)

expected_ic_df = DataFrame(index=expected_ix,
Expand All @@ -94,25 +102,29 @@ def test_information_coefficient(self,
@parameterized.expand([(factor_data,
[4, 3, 2, 1, 1, 2, 3, 4],
False,
False,
'D',
dr,
[-1., -1.]),
(factor_data,
[1, 2, 3, 4, 4, 3, 2, 1],
False,
False,
'W',
DatetimeIndex(['2015-01-04'],
name='date',
freq='W-SUN'),
[1.]),
(factor_data,
[1, 2, 3, 4, 4, 3, 2, 1],
False,
True,
None,
Int64Index([1, 2], name='group'),
[1., 1.]),
(factor_data,
[1, 2, 3, 4, 4, 3, 2, 1],
False,
True,
'W',
MultiIndex.from_product(
Expand All @@ -124,6 +136,7 @@ def test_information_coefficient(self,
def test_mean_information_coefficient(self,
factor_data,
forward_returns,
group_adjust,
by_group,
by_time,
expected_ix,
Expand All @@ -133,6 +146,7 @@ def test_mean_information_coefficient(self,
data=forward_returns)

ic = mean_information_coefficient(factor_data,
group_adjust=group_adjust,
by_group=by_group,
by_time=by_time)

Expand Down
3 changes: 2 additions & 1 deletion alphalens/tests/test_tears.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ def test_create_information_tear_sheet(
periods=periods,
filter_zscore=filter_zscore)

create_information_tear_sheet(factor_data, by_group=False)
create_information_tear_sheet(
factor_data, group_neutral=False, by_group=False)

@parameterized.expand([(2, (2, 3, 6), True),
(4, (1, 2, 3, 7), False)])
Expand Down

0 comments on commit dea4e1a

Please sign in to comment.