From 8621eb222324d30896576c7c69992431a9cc3508 Mon Sep 17 00:00:00 2001 From: Thomas Wiecki Date: Tue, 11 Dec 2012 12:12:32 -0500 Subject: [PATCH 1/2] Revert "STY: Removed drop_condition arguments." This reverts commit c7383f6275b3b145fadecd261c28e9344a8e4508. --- zipline/transforms/utils.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/zipline/transforms/utils.py b/zipline/transforms/utils.py index a5d47803..ea8b7612 100644 --- a/zipline/transforms/utils.py +++ b/zipline/transforms/utils.py @@ -241,7 +241,12 @@ class EventWindow(object): # Clear out any expired events. drop_condition changes depending # on whether or not we are running in market_aware mode. - while self.drop_condition(): + # + # oldest newest + # | | + # V V + while self.drop_condition(self.ticks[0].dt, self.ticks[-1].dt): + # popleft removes and returns the oldest tick in self.ticks popped = self.ticks.popleft() @@ -249,7 +254,7 @@ class EventWindow(object): # behavior for removing ticks. self.handle_remove(popped) - def out_of_market_window(self): + def out_of_market_window(self, oldest, newest): # Find number of unique days in window # Note that this assumes that each day we received an # event is a trading day. @@ -257,9 +262,8 @@ class EventWindow(object): return len(unique_dts) > self.window_length - def out_of_delta(self): - # newest - oldest - return (self.ticks[-1].dt - self.ticks[0].dt) >= self.delta + def out_of_delta(self, oldest, newest): + return (newest - oldest) >= self.delta # All event windows expect to receive events with datetime fields # that arrive in sorted order. From f8e4d8ade6fa42fa99181e447e373515f2c9ef88 Mon Sep 17 00:00:00 2001 From: Thomas Wiecki Date: Tue, 11 Dec 2012 12:12:51 -0500 Subject: [PATCH 2/2] Revert "BUG: EventWindow now always contains constant number of days." This reverts commit 7a0a6f5231ce6991a61ccce1cc68e5f5c11c84ae. --- tests/test_transforms.py | 8 ++++++-- zipline/transforms/utils.py | 35 +++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/tests/test_transforms.py b/tests/test_transforms.py index 2f1b2d0d..f3b2ffe2 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -123,7 +123,11 @@ class TestEventWindow(TestCase): # Record the length of the window after each event. lengths.append(len(window.ticks)) - assert lengths == [1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3] + # The window stretches out during the weekend because we wait + # to drop events until the weekend ends. The last window is + # briefly longer because it doesn't complete a full day. The + # window then shrinks once the day completes + assert lengths == [1, 2, 3, 3, 3, 4, 5, 5, 5, 3, 4, 3] assert window.added == events assert window.removed == events[:-3] @@ -142,7 +146,7 @@ class TestEventWindow(TestCase): # Record the length of the window after each event. lengths.append(len(window.ticks)) - assert lengths == [1, 2, 2, 2, 2] + assert lengths == [1, 2, 3, 3, 2] assert window.added == events assert window.removed == events[:-2] diff --git a/zipline/transforms/utils.py b/zipline/transforms/utils.py index ea8b7612..4ee0a999 100644 --- a/zipline/transforms/utils.py +++ b/zipline/transforms/utils.py @@ -239,6 +239,9 @@ class EventWindow(object): # adding new ticks. self.handle_add(event) + if self.market_aware: + self.add_new_holidays(event.dt) + # Clear out any expired events. drop_condition changes depending # on whether or not we are running in market_aware mode. # @@ -254,13 +257,33 @@ class EventWindow(object): # behavior for removing ticks. self.handle_remove(popped) - def out_of_market_window(self, oldest, newest): - # Find number of unique days in window - # Note that this assumes that each day we received an - # event is a trading day. - unique_dts = set([event.dt.date() for event in self.ticks]) + def add_new_holidays(self, newest): + # Add to our tracked window any untracked holidays that are + # older than our newest event. (newest should always be + # self.ticks[-1]) + while len(self.all_holidays) > 0 and self.all_holidays[0] <= newest: + self.cur_holidays.append(self.all_holidays.popleft()) - return len(unique_dts) > self.window_length + def drop_old_holidays(self, oldest): + # Drop from our tracked window any holidays that are older + # than our oldest tracked event. (oldest should always + # be self.ticks[0]) + while len(self.cur_holidays) > 0 and self.cur_holidays[0] < oldest: + self.cur_holidays.popleft() + + def out_of_market_window(self, oldest, newest): + self.drop_old_holidays(oldest) + calendar_dates_between = (newest.date() - oldest.date()).days + holidays_between = len(self.cur_holidays) + trading_days_between = calendar_dates_between - holidays_between + + # "Put back" a day if oldest is earlier in its day than newest, + # reflecting the fact that we haven't yet completed the last + # day in the window. + if oldest.time() > newest.time(): + trading_days_between -= 1 + + return trading_days_between >= self.window_length def out_of_delta(self, oldest, newest): return (newest - oldest) >= self.delta