diff --git a/tests/events/test_events.py b/tests/events/test_events.py index 3bc8ffe2..e7c6ca8e 100644 --- a/tests/events/test_events.py +++ b/tests/events/test_events.py @@ -312,6 +312,19 @@ class StatelessRulesTests(RuleTestCase): else: self.assertTrue(should_trigger(minute)) + def test_invalid_offset(self): + with self.assertRaises(ValueError): + AfterOpen(hours=12, minutes=1) + + with self.assertRaises(ValueError): + AfterOpen(hours=0, minutes=0) + + with self.assertRaises(ValueError): + BeforeClose(hours=12, minutes=1) + + with self.assertRaises(ValueError): + BeforeClose(hours=0, minutes=0) + def test_BeforeClose(self): minute_groups = minutes_for_days(self.cal, ordered_days=True) should_trigger = self.before_close.should_trigger diff --git a/tests/events/test_events_cme.py b/tests/events/test_events_cme.py index 59483a96..b6e12efc 100644 --- a/tests/events/test_events_cme.py +++ b/tests/events/test_events_cme.py @@ -15,7 +15,9 @@ from unittest import TestCase import pandas as pd -from test_events import StatefulRulesTests, StatelessRulesTests +from test_events import StatefulRulesTests, StatelessRulesTests, \ + minutes_for_days +from zipline.utils.events import AfterOpen class TestStatelessRulesCME(StatelessRulesTests, TestCase): @@ -24,6 +26,18 @@ class TestStatelessRulesCME(StatelessRulesTests, TestCase): HALF_SESSION = pd.Timestamp("2014-07-04", tz='UTC') FULL_SESSION = pd.Timestamp("2014-09-24", tz='UTC') + def test_far_after_open(self): + minute_groups = minutes_for_days(self.cal, ordered_days=True) + after_open = AfterOpen(hours=9, minutes=25) + after_open.cal = self.cal + + for session_minutes in minute_groups: + for i, minute in enumerate(session_minutes): + if i != 564: + self.assertFalse(after_open.should_trigger(minute)) + else: + self.assertTrue(after_open.should_trigger(minute)) + class TestStatefulRulesCME(StatefulRulesTests, TestCase): CALENDAR_STRING = "CME" diff --git a/tests/events/test_events_nyse.py b/tests/events/test_events_nyse.py index c6f9bcdd..ac2e9087 100644 --- a/tests/events/test_events_nyse.py +++ b/tests/events/test_events_nyse.py @@ -18,10 +18,12 @@ import pandas as pd from nose_parameterized import parameterized from zipline.testing import parameter_space -from zipline.utils.events import NDaysBeforeLastTradingDayOfWeek, AfterOpen +from zipline.utils.events import NDaysBeforeLastTradingDayOfWeek, AfterOpen, \ + BeforeClose from zipline.utils.events import NthTradingDayOfWeek -from test_events import StatelessRulesTests, StatefulRulesTests +from test_events import StatelessRulesTests, StatefulRulesTests, \ + minutes_for_days class TestStatelessRulesNYSE(StatelessRulesTests, TestCase): @@ -140,6 +142,23 @@ class TestStatelessRulesNYSE(StatelessRulesTests, TestCase): self.assertEqual(n_triggered, 1) + def test_offset_too_far(self): + minute_groups = minutes_for_days(self.cal, ordered_days=True) + + # Neither rule should ever fire, since they are configured to fire + # 11+ hours after the open or before the close. a NYSE session is + # never longer than 6.5 hours. + after_open_rule = AfterOpen(hours=11, minutes=11) + after_open_rule.cal = self.cal + + before_close_rule = BeforeClose(hours=11, minutes=5) + before_close_rule.cal = self.cal + + for session_minutes in minute_groups: + for minute in session_minutes: + self.assertFalse(after_open_rule.should_trigger(minute)) + self.assertFalse(before_close_rule.should_trigger(minute)) + class TestStatefulRulesNYSE(StatefulRulesTests, TestCase): CALENDAR_STRING = "NYSE" diff --git a/zipline/utils/events.py b/zipline/utils/events.py index cdd5bcc3..b5495673 100644 --- a/zipline/utils/events.py +++ b/zipline/utils/events.py @@ -90,12 +90,12 @@ def _out_of_range_error(a, b=None, var='offset'): def _td_check(td): seconds = td.total_seconds() - # 23400 seconds is 6 hours and 30 minutes. - if 60 <= seconds <= 23400: + # 43200 seconds = 12 hours + if 60 <= seconds <= 43200: return td else: - raise ValueError('offset must be in between 1 minute and 6 hours and' - ' 30 minutes inclusive') + raise ValueError('offset must be in between 1 minute and 12 hours, ' + 'inclusive.') def _build_offset(offset, kwargs, default):