mirror of
https://github.com/wassname/catalyst.git
synced 2026-09-09 11:19:23 +08:00
Merge pull request #1502 from quantopian/remove-future-chain
MAINT: Remove `future_chain` API method.
This commit is contained in:
@@ -58,7 +58,6 @@ from zipline.errors import (
|
||||
TradingControlViolation,
|
||||
AccountControlViolation,
|
||||
SymbolNotFound,
|
||||
RootSymbolNotFound,
|
||||
UnsupportedDatetimeFormat,
|
||||
CannotOrderDelistedAsset,
|
||||
SetCancelPolicyPostInit,
|
||||
@@ -726,108 +725,6 @@ def log_nyse_close(context, data):
|
||||
with self.assertRaises(TypeError):
|
||||
algo.future_symbol({'foo': 'bar'})
|
||||
|
||||
def test_future_chain_offset(self):
|
||||
# November 2006 December 2006
|
||||
# Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
|
||||
# 1 2 3 4 1 2
|
||||
# 5 6 7 8 9 10 11 3 4 5 6 7 8 9
|
||||
# 12 13 14 15 16 17 18 10 11 12 13 14 15 16
|
||||
# 19 20 21 22 23 24 25 17 18 19 20 21 22 23
|
||||
# 26 27 28 29 30 24 25 26 27 28 29 30
|
||||
# 31
|
||||
|
||||
algo = TradingAlgorithm(env=self.env)
|
||||
algo.datetime = pd.Timestamp('2006-12-01', tz='UTC')
|
||||
|
||||
self.assertEqual(
|
||||
algo.future_chain('CL', offset=1).as_of_date,
|
||||
pd.Timestamp("2006-12-04", tz='UTC')
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
algo.future_chain("CL", offset=5).as_of_date,
|
||||
pd.Timestamp("2006-12-08", tz='UTC')
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
algo.future_chain("CL", offset=-10).as_of_date,
|
||||
pd.Timestamp("2006-11-16", tz='UTC')
|
||||
)
|
||||
|
||||
# September 2016
|
||||
# Su Mo Tu We Th Fr Sa
|
||||
# 1 2 3
|
||||
# 4 5 6 7 8 9 10
|
||||
# 11 12 13 14 15 16 17
|
||||
# 18 19 20 21 22 23 24
|
||||
# 25 26 27 28 29 30
|
||||
self.assertEqual(
|
||||
algo.future_chain(
|
||||
"CL",
|
||||
as_of_date=pd.Timestamp("2016-08-31", tz='UTC'),
|
||||
offset=10
|
||||
).as_of_date,
|
||||
pd.Timestamp("2016-09-15", tz='UTC')
|
||||
)
|
||||
|
||||
def test_future_chain(self):
|
||||
algo = TradingAlgorithm(env=self.env)
|
||||
algo.datetime = pd.Timestamp('2006-12-01', tz='UTC')
|
||||
|
||||
# Check that the fields of the FutureChain object are set correctly
|
||||
cl = algo.future_chain('CL')
|
||||
self.assertEqual(cl.root_symbol, 'CL')
|
||||
self.assertEqual(cl.as_of_date, algo.datetime)
|
||||
|
||||
# Check the fields are set correctly if an as_of_date is supplied
|
||||
as_of_date = pd.Timestamp('1952-08-11', tz='UTC')
|
||||
|
||||
cl = algo.future_chain('CL', as_of_date=as_of_date)
|
||||
self.assertEqual(cl.root_symbol, 'CL')
|
||||
self.assertEqual(cl.as_of_date, as_of_date)
|
||||
|
||||
cl = algo.future_chain('CL', as_of_date='1952-08-11')
|
||||
self.assertEqual(cl.root_symbol, 'CL')
|
||||
self.assertEqual(cl.as_of_date, as_of_date)
|
||||
|
||||
# Check that weird capitalization is corrected
|
||||
cl = algo.future_chain('cL')
|
||||
self.assertEqual(cl.root_symbol, 'CL')
|
||||
|
||||
cl = algo.future_chain('cl')
|
||||
self.assertEqual(cl.root_symbol, 'CL')
|
||||
|
||||
# Check that invalid root symbols raise RootSymbolNotFound
|
||||
with self.assertRaises(RootSymbolNotFound):
|
||||
algo.future_chain('CLZ')
|
||||
|
||||
with self.assertRaises(RootSymbolNotFound):
|
||||
algo.future_chain('')
|
||||
|
||||
# Check that invalid dates raise UnsupportedDatetimeFormat
|
||||
with self.assertRaises(UnsupportedDatetimeFormat):
|
||||
algo.future_chain('CL', 'my_finger_slipped')
|
||||
|
||||
with self.assertRaises(UnsupportedDatetimeFormat):
|
||||
algo.future_chain('CL', '2015-09-')
|
||||
|
||||
# Supplying a non-string argument to future_chain()
|
||||
# should result in a TypeError.
|
||||
with self.assertRaises(TypeError):
|
||||
algo.future_chain(1)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
algo.future_chain((1,))
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
algo.future_chain({1})
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
algo.future_chain([1])
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
algo.future_chain({'foo': 'bar'})
|
||||
|
||||
def test_set_symbol_lookup_date(self):
|
||||
"""
|
||||
Test the set_symbol_lookup_date API method.
|
||||
|
||||
@@ -48,11 +48,6 @@ from zipline.assets.synthetic import (
|
||||
from six import itervalues, integer_types
|
||||
from toolz import valmap
|
||||
|
||||
from zipline.assets.futures import (
|
||||
cme_code_to_month,
|
||||
FutureChain,
|
||||
month_to_cme_code
|
||||
)
|
||||
from zipline.assets.asset_writer import (
|
||||
check_version_info,
|
||||
write_version_info,
|
||||
@@ -67,7 +62,6 @@ from zipline.errors import (
|
||||
EquitiesNotFound,
|
||||
FutureContractsNotFound,
|
||||
MultipleSymbolsFound,
|
||||
RootSymbolNotFound,
|
||||
AssetDBVersionError,
|
||||
SidsNotFound,
|
||||
SymbolNotFound,
|
||||
@@ -883,94 +877,6 @@ class AssetFinderTestCase(WithTradingCalendars, ZiplineTestCase):
|
||||
self.assertTrue(issubclass(warning.category,
|
||||
DeprecationWarning))
|
||||
|
||||
def test_lookup_future_chain(self):
|
||||
metadata = pd.DataFrame.from_records([
|
||||
# Notice day is today, so should be valid.
|
||||
{
|
||||
'symbol': 'ADN15',
|
||||
'root_symbol': 'AD',
|
||||
'notice_date': pd.Timestamp('2015-06-14', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2015-08-14', tz='UTC'),
|
||||
'start_date': pd.Timestamp('2015-01-01', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
{
|
||||
'symbol': 'ADV15',
|
||||
'root_symbol': 'AD',
|
||||
'notice_date': pd.Timestamp('2015-05-14', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2015-09-14', tz='UTC'),
|
||||
'start_date': pd.Timestamp('2015-01-01', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
# Starts trading today, so should be valid.
|
||||
{
|
||||
'symbol': 'ADF16',
|
||||
'root_symbol': 'AD',
|
||||
'notice_date': pd.Timestamp('2015-11-16', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2015-12-16', tz='UTC'),
|
||||
'start_date': pd.Timestamp('2015-05-14', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
# Starts trading in August, so not valid.
|
||||
{
|
||||
'symbol': 'ADX16',
|
||||
'root_symbol': 'AD',
|
||||
'notice_date': pd.Timestamp('2015-11-16', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2015-12-16', tz='UTC'),
|
||||
'start_date': pd.Timestamp('2015-08-01', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
# Notice date comes after expiration
|
||||
{
|
||||
'symbol': 'ADZ16',
|
||||
'root_symbol': 'AD',
|
||||
'notice_date': pd.Timestamp('2016-11-25', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2016-11-16', tz='UTC'),
|
||||
'start_date': pd.Timestamp('2015-08-01', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
# This contract has no start date and also this contract should be
|
||||
# last in all chains
|
||||
{
|
||||
'symbol': 'ADZ20',
|
||||
'root_symbol': 'AD',
|
||||
'notice_date': pd.Timestamp('2020-11-25', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2020-11-16', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
])
|
||||
self.write_assets(futures=metadata)
|
||||
finder = self.asset_finder
|
||||
dt = pd.Timestamp('2015-05-14', tz='UTC')
|
||||
dt_2 = pd.Timestamp('2015-10-14', tz='UTC')
|
||||
dt_3 = pd.Timestamp('2016-11-17', tz='UTC')
|
||||
|
||||
# Check that we get the expected number of contracts, in the
|
||||
# right order
|
||||
ad_contracts = finder.lookup_future_chain('AD', dt)
|
||||
self.assertEqual(len(ad_contracts), 6)
|
||||
self.assertEqual(ad_contracts[0].sid, 1)
|
||||
self.assertEqual(ad_contracts[1].sid, 0)
|
||||
self.assertEqual(ad_contracts[5].sid, 5)
|
||||
|
||||
# Check that, when some contracts have expired, the chain has advanced
|
||||
# properly to the next contracts
|
||||
ad_contracts = finder.lookup_future_chain('AD', dt_2)
|
||||
self.assertEqual(len(ad_contracts), 4)
|
||||
self.assertEqual(ad_contracts[0].sid, 2)
|
||||
self.assertEqual(ad_contracts[3].sid, 5)
|
||||
|
||||
# Check that when the expiration_date has passed but the
|
||||
# notice_date hasn't, contract is still considered invalid.
|
||||
ad_contracts = finder.lookup_future_chain('AD', dt_3)
|
||||
self.assertEqual(len(ad_contracts), 1)
|
||||
self.assertEqual(ad_contracts[0].sid, 5)
|
||||
|
||||
# Check that pd.NaT for as_of_date gives the whole chain
|
||||
ad_contracts = finder.lookup_future_chain('AD', pd.NaT)
|
||||
self.assertEqual(len(ad_contracts), 6)
|
||||
self.assertEqual(ad_contracts[5].sid, 5)
|
||||
|
||||
def test_map_identifier_index_to_sids(self):
|
||||
# Build an empty finder and some Assets
|
||||
dt = pd.Timestamp('2014-01-01', tz='UTC')
|
||||
@@ -1218,179 +1124,6 @@ class AssetFinderTestCase(WithTradingCalendars, ZiplineTestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestFutureChain(WithAssetFinder, ZiplineTestCase):
|
||||
@classmethod
|
||||
def make_futures_info(cls):
|
||||
return pd.DataFrame.from_records([
|
||||
{
|
||||
'symbol': 'CLG06',
|
||||
'root_symbol': 'CL',
|
||||
'start_date': pd.Timestamp('2005-12-01', tz='UTC'),
|
||||
'notice_date': pd.Timestamp('2005-12-20', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2006-01-20', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
{
|
||||
'root_symbol': 'CL',
|
||||
'symbol': 'CLK06',
|
||||
'start_date': pd.Timestamp('2005-12-01', tz='UTC'),
|
||||
'notice_date': pd.Timestamp('2006-03-20', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2006-04-20', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
{
|
||||
'symbol': 'CLQ06',
|
||||
'root_symbol': 'CL',
|
||||
'start_date': pd.Timestamp('2005-12-01', tz='UTC'),
|
||||
'notice_date': pd.Timestamp('2006-06-20', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2006-07-20', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
},
|
||||
{
|
||||
'symbol': 'CLX06',
|
||||
'root_symbol': 'CL',
|
||||
'start_date': pd.Timestamp('2006-02-01', tz='UTC'),
|
||||
'notice_date': pd.Timestamp('2006-09-20', tz='UTC'),
|
||||
'expiration_date': pd.Timestamp('2006-10-20', tz='UTC'),
|
||||
'exchange': "TEST",
|
||||
}
|
||||
])
|
||||
|
||||
def _get_future_chain(self, date_str, symbol):
|
||||
dt = pd.Timestamp(date_str, tz='UTC')
|
||||
|
||||
return FutureChain(
|
||||
symbol,
|
||||
dt,
|
||||
self.asset_finder.lookup_future_chain(symbol, dt)
|
||||
)
|
||||
|
||||
def test_len(self):
|
||||
""" Test the __len__ method of FutureChain.
|
||||
"""
|
||||
# Sids 0, 1, & 2 have started, 3 has not yet started, but all are in
|
||||
# the chain
|
||||
cl = self._get_future_chain('2005-12-01', 'CL')
|
||||
self.assertEqual(len(cl), 4)
|
||||
|
||||
# Sid 0 is still valid on its notice date.
|
||||
cl = self._get_future_chain('2005-12-20', 'CL')
|
||||
self.assertEqual(len(cl), 4)
|
||||
|
||||
# Sid 0 is now invalid, leaving Sids 1 & 2 valid (and 3 not started).
|
||||
cl = self._get_future_chain('2005-12-21', 'CL')
|
||||
self.assertEqual(len(cl), 3)
|
||||
|
||||
# Sid 3 has started, so 1, 2, & 3 are now valid.
|
||||
cl = self._get_future_chain('2006-02-01', 'CL')
|
||||
self.assertEqual(len(cl), 3)
|
||||
|
||||
# All contracts are no longer valid.
|
||||
cl = self._get_future_chain('2006-09-21', 'CL')
|
||||
self.assertEqual(len(cl), 0)
|
||||
|
||||
def test_getitem(self):
|
||||
""" Test the __getitem__ method of FutureChain.
|
||||
"""
|
||||
cl = self._get_future_chain('2005-12-01', 'CL')
|
||||
self.assertEqual(cl[0], 0)
|
||||
self.assertEqual(cl[1], 1)
|
||||
self.assertEqual(cl[2], 2)
|
||||
|
||||
cl = self._get_future_chain('2005-12-20', 'CL')
|
||||
self.assertEqual(cl[0], 0)
|
||||
|
||||
cl = self._get_future_chain('2005-12-21', 'CL')
|
||||
self.assertEqual(cl[0], 1)
|
||||
|
||||
cl = self._get_future_chain('2006-02-01', 'CL')
|
||||
self.assertEqual(cl[-1], 3)
|
||||
|
||||
def test_iter(self):
|
||||
""" Test the __iter__ method of FutureChain.
|
||||
"""
|
||||
cl = self._get_future_chain('2005-12-01', 'CL')
|
||||
for i, contract in enumerate(cl):
|
||||
self.assertEqual(contract, i)
|
||||
|
||||
# First contract is now invalid, so sids will be offset by one
|
||||
cl = self._get_future_chain('2005-12-21', 'CL')
|
||||
for i, contract in enumerate(cl):
|
||||
self.assertEqual(contract, i + 1)
|
||||
|
||||
def test_root_symbols(self):
|
||||
""" Test that different variations on root symbols are handled
|
||||
as expected.
|
||||
"""
|
||||
# Make sure this successfully gets the chain for CL.
|
||||
cl = self._get_future_chain('2005-12-01', 'CL')
|
||||
self.assertEqual(cl.root_symbol, 'CL')
|
||||
|
||||
# These root symbols don't exist, so RootSymbolNotFound should
|
||||
# be raised immediately.
|
||||
with self.assertRaises(RootSymbolNotFound):
|
||||
self._get_future_chain('2005-12-01', 'CLZ')
|
||||
|
||||
with self.assertRaises(RootSymbolNotFound):
|
||||
self._get_future_chain('2005-12-01', '')
|
||||
|
||||
def test_repr(self):
|
||||
""" Test the __repr__ method of FutureChain.
|
||||
"""
|
||||
cl = self._get_future_chain('2005-12-01', 'CL')
|
||||
|
||||
self.assertEqual(
|
||||
repr(cl),
|
||||
"FutureChain('CL', '2005-12-01')"
|
||||
)
|
||||
|
||||
def test_contracts_returns_a_copy(self):
|
||||
cl = self._get_future_chain('2005-12-01', 'CL')
|
||||
self.assertEqual(len(cl), 4)
|
||||
|
||||
contracts = cl.contracts
|
||||
contracts.pop(0)
|
||||
|
||||
self.assertEqual(len(contracts), 3)
|
||||
self.assertEqual(len(cl), 4)
|
||||
|
||||
def test_cme_code_to_month(self):
|
||||
codes = {
|
||||
'F': 1, # January
|
||||
'G': 2, # February
|
||||
'H': 3, # March
|
||||
'J': 4, # April
|
||||
'K': 5, # May
|
||||
'M': 6, # June
|
||||
'N': 7, # July
|
||||
'Q': 8, # August
|
||||
'U': 9, # September
|
||||
'V': 10, # October
|
||||
'X': 11, # November
|
||||
'Z': 12 # December
|
||||
}
|
||||
for key in codes:
|
||||
self.assertEqual(codes[key], cme_code_to_month(key))
|
||||
|
||||
def test_month_to_cme_code(self):
|
||||
codes = {
|
||||
1: 'F', # January
|
||||
2: 'G', # February
|
||||
3: 'H', # March
|
||||
4: 'J', # April
|
||||
5: 'K', # May
|
||||
6: 'M', # June
|
||||
7: 'N', # July
|
||||
8: 'Q', # August
|
||||
9: 'U', # September
|
||||
10: 'V', # October
|
||||
11: 'X', # November
|
||||
12: 'Z', # December
|
||||
}
|
||||
for key in codes:
|
||||
self.assertEqual(codes[key], month_to_cme_code(key))
|
||||
|
||||
|
||||
class TestAssetDBVersioning(ZiplineTestCase):
|
||||
|
||||
def init_instance_fixtures(self):
|
||||
|
||||
Reference in New Issue
Block a user