MAINT: Pandas compat for rolling_*.

This commit is contained in:
Scott Sanderson
2016-07-20 20:03:35 -04:00
parent a39a6e1bbf
commit ca54721058
2 changed files with 107 additions and 11 deletions
+25 -11
View File
@@ -25,12 +25,8 @@ from pandas import (
Categorical,
DataFrame,
date_range,
ewma,
ewmstd,
Int64Index,
MultiIndex,
rolling_apply,
rolling_mean,
Series,
Timestamp,
)
@@ -84,6 +80,12 @@ from zipline.testing.fixtures import (
)
from zipline.utils.memoize import lazyval
from zipline.utils.numpy_utils import bool_dtype, datetime64ns_dtype
from zipline.utils.pandas_utils import (
ewma,
ewmstd,
rolling_apply,
rolling_mean,
)
class RollingSumDifference(CustomFactor):
@@ -1009,14 +1011,16 @@ class SyntheticBcolzTestCase(WithAdjustmentReader,
# computed results to be computed using values anchored on the
# **previous** day's data.
expected_raw = rolling_mean(
expected_bar_values_2d(
dates - self.trading_calendar.day,
self.equity_info,
'close',
DataFrame(
expected_bar_values_2d(
dates - self.trading_calendar.day,
self.equity_info,
'close',
),
),
window_length,
min_periods=1,
)
).values
expected = DataFrame(
# Truncate off the extra rows needed to compute the SMAs.
@@ -1122,19 +1126,29 @@ class ParameterizedFactorTestCase(WithTradingEnvironment, ZiplineTestCase):
def expected_ewma(self, window_length, decay_rate):
alpha = 1 - decay_rate
span = (2 / alpha) - 1
# XXX: This is a comically inefficient way to compute a windowed EWMA.
# Don't use it outside of testing. We're using rolling-apply of an
# ewma (which is itself a rolling-window function) because we only want
# to look at ``window_length`` rows at a time.
return rolling_apply(
self.raw_data,
window_length,
lambda window: ewma(window, span=span)[-1],
lambda window: ewma(DataFrame(window), span=span).values[-1],
)[window_length:]
def expected_ewmstd(self, window_length, decay_rate):
alpha = 1 - decay_rate
span = (2 / alpha) - 1
# XXX: This is a comically inefficient way to compute a windowed EWMSTD.
# Don't use it outside of testing. We're using rolling-apply of an
# ewma (which is itself a rolling-window function) because we only want
# to look at ``window_length`` rows at a time.
return rolling_apply(
self.raw_data,
window_length,
lambda window: ewmstd(window, span=span)[-1],
lambda window: ewmstd(DataFrame(window), span=span).values[-1],
)[window_length:]
@parameterized.expand([
+82
View File
@@ -160,3 +160,85 @@ def timedelta_to_integral_minutes(delta):
Convert a pd.Timedelta to a number of minutes as an int.
"""
return timedelta_to_integral_seconds(delta) // 60
# Remove when we drop support for 0.17
if pandas_version >= StrictVersion('0.18'):
def rolling_mean(arg,
window,
min_periods=None,
freq=None,
center=False,
**kwargs):
return arg.rolling(
window,
min_periods=min_periods,
freq=freq,
center=center,
**kwargs
).mean()
def rolling_apply(arg,
window,
func,
min_periods=None,
freq=None,
center=False,
**kwargs):
return arg.rolling(
window,
min_periods=min_periods,
freq=freq,
center=center,
**kwargs
).apply(func)
def ewma(arg,
com=None,
span=None,
halflife=None,
alpha=None,
min_periods=0,
freq=None,
adjust=True,
how=None,
ignore_na=False):
return arg.ewm(
com=com,
span=span,
halflife=halflife,
alpha=alpha,
min_periods=min_periods,
freq=freq,
adjust=adjust,
ignore_na=ignore_na,
).mean()
def ewmstd(arg,
com=None,
span=None,
halflife=None,
alpha=None,
min_periods=0,
freq=None,
adjust=True,
how=None,
ignore_na=False):
return arg.ewm(
com=com,
span=span,
halflife=halflife,
alpha=alpha,
min_periods=min_periods,
freq=freq,
adjust=adjust,
ignore_na=ignore_na,
).std()
else:
rolling_mean = pd.rolling_mean
rolling_apply = pd.rolling_apply
ewma = pd.ewma
ewmstd = pd.ewmstd