BUG: Use arrays for week/month group calculations.

In pandas 0.18, the behavior of ``nth()`` changed so that Grouper no
longer can be easily used to recover group labels.

Instead of using the built-in grouper behavior, we use a groupby on two
arrays we build ourselves.  This recovers the original behavior, and is
about 2x faster as a bonus.
This commit is contained in:
Scott Sanderson
2016-09-20 17:12:07 -04:00
parent f8734e8721
commit 74277490d5
+24 -15
View File
@@ -17,6 +17,7 @@ from collections import namedtuple
import six
import datetime
import numpy as np
import pandas as pd
import pytz
@@ -407,17 +408,21 @@ class TradingDayOfWeekRule(six.with_metaclass(ABCMeta, StatelessRule)):
self.td_delta = (-n - 1) if invert else n
@lazyval
def execution_periods(self):
# calculate the list of periods that match the given criteria
return self.cal.schedule.groupby(
pd.Grouper(freq="W")
).nth(int(self.td_delta)).index
def should_trigger(self, dt):
# is this market minute's period in the list of execution periods?
return self.cal.minute_to_session_label(dt) in \
self.execution_periods
val = self.cal.minute_to_session_label(dt, direction="none").value
return val in self.execution_period_values
@lazyval
def execution_period_values(self):
# calculate the list of periods that match the given criteria
sessions = self.cal.all_sessions
return set(
pd.Series(data=sessions)
.groupby([sessions.year, sessions.weekofyear])
.nth(self.td_delta)
.astype(np.int64)
)
class NthTradingDayOfWeek(TradingDayOfWeekRule):
@@ -448,15 +453,19 @@ class TradingDayOfMonthRule(six.with_metaclass(ABCMeta, StatelessRule)):
def should_trigger(self, dt):
# is this market minute's period in the list of execution periods?
return self.cal.minute_to_session_label(dt) in \
self.execution_periods
value = self.cal.minute_to_session_label(dt, direction="none").value
return value in self.execution_period_values
@lazyval
def execution_periods(self):
def execution_period_values(self):
# calculate the list of periods that match the given criteria
return self.cal.schedule.groupby(
pd.Grouper(freq="M")
).nth(int(self.td_delta)).index
sessions = self.cal.all_sessions
return set(
pd.Series(data=sessions)
.groupby([sessions.year, sessions.month])
.nth(self.td_delta)
.astype(np.int64)
)
class NthTradingDayOfMonth(TradingDayOfMonthRule):