diff --git a/tests/test_continuous_futures.py b/tests/test_continuous_futures.py index 28ddaa38..3559f43e 100644 --- a/tests/test_continuous_futures.py +++ b/tests/test_continuous_futures.py @@ -467,6 +467,16 @@ class ContinuousFuturesTestCase(WithCreateBarData, 'Auto close at beginning of session so FOG16 is now ' 'the current contract.') + # Test that the current contract outside of the continuous future's + # start and end dates is None. + contract = self.data_portal.get_spot_value( + cf_primary, + 'contract', + self.START_DATE - self.trading_calendar.day, + 'daily', + ) + self.assertIsNone(contract) + def test_get_value_close_daily(self): cf_primary = self.asset_finder.create_continuous_future( 'FO', 0, 'calendar', None) diff --git a/zipline/data/continuous_future_reader.py b/zipline/data/continuous_future_reader.py index 72f6518d..8c0d7a2e 100644 --- a/zipline/data/continuous_future_reader.py +++ b/zipline/data/continuous_future_reader.py @@ -1,4 +1,5 @@ import numpy as np +import pandas as pd from zipline.data.session_bars import SessionBarReader @@ -162,6 +163,8 @@ class ContinuousFutureSessionBarReader(SessionBarReader): sid = (rf.get_contract_center(asset.root_symbol, dt, asset.offset)) + if sid is None: + return pd.NaT contract = rf.asset_finder.retrieve_asset(sid) return self._bar_reader.get_last_traded_dt(contract, dt) @@ -346,6 +349,8 @@ class ContinuousFutureMinuteBarReader(SessionBarReader): sid = (rf.get_contract_center(asset.root_symbol, dt, asset.offset)) + if sid is None: + return pd.NaT contract = rf.asset_finder.retrieve_asset(sid) return self._bar_reader.get_last_traded_dt(contract, dt) diff --git a/zipline/data/data_portal.py b/zipline/data/data_portal.py index 762dd636..2d29d7d1 100644 --- a/zipline/data/data_portal.py +++ b/zipline/data/data_portal.py @@ -500,10 +500,10 @@ class DataPortal(object): session_label > asset.end_date): if field == "volume": return 0 - elif field != "last_traded": - return np.NaN elif field == "contract": return None + elif field != "last_traded": + return np.NaN if data_frequency == "daily": if field == "contract": @@ -1368,7 +1368,9 @@ class DataPortal(object): def _get_current_contract(self, continuous_future, dt): rf = self._roll_finders[continuous_future.roll_style] - return self.asset_finder.retrieve_asset( - rf.get_contract_center(continuous_future.root_symbol, - dt, - continuous_future.offset)) + contract_sid = rf.get_contract_center(continuous_future.root_symbol, + dt, + continuous_future.offset) + if contract_sid is None: + return None + return self.asset_finder.retrieve_asset(contract_sid)