Merge pull request #1583 from quantopian/allow-sliding-window-to-reset

ENH: Allow arbitrary history queries.
This commit is contained in:
Eddie Hebert
2016-11-07 22:31:13 -05:00
committed by GitHub
2 changed files with 73 additions and 6 deletions
+58
View File
@@ -1761,6 +1761,64 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
np.testing.assert_almost_equal(window_1[self.ASSET2].values,
window_2[self.ASSET2].values)
def test_history_window_out_of_order_dates(self):
"""
Use a history window with non-monotonically increasing dates.
A scenario which does not occur during simulations, but useful
for using a history loader in a notebook.
"""
window_1 = self.data_portal.get_history_window(
[self.ASSET1],
pd.Timestamp('2014-02-07', tz='UTC'),
4,
"1d",
"close"
)
window_2 = self.data_portal.get_history_window(
[self.ASSET1],
pd.Timestamp('2014-02-05', tz='UTC'),
4,
"1d",
"close"
)
window_3 = self.data_portal.get_history_window(
[self.ASSET1],
pd.Timestamp('2014-02-07', tz='UTC'),
4,
"1d",
"close"
)
window_4 = self.data_portal.get_history_window(
[self.ASSET1],
pd.Timestamp('2014-01-22', tz='UTC'),
4,
"1d",
"close"
)
# Calling 02-07 after resetting the window should not affect the
# results.
np.testing.assert_almost_equal(window_1.values, window_3.values)
offsets = np.arange(4)
def assert_window_prices(window, starting_price):
np.testing.assert_almost_equal(window.loc[:, self.ASSET1],
starting_price + offsets)
# Window 1 starts on the 23rd day of data for ASSET 1.
assert_window_prices(window_1, 23)
# Window 2 starts on the 21st day of data for ASSET 1.
assert_window_prices(window_2, 21)
# Window 3 starts on the 23rd day of data for ASSET 1.
assert_window_prices(window_3, 23)
# Window 4 starts on the 11th day of data for ASSET 1.
assert_window_prices(window_4, 11)
class NoPrefetchDailyEquityHistoryTestCase(DailyEquityHistoryTestCase):
DATA_PORTAL_MINUTE_HISTORY_PREFETCH = 0
+15 -6
View File
@@ -379,12 +379,26 @@ class HistoryLoader(with_metaclass(ABCMeta)):
assets = self._asset_finder.retrieve_all(assets)
try:
end_ix = self._calendar.get_loc(end)
except KeyError:
raise KeyError("{0} not in calendar [{1}...{2}]".format(
end, self._calendar[0], self._calendar[-1]))
for asset in assets:
try:
asset_windows[asset] = self._window_blocks[field].get(
window = self._window_blocks[field].get(
(asset, size, is_perspective_after), end)
except KeyError:
needed_assets.append(asset)
else:
if end_ix < window.most_recent_ix:
# Window needs reset. Requested end index occurs before the
# end index from the previous history call for this window.
# Grab new window instead of rewinding adjustments.
needed_assets.append(asset)
else:
asset_windows[asset] = window
if needed_assets:
start = dts[0]
@@ -395,11 +409,6 @@ class HistoryLoader(with_metaclass(ABCMeta)):
except KeyError:
raise KeyError("{0} not in calendar [{1}...{2}]".format(
start, self._calendar[0], self._calendar[-1]))
try:
end_ix = self._calendar.get_loc(end)
except KeyError:
raise KeyError("{0} not in calendar [{1}...{2}]".format(
end, self._calendar[0], self._calendar[-1]))
cal = self._calendar
prefetch_end_ix = min(end_ix + self._prefetch_length, len(cal) - 1)
prefetch_end = cal[prefetch_end_ix]