Merge pull request #1594 from quantopian/fix-after-half-day-nan

BUG: Fix minute bar last traded after half day.
This commit is contained in:
Eddie Hebert
2016-11-15 15:33:42 -05:00
committed by GitHub
2 changed files with 75 additions and 1 deletions
+65
View File
@@ -46,6 +46,7 @@ from zipline.data.minute_bars import (
)
from zipline.testing.fixtures import (
WithAssetFinder,
WithInstanceTmpDir,
WithTradingCalendars,
ZiplineTestCase,
@@ -59,9 +60,12 @@ TEST_CALENDAR_STOP = Timestamp('2015-12-31', tz='UTC')
class BcolzMinuteBarTestCase(WithTradingCalendars,
WithAssetFinder,
WithInstanceTmpDir,
ZiplineTestCase):
ASSET_FINDER_EQUITY_SIDS = 1, 2
@classmethod
def init_class_fixtures(cls):
super(BcolzMinuteBarTestCase, cls).init_class_fixtures()
@@ -1040,3 +1044,64 @@ class BcolzMinuteBarTestCase(WithTradingCalendars,
_, last_close = cal.open_and_close_for_session(
self.test_calendar_start)
self.assertEqual(self.reader.last_available_dt, last_close)
def test_early_market_close(self):
# Date to test is 2015-11-30 9:31
# Early close is 2015-11-27 18:00
friday_after_tday = Timestamp('2015-11-27', tz='UTC')
friday_after_tday_close = self.market_closes[friday_after_tday]
before_early_close = friday_after_tday_close - timedelta(minutes=8)
after_early_close = friday_after_tday_close + timedelta(minutes=8)
monday_after_tday = Timestamp('2015-11-30', tz='UTC')
minute = self.market_opens[monday_after_tday]
# Test condition where there is data written after the market
# close (ideally, this should not occur in datasets, but guards
# against consumers of the minute bar writer, which do not filter
# out after close minutes.
minutes = [
before_early_close,
after_early_close,
minute,
]
sid = 1
data = DataFrame(
data={
'open': [10.0, 11.0, nan],
'high': [20.0, 21.0, nan],
'low': [30.0, 31.0, nan],
'close': [40.0, 41.0, nan],
'volume': [50, 51, 0]
},
index=[minutes])
self.writer.write_sid(sid, data)
open_price = self.reader.get_value(sid, minute, 'open')
assert_almost_equal(nan, open_price)
high_price = self.reader.get_value(sid, minute, 'high')
assert_almost_equal(nan, high_price)
low_price = self.reader.get_value(sid, minute, 'low')
assert_almost_equal(nan, low_price)
close_price = self.reader.get_value(sid, minute, 'close')
assert_almost_equal(nan, close_price)
volume = self.reader.get_value(sid, minute, 'volume')
self.assertEquals(0, volume)
asset = self.asset_finder.retrieve_asset(sid)
last_traded_dt = self.reader.get_last_traded_dt(asset, minute)
self.assertEquals(last_traded_dt, before_early_close,
"The last traded dt should be before the early "
"close, even when data is written between the early "
"close and the next open.")
+10 -1
View File
@@ -124,7 +124,7 @@ def find_last_traded_position_internal(
-------
int: The position of the last traded minute, starting from `minute_val`
"""
cdef Py_ssize_t minute_pos, current_minute
cdef Py_ssize_t minute_pos, current_minute, q
minute_pos = int_min(
find_position_of_minute(market_opens, market_closes, end_minute,
@@ -137,6 +137,15 @@ def find_last_traded_position_internal(
market_opens, minute_pos, minutes_per_day
)
q = cython.cdiv(minute_pos, minutes_per_day)
if current_minute > market_closes[q]:
minute_pos = find_position_of_minute(market_opens,
market_closes,
market_closes[q],
minutes_per_day,
False)
continue
if current_minute < start_minute:
return -1