From 2b5a78572f54a3f55467eb24e61ade511d79953c Mon Sep 17 00:00:00 2001 From: Andrew Daniels Date: Thu, 6 Oct 2016 14:44:56 -0400 Subject: [PATCH 1/2] ENH: Adds last_available_{session, minute} args to DataPortal This allows optionally setting the last available dts in the DataPortal explicitly. If these args aren't provided, we fall back to inferring these from the underlying readers, which was the previous behavior. --- zipline/data/data_portal.py | 10 +++++++++- zipline/data/dispatch_bar_reader.py | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/zipline/data/data_portal.py b/zipline/data/data_portal.py index 8e9ca30460..956fe61a61 100644 --- a/zipline/data/data_portal.py +++ b/zipline/data/data_portal.py @@ -104,6 +104,10 @@ class DataPortal(object): adjustment_reader : SQLiteAdjustmentWriter, optional The adjustment reader. This is used to apply splits, dividends, and other adjustment data to the raw data from the readers. + last_available_session : pd.Timestamp, optional + The last session to make available in session-level data. + last_available_minute : pd.Timestamp, optional + The last minute to make available in minute-level data. """ def __init__(self, asset_finder, @@ -113,7 +117,9 @@ def __init__(self, equity_minute_reader=None, future_daily_reader=None, future_minute_reader=None, - adjustment_reader=None): + adjustment_reader=None, + last_available_session=None, + last_available_minute=None): self.trading_calendar = trading_calendar self.asset_finder = asset_finder @@ -169,12 +175,14 @@ def __init__(self, self.trading_calendar, self.asset_finder, aligned_minute_readers, + last_available_minute, ) _dispatch_session_reader = AssetDispatchSessionBarReader( self.trading_calendar, self.asset_finder, aligned_session_readers, + last_available_session, ) self._pricing_readers = { diff --git a/zipline/data/dispatch_bar_reader.py b/zipline/data/dispatch_bar_reader.py index a80e66b6c5..dab38439d8 100644 --- a/zipline/data/dispatch_bar_reader.py +++ b/zipline/data/dispatch_bar_reader.py @@ -35,11 +35,21 @@ class AssetDispatchBarReader(with_metaclass(ABCMeta)): - readers : dict A dict mapping Asset type to the corresponding [Minute|Session]BarReader + - last_available_dt : pd.Timestamp or None, optional + If not provided, infers it by using the min of the + last_available_dt values of the underlying readers. """ - def __init__(self, trading_calendar, asset_finder, readers): + def __init__( + self, + trading_calendar, + asset_finder, + readers, + last_available_dt=None, + ): self._trading_calendar = trading_calendar self._asset_finder = asset_finder self._readers = readers + self._last_available_dt = last_available_dt for t, r in iteritems(self._readers): assert trading_calendar == r.trading_calendar, \ @@ -72,7 +82,10 @@ def trading_calendar(self): @lazyval def last_available_dt(self): - return min(r.last_available_dt for r in self._readers.values()) + if self._last_available_dt is not None: + return self._last_available_dt + else: + return min(r.last_available_dt for r in self._readers.values()) @lazyval def first_trading_day(self): From 01ad7932011673cf869d2510fcfdd28ee9f14988 Mon Sep 17 00:00:00 2001 From: Andrew Daniels Date: Thu, 6 Oct 2016 16:16:57 -0400 Subject: [PATCH 2/2] TST: Adds data portal test case with explicit last available args --- tests/test_data_portal.py | 19 +++++++++++++++---- zipline/testing/fixtures.py | 5 +++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/test_data_portal.py b/tests/test_data_portal.py index b69c197957..345e0fc774 100644 --- a/tests/test_data_portal.py +++ b/tests/test_data_portal.py @@ -23,13 +23,14 @@ from zipline.testing.fixtures import ( ZiplineTestCase, WithTradingSessions, - WithDataPortal + WithDataPortal, + alias, ) -class TestDataPortal(WithDataPortal, - WithTradingSessions, - ZiplineTestCase): +class DataPortalTestBase(WithDataPortal, + WithTradingSessions, + ZiplineTestCase): ASSET_FINDER_EQUITY_SIDS = (1,) START_DATE = pd.Timestamp('2016-08-01') @@ -374,3 +375,13 @@ def test_get_last_traded_dt_minute(self): self.assertEqual(minutes[4], result, "Asset 10000 had a trade on fourth minute, so should " "return that as the last trade on the fifth.") + + +class TestDataPortal(DataPortalTestBase): + DATA_PORTAL_LAST_AVAILABLE_SESSION = None + DATA_PORTAL_LAST_AVAILABLE_MINUTE = None + + +class TestDataPortalExplicitLastAvailable(DataPortalTestBase): + DATA_PORTAL_LAST_AVAILABLE_SESSION = alias('START_DATE') + DATA_PORTAL_LAST_AVAILABLE_MINUTE = alias('END_DATE') diff --git a/zipline/testing/fixtures.py b/zipline/testing/fixtures.py index 3570d255ed..98709ab854 100644 --- a/zipline/testing/fixtures.py +++ b/zipline/testing/fixtures.py @@ -1265,6 +1265,9 @@ class WithDataPortal(WithAdjustmentReader, DATA_PORTAL_FIRST_TRADING_DAY = None + DATA_PORTAL_LAST_AVAILABLE_SESSION = None + DATA_PORTAL_LAST_AVAILABLE_MINUTE = None + def make_data_portal(self): if self.DATA_PORTAL_FIRST_TRADING_DAY is None: if self.DATA_PORTAL_USE_MINUTE_DATA: @@ -1300,6 +1303,8 @@ def make_data_portal(self): if self.DATA_PORTAL_USE_MINUTE_DATA else None ), + last_available_session=self.DATA_PORTAL_LAST_AVAILABLE_SESSION, + last_available_minute=self.DATA_PORTAL_LAST_AVAILABLE_MINUTE, ) def init_instance_fixtures(self):