mirror of
https://github.com/wassname/catalyst.git
synced 2026-09-12 12:12:04 +08:00
BUG: OrderedContracts chain could sometimes terminate on first contract
This commit is contained in:
@@ -139,6 +139,7 @@ def build_lookup_generic_cases(asset_finder_type):
|
|||||||
'root_symbol': 'FO',
|
'root_symbol': 'FO',
|
||||||
'start_date': unique_start.value,
|
'start_date': unique_start.value,
|
||||||
'end_date': unique_end.value,
|
'end_date': unique_end.value,
|
||||||
|
'auto_close_date': unique_end.value,
|
||||||
'exchange': 'FUT',
|
'exchange': 'FUT',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1329,9 +1329,9 @@ class OrderedContractsTestCase(WithAssetFinder,
|
|||||||
@classmethod
|
@classmethod
|
||||||
def make_root_symbols_info(self):
|
def make_root_symbols_info(self):
|
||||||
return pd.DataFrame({
|
return pd.DataFrame({
|
||||||
'root_symbol': ['FO', 'BA'],
|
'root_symbol': ['FO', 'BA', 'BZ'],
|
||||||
'root_symbol_id': [1, 2],
|
'root_symbol_id': [1, 2, 3],
|
||||||
'exchange': ['CME', 'CME']})
|
'exchange': ['CME', 'CME', 'CME']})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make_futures_info(self):
|
def make_futures_info(self):
|
||||||
@@ -1372,8 +1372,32 @@ class OrderedContractsTestCase(WithAssetFinder,
|
|||||||
'multiplier': [1000.0] * 3,
|
'multiplier': [1000.0] * 3,
|
||||||
'exchange': ['CME'] * 3,
|
'exchange': ['CME'] * 3,
|
||||||
})
|
})
|
||||||
|
# BZ is set up to test the case where the first contract in a chain has
|
||||||
|
# an auto close date before its start date.
|
||||||
|
bz_frame = DataFrame({
|
||||||
|
'root_symbol': ['BZ'] * 3,
|
||||||
|
'asset_name': ['Baz'] * 3,
|
||||||
|
'symbol': ['BZF16', 'BZG16', 'BZH16'],
|
||||||
|
'sid': range(8, 11),
|
||||||
|
'start_date': pd.date_range('2015-01-02', periods=3, tz='UTC'),
|
||||||
|
'end_date': pd.date_range(
|
||||||
|
'2015-01-15', periods=3, freq='M', tz='UTC',
|
||||||
|
),
|
||||||
|
'notice_date': pd.date_range(
|
||||||
|
'2014-12-31', periods=3, freq='M', tz='UTC',
|
||||||
|
),
|
||||||
|
'expiration_date': pd.date_range(
|
||||||
|
'2015-01-15', periods=3, freq='M', tz='UTC',
|
||||||
|
),
|
||||||
|
'auto_close_date': pd.date_range(
|
||||||
|
'2014-12-29', periods=3, freq='M', tz='UTC',
|
||||||
|
),
|
||||||
|
'tick_size': [0.001] * 3,
|
||||||
|
'multiplier': [1000.0] * 3,
|
||||||
|
'exchange': ['CME'] * 3,
|
||||||
|
})
|
||||||
|
|
||||||
return pd.concat([fo_frame, ba_frame])
|
return pd.concat([fo_frame, ba_frame, bz_frame])
|
||||||
|
|
||||||
def test_contract_at_offset(self):
|
def test_contract_at_offset(self):
|
||||||
contract_sids = array([1, 2, 3, 4], dtype=int64)
|
contract_sids = array([1, 2, 3, 4], dtype=int64)
|
||||||
@@ -1471,6 +1495,16 @@ class OrderedContractsTestCase(WithAssetFinder,
|
|||||||
"Contract BAG16 (sid=6) should be ommitted from chain, since "
|
"Contract BAG16 (sid=6) should be ommitted from chain, since "
|
||||||
"it does not satisfy the roll predicate.")
|
"it does not satisfy the roll predicate.")
|
||||||
|
|
||||||
|
def test_auto_close_before_start(self):
|
||||||
|
contract_sids = array([8, 9, 10], dtype=int64)
|
||||||
|
contracts = self.asset_finder.retrieve_all(contract_sids)
|
||||||
|
oc = OrderedContracts('BZ', deque(contracts))
|
||||||
|
|
||||||
|
# The OrderedContracts chain should omit BZF16 and start with BZG16.
|
||||||
|
self.assertEqual(oc.start_date, contracts[1].start_date)
|
||||||
|
self.assertEqual(oc.end_date, contracts[-1].end_date)
|
||||||
|
self.assertEqual(oc.contract_before_auto_close(oc.start_date.value), 9)
|
||||||
|
|
||||||
|
|
||||||
class NoPrefetchContinuousFuturesTestCase(ContinuousFuturesTestCase):
|
class NoPrefetchContinuousFuturesTestCase(ContinuousFuturesTestCase):
|
||||||
DATA_PORTAL_MINUTE_HISTORY_PREFETCH = 0
|
DATA_PORTAL_MINUTE_HISTORY_PREFETCH = 0
|
||||||
|
|||||||
@@ -333,6 +333,12 @@ cdef class OrderedContracts(object):
|
|||||||
while contracts:
|
while contracts:
|
||||||
contract = contracts.popleft()
|
contract = contracts.popleft()
|
||||||
|
|
||||||
|
# It is possible that the first contract in our list has a start
|
||||||
|
# date on or after its auto close date. In that case the contract
|
||||||
|
# is not tradable, so do not include it in the chain.
|
||||||
|
if prev is None and contract.start_date >= contract.auto_close_date:
|
||||||
|
continue
|
||||||
|
|
||||||
# Prevent contract chains with gaps between auto close and start of
|
# Prevent contract chains with gaps between auto close and start of
|
||||||
# next contract.
|
# next contract.
|
||||||
# This is in lieu of more explicit support for
|
# This is in lieu of more explicit support for
|
||||||
@@ -345,7 +351,7 @@ cdef class OrderedContracts(object):
|
|||||||
|
|
||||||
self._start_date = min(contract.start_date.value, self._start_date)
|
self._start_date = min(contract.start_date.value, self._start_date)
|
||||||
self._end_date = max(contract.end_date.value, self._end_date)
|
self._end_date = max(contract.end_date.value, self._end_date)
|
||||||
|
|
||||||
curr = ContractNode(contract)
|
curr = ContractNode(contract)
|
||||||
self.sid_to_contract[contract.sid] = curr
|
self.sid_to_contract[contract.sid] = curr
|
||||||
if self._head_contract is None:
|
if self._head_contract is None:
|
||||||
@@ -355,7 +361,7 @@ cdef class OrderedContracts(object):
|
|||||||
curr.prev = prev
|
curr.prev = prev
|
||||||
prev.next = curr
|
prev.next = curr
|
||||||
prev = curr
|
prev = curr
|
||||||
|
|
||||||
cpdef long_t contract_before_auto_close(self, long_t dt_value):
|
cpdef long_t contract_before_auto_close(self, long_t dt_value):
|
||||||
"""
|
"""
|
||||||
Get the contract with next upcoming auto close date.
|
Get the contract with next upcoming auto close date.
|
||||||
@@ -393,7 +399,7 @@ cdef class OrderedContracts(object):
|
|||||||
if curr.contract.start_date.value <= dt_value:
|
if curr.contract.start_date.value <= dt_value:
|
||||||
contracts.append(curr.contract.sid)
|
contracts.append(curr.contract.sid)
|
||||||
curr = curr.next
|
curr = curr.next
|
||||||
|
|
||||||
return array(contracts, dtype='int64')
|
return array(contracts, dtype='int64')
|
||||||
|
|
||||||
property start_date:
|
property start_date:
|
||||||
|
|||||||
Reference in New Issue
Block a user