BUG: Fixes issues with AssetFinder future lookups

Contracts must have been trading at the as_of_date to be considered valid, and a contract's position in the chain is now zero-indexed.
This commit is contained in:
Andrew Daniels
2015-06-29 09:51:50 -04:00
parent cc77a52322
commit 759f346c93
2 changed files with 35 additions and 17 deletions
+30 -12
View File
@@ -581,19 +581,22 @@ class AssetFinderTestCase(TestCase):
'symbol': 'ADN15',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-06-15', tz='UTC')
'expiration_date': pd.Timestamp('2015-06-15', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
1: {
'symbol': 'ADV15',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-09-14', tz='UTC')
'expiration_date': pd.Timestamp('2015-09-14', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
0: {
'symbol': 'ADF16',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-12-14', tz='UTC')
'expiration_date': pd.Timestamp('2015-12-14', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
}
@@ -602,13 +605,12 @@ class AssetFinderTestCase(TestCase):
dt = pd.Timestamp('2015-06-19', tz='UTC')
# Check that the primary and secondary contracts are as expected
primary = finder.lookup_future_in_chain('AD', dt, 1)
secondary = finder.lookup_future_in_chain('AD', dt, 2)
primary = finder.lookup_future_in_chain('AD', dt, 0)
secondary = finder.lookup_future_in_chain('AD', dt, 1)
self.assertEqual(primary.sid, 1)
self.assertEqual(secondary.sid, 0)
# Check that we get None for an invalid contract num
self.assertIsNone(finder.lookup_future_in_chain('AD', dt, 0))
self.assertIsNone(finder.lookup_future_in_chain('AD', dt, -10))
self.assertIsNone(finder.lookup_future_in_chain('AD', dt, 10))
self.assertIsNone(finder.lookup_future_in_chain('CL', dt, 1))
@@ -619,19 +621,32 @@ class AssetFinderTestCase(TestCase):
'symbol': 'ADN15',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-06-15', tz='UTC')
'expiration_date': pd.Timestamp('2015-06-15', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
1: {
'symbol': 'ADV15',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-09-14', tz='UTC')
'expiration_date': pd.Timestamp('2015-09-14', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
# Starts trading today, so should be valid.
0: {
'symbol': 'ADF16',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-12-14', tz='UTC')
'expiration_date': pd.Timestamp('2015-12-14', tz='UTC'),
'start_date': pd.Timestamp('2015-06-19', tz='UTC')
},
# Copy of the above future, but starts trading in August,
# so it isn't valid.
3: {
'symbol': 'ADF16',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-12-14', tz='UTC'),
'start_date': pd.Timestamp('2015-08-01', tz='UTC')
},
}
@@ -652,19 +667,22 @@ class AssetFinderTestCase(TestCase):
'symbol': 'ADN15',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-06-15', tz='UTC')
'expiration_date': pd.Timestamp('2015-06-15', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
1: {
'symbol': 'ADV15',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-09-14', tz='UTC')
'expiration_date': pd.Timestamp('2015-09-14', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
0: {
'symbol': 'ADF16',
'root_symbol': 'AD',
'asset_type': 'future',
'expiration_date': pd.Timestamp('2015-12-14', tz='UTC')
'expiration_date': pd.Timestamp('2015-12-14', tz='UTC'),
'start_date': pd.Timestamp('2015-01-01', tz='UTC')
},
}
+5 -5
View File
@@ -247,7 +247,8 @@ class AssetFinder(object):
"""
try:
return [c for c in self.future_chains_cache[root_symbol]
if c.expiration_date > as_of_date]
if c.expiration_date and (c.expiration_date > as_of_date)
and c.start_date and (c.start_date <= as_of_date)]
except KeyError:
return None
@@ -269,7 +270,7 @@ class AssetFinder(object):
as_of_date = normalize_date(as_of_date)
return self._valid_contracts(root_symbol, as_of_date)
def lookup_future_in_chain(self, root_symbol, as_of_date, contract_num=1):
def lookup_future_in_chain(self, root_symbol, as_of_date, contract_num=0):
""" Find a specific contract in the futures chain for a given
root symbol.
@@ -293,11 +294,10 @@ class AssetFinder(object):
as_of_date = normalize_date(as_of_date)
valid_contracts = self._valid_contracts(root_symbol, as_of_date)
contract_index = contract_num - 1
if valid_contracts and contract_index >= 0:
if valid_contracts and contract_num >= 0:
try:
return valid_contracts[contract_index]
return valid_contracts[contract_num]
except IndexError:
pass