BUG: Protect against contract offset at end of range. (#1564)

This boundary case was exposed with internal fixture data which used a
continuous future with a contract chain of size one.
This commit is contained in:
Eddie Hebert
2016-10-27 16:48:34 -04:00
committed by Andrew Daniels
parent e07d5a202a
commit 8876092d29
2 changed files with 30 additions and 4 deletions
+22
View File
@@ -835,6 +835,28 @@ def record_current_contract(algo, data):
class OrderedContractsTestCase(ZiplineTestCase):
def test_contract_at_offset(self):
contract_sids = array([1, 2, 3, 4], dtype=int64)
start_dates = pd.date_range('2015-01-01', periods=4, tz="UTC")
auto_close_dates = pd.date_range('2016-04-01', periods=4, tz="UTC")
oc = OrderedContracts('FO',
contract_sids,
start_dates.astype('int64'),
auto_close_dates.astype('int64'))
self.assertEquals(1,
oc.contract_at_offset(1, 0, start_dates[-1].value),
"Offset of 0 should return provided sid")
self.assertEquals(2,
oc.contract_at_offset(1, 1, start_dates[-1].value),
"Offset of 1 should return next sid in chain.")
self.assertEquals(None,
oc.contract_at_offset(4, 1, start_dates[-1].value),
"Offset at end of chain should not crash.")
def test_active_chain(self):
contract_sids = array([1, 2, 3, 4], dtype=int64)
start_dates = pd.date_range('2015-01-01', periods=4, tz="UTC")
+8 -4
View File
@@ -302,16 +302,20 @@ cdef class OrderedContracts(object):
Get the sid which is the given sid plus the offset distance.
An offset of 0 should be reflexive.
"""
cdef Py_ssize_t i
cdef Py_ssize_t i, j
cdef long_t[:] sids
sids = self.contract_sids
start_dates = self.start_dates
for i in range(self._size):
i = 0
j = i + offset
while j < self._size:
if sid == sids[i]:
if start_dates[i + offset] < start_cap:
return sids[i + offset]
if start_dates[j] < start_cap:
return sids[j]
else:
return None
i += 1
j += 1
cpdef long_t[:] active_chain(self, long_t starting_sid, long_t dt_value):
cdef Py_ssize_t left, right, i, j