From f9812968d4890562326546856250b5810f34d250 Mon Sep 17 00:00:00 2001 From: jfkirk Date: Tue, 10 May 2016 11:43:56 -0400 Subject: [PATCH] MAINT: Updates July 5th Holiday for pandas 17 --- zipline/utils/calendars/exchange_calendar.py | 4 +- .../utils/calendars/nyse_exchange_calendar.py | 4 +- zipline/utils/pandas_utils.py | 102 ++---------------- 3 files changed, 16 insertions(+), 94 deletions(-) diff --git a/zipline/utils/calendars/exchange_calendar.py b/zipline/utils/calendars/exchange_calendar.py index ba32f942..e851ae78 100644 --- a/zipline/utils/calendars/exchange_calendar.py +++ b/zipline/utils/calendars/exchange_calendar.py @@ -200,14 +200,14 @@ class ExchangeCalendar(with_metaclass(ABCMeta)): is_scheduled_day_hook=self.is_open_on_day, ) - def next_start_and_end(self, date): + def next_open_and_close(self, date): return next_open_and_close( date, open_and_close_hook=self.open_and_close, next_scheduled_day_hook=self.next_trading_day, ) - def previous_start_and_end(self, date): + def previous_open_and_close(self, date): return previous_open_and_close( date, open_and_close_hook=self.open_and_close, diff --git a/zipline/utils/calendars/nyse_exchange_calendar.py b/zipline/utils/calendars/nyse_exchange_calendar.py index 0d0ef966..4032333a 100644 --- a/zipline/utils/calendars/nyse_exchange_calendar.py +++ b/zipline/utils/calendars/nyse_exchange_calendar.py @@ -39,6 +39,7 @@ from pandas.tseries.holiday import( from pandas.tseries.offsets import Day from pytz import timezone +from zipline.utils.pandas_utils import july_5th_holiday_observance from .exchange_calendar import ExchangeCalendar from .calendar_helpers import normalize_date @@ -112,7 +113,8 @@ FridayAfterIndependenceDayExcept2013 = Holiday( month=7, day=5, days_of_week=(FRIDAY,), - observance=lambda dt: None if dt.year == 2013 else dt, + # The 2013 observance lambda is pandas version-dependent + observance=july_5th_holiday_observance, start_date=Timestamp("1995-01-01"), ) USBlackFridayBefore1993 = Holiday( diff --git a/zipline/utils/pandas_utils.py b/zipline/utils/pandas_utils.py index e95e2097..9a7122c2 100644 --- a/zipline/utils/pandas_utils.py +++ b/zipline/utils/pandas_utils.py @@ -1,10 +1,10 @@ """ Utilities for working with pandas objects. """ -from itertools import product -import operator as op - import pandas as pd +from distutils.version import StrictVersion + +pandas_version = StrictVersion(pd.__version__) def explode(df): @@ -17,93 +17,13 @@ def explode(df): try: - # pandas 0.16 compat - _df_sort_values = pd.DataFrame.sort_values - _series_sort_values = pd.Series.sort_values + # This branch is hit in pandas 17 + sort_values = pd.DataFrame.sort_values except AttributeError: - _df_sort_values = pd.DataFrame.sort - _series_sort_values = pd.Series.sort + # This branch is hit in pandas 16 + sort_values = pd.DataFrame.sort - -def sort_values(ob, *args, **kwargs): - if isinstance(ob, pd.DataFrame): - return _df_sort_values(ob, *args, **kwargs) - elif isinstance(ob, pd.Series): - return _series_sort_values(ob, *args, **kwargs) - raise ValueError( - 'sort_values expected a dataframe or series, not %s: %r' % ( - type(ob).__name__, ob, - ), - ) - - -def _time_to_micros(time): - """Convert a time into microseconds since midnight. - - Parameters - ---------- - time : datetime.time - The time to convert. - - Returns - ------- - us : int - The number of microseconds since midnight. - - Notes - ----- - This does not account for leap seconds or daylight savings. - """ - seconds = time.hour * 60 * 60 + time.minute * 60 + time.second - return 1000000 * seconds + time.microsecond - - -_opmap = dict(zip( - product((True, False), repeat=3), - product((op.le, op.lt), (op.le, op.lt), (op.and_, op.or_)), -)) - - -def mask_between_time(dts, start, end, include_start=True, include_end=True): - """Return a mask of all of the datetimes in ``dts`` that are between - ``start`` and ``end``. - - Parameters - ---------- - dts : pd.DatetimeIndex - The index to mask. - start : time - Mask away times less than the start. - end : time - Mask away times greater than the end. - include_start : bool, optional - Inclusive on ``start``. - include_end : bool, optional - Inclusive on ``end``. - - Returns - ------- - mask : np.ndarray[bool] - A bool array masking ``dts``. - - See Also - -------- - :meth:`pandas.DatetimeIndex.indexer_between_time` - """ - # This function is adapted from - # `pandas.Datetime.Index.indexer_between_time` which was originally - # written by Wes McKinney, Chang She, and Grant Roch. - time_micros = dts._get_time_micros() - start_micros = _time_to_micros(start) - end_micros = _time_to_micros(end) - - left_op, right_op, join_op = _opmap[ - bool(include_start), - bool(include_end), - start_micros <= end_micros, - ] - - return join_op( - left_op(start_micros, time_micros), - right_op(time_micros, end_micros), - ) +if pandas_version >= StrictVersion('0.17.1'): + july_5th_holiday_observance = lambda dtix: dtix[dtix.year != 2013] +else: + july_5th_holiday_observance = lambda dt: None if dt.year == 2013 else dt \ No newline at end of file