diff --git a/tests/data/test_minute_bars.py b/tests/data/test_minute_bars.py index a1253b29..aec62cce 100644 --- a/tests/data/test_minute_bars.py +++ b/tests/data/test_minute_bars.py @@ -45,7 +45,7 @@ from zipline.data.minute_bars import ( from zipline.testing.fixtures import ( WithInstanceTmpDir, - WithTradingCalendar, + WithTradingCalendars, ZiplineTestCase, ) @@ -56,7 +56,8 @@ TEST_CALENDAR_START = Timestamp('2014-06-02', tz='UTC') TEST_CALENDAR_STOP = Timestamp('2015-12-31', tz='UTC') -class BcolzMinuteBarTestCase(WithTradingCalendar, WithInstanceTmpDir, +class BcolzMinuteBarTestCase(WithTradingCalendars, + WithInstanceTmpDir, ZiplineTestCase): @classmethod diff --git a/tests/pipeline/base.py b/tests/pipeline/base.py index 31050bec..a5c8454f 100644 --- a/tests/pipeline/base.py +++ b/tests/pipeline/base.py @@ -17,7 +17,10 @@ from zipline.testing import ( ExplodingObject, tmp_asset_finder, ) -from zipline.testing.fixtures import ZiplineTestCase, WithTradingCalendar +from zipline.testing.fixtures import ( + WithTradingCalendars, + ZiplineTestCase, +) from zipline.utils.functional import dzip_exact from zipline.utils.pandas_utils import explode @@ -50,7 +53,7 @@ def with_defaults(**default_funcs): with_default_shape = with_defaults(shape=lambda self: self.default_shape) -class BasePipelineTestCase(WithTradingCalendar, ZiplineTestCase): +class BasePipelineTestCase(WithTradingCalendars, ZiplineTestCase): @classmethod def init_class_fixtures(cls): diff --git a/tests/pipeline/test_events.py b/tests/pipeline/test_events.py index 467c8da3..3b4831ae 100644 --- a/tests/pipeline/test_events.py +++ b/tests/pipeline/test_events.py @@ -27,7 +27,7 @@ from zipline.pipeline.loaders.utils import ( from zipline.testing import check_arrays, ZiplineTestCase from zipline.testing.fixtures import ( WithAssetFinder, - WithNYSETradingDays, + WithTradingSessions, ) from zipline.testing.predicates import assert_equal from zipline.utils.numpy_utils import ( @@ -268,7 +268,7 @@ class EventIndexerTestCase(ZiplineTestCase): class EventsLoaderTestCase(WithAssetFinder, - WithNYSETradingDays, + WithTradingSessions, ZiplineTestCase): START_DATE = pd.Timestamp('2014-01-01') diff --git a/tests/test_algorithm.py b/tests/test_algorithm.py index 0968df6f..069874f9 100644 --- a/tests/test_algorithm.py +++ b/tests/test_algorithm.py @@ -98,7 +98,7 @@ from zipline.testing.fixtures import ( WithSimParams, WithTradingEnvironment, WithTmpDir, - WithTradingCalendar, + WithTradingCalendars, ZiplineTestCase, ) from zipline.test_algorithms import ( @@ -3500,7 +3500,7 @@ class TestOrderCancelation(WithDataPortal, self.assertFalse(log_catcher.has_warnings) -class TestEquityAutoClose(WithTmpDir, WithTradingCalendar, ZiplineTestCase): +class TestEquityAutoClose(WithTmpDir, WithTradingCalendars, ZiplineTestCase): """ Tests if delisted equities are properly removed from a portfolio holding positions in said equities. diff --git a/tests/test_assets.py b/tests/test_assets.py index f1ba7991..8eb6489c 100644 --- a/tests/test_assets.py +++ b/tests/test_assets.py @@ -82,7 +82,7 @@ from zipline.testing.predicates import assert_equal from zipline.testing.fixtures import ( WithAssetFinder, ZiplineTestCase, - WithTradingCalendar, + WithTradingCalendars, ) from zipline.utils.range import range @@ -404,7 +404,7 @@ class TestFuture(WithAssetFinder, ZiplineTestCase): TestFuture.asset_finder.lookup_future_symbol('XXX99') -class AssetFinderTestCase(WithTradingCalendar, ZiplineTestCase): +class AssetFinderTestCase(WithTradingCalendars, ZiplineTestCase): asset_finder_type = AssetFinder def write_assets(self, **kwargs): diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py index 950c0229..7abe4604 100644 --- a/tests/test_benchmark.py +++ b/tests/test_benchmark.py @@ -30,12 +30,12 @@ from zipline.testing import ( from zipline.testing.fixtures import ( WithDataPortal, WithSimParams, - WithTradingCalendar, + WithTradingCalendars, ZiplineTestCase, ) -class TestBenchmark(WithDataPortal, WithSimParams, WithTradingCalendar, +class TestBenchmark(WithDataPortal, WithSimParams, WithTradingCalendars, ZiplineTestCase): START_DATE = pd.Timestamp('2006-01-03', tz='utc') END_DATE = pd.Timestamp('2006-12-29', tz='utc') diff --git a/tests/test_perf_tracking.py b/tests/test_perf_tracking.py index cc36b418..7e053720 100644 --- a/tests/test_perf_tracking.py +++ b/tests/test_perf_tracking.py @@ -57,7 +57,7 @@ from zipline.testing.fixtures import ( WithSimParams, WithTmpDir, WithTradingEnvironment, - WithTradingCalendar, + WithTradingCalendars, ZiplineTestCase, ) from zipline.utils.calendars import get_calendar @@ -1031,8 +1031,9 @@ class TestDividendPerformanceHolidayStyle(TestDividendPerformance): END_DATE = pd.Timestamp('2003-12-08', tz='utc') -class TestPositionPerformance(WithInstanceTmpDir, WithTradingCalendar, +class TestPositionPerformance(WithInstanceTmpDir, WithTradingCalendars, ZiplineTestCase): + def create_environment_stuff(self, num_days=4, sids=[1, 2], diff --git a/tests/test_security_list.py b/tests/test_security_list.py index 4d699ff7..f0609142 100644 --- a/tests/test_security_list.py +++ b/tests/test_security_list.py @@ -14,7 +14,7 @@ from zipline.testing import ( ) from zipline.testing.fixtures import ( WithLogger, - WithTradingCalendar, + WithTradingCalendars, ZiplineTestCase, ) from zipline.utils import factory @@ -67,7 +67,7 @@ class IterateRLAlgo(TradingAlgorithm): self.found = True -class SecurityListTestCase(WithLogger, WithTradingCalendar, ZiplineTestCase): +class SecurityListTestCase(WithLogger, WithTradingCalendars, ZiplineTestCase): @classmethod def init_class_fixtures(cls): diff --git a/zipline/testing/fixtures.py b/zipline/testing/fixtures.py index 040ace99..2a8b3294 100644 --- a/zipline/testing/fixtures.py +++ b/zipline/testing/fixtures.py @@ -3,7 +3,7 @@ from unittest import TestCase from contextlib2 import ExitStack from logbook import NullHandler, Logger -from six import with_metaclass +from six import with_metaclass, iteritems from toolz import flip import pandas as pd import responses @@ -365,28 +365,58 @@ class WithAssetFinder(WithDefaultDateBounds): cls.asset_finder = cls.make_asset_finder() -class WithTradingCalendar(object): +class WithTradingCalendars(object): """ - ZiplineTestCase mixing providing cls.trading_calendar as a class-level - fixture. + ZiplineTestCase mixin providing cls.trading_calendar, + cls.all_trading_calendars, cls.trading_calendar_for_asset_type as a + class-level fixture. - After ``init_class_fixtures`` has been called, `cls.trading_calendar` is - populated with a trading calendar. + After ``init_class_fixtures`` has been called: + - `cls.trading_calendar` is populated with a default of the nyse trading + calendar for compatibility with existing tests + - `cls.all_trading_calendars` is populated with the trading calendars + keyed by name, + - `cls.trading_calendar_for_asset_type` is populated with the trading + calendars keyed by the asset type which uses the respective calendar. Attributes ---------- - TRADING_CALENDAR_STR : str - The identifier of the calendar to use. + TRADING_CALENDAR_STRS : iterable + iterable of identifiers of the calendars to use. + TRADING_CALENDAR_FOR_ASSET_TYPE : dict + A dictionay which maps asset type names to the calendar associated + with that asset type. """ - TRADING_CALENDAR_STR = 'NYSE' + TRADING_CALENDAR_STRS = ('NYSE',) + TRADING_CALENDAR_FOR_ASSET_TYPE = {'equities': 'NYSE'} + + # For backwards compatibility, exisitng tests and fixtures refer to + # `trading_calendar` with the assumption that the value is the NYSE + # calendar. + trading_calendar = alias('nyse_calendar') @classmethod def init_class_fixtures(cls): - super(WithTradingCalendar, cls).init_class_fixtures() - cls.trading_calendar = get_calendar(cls.TRADING_CALENDAR_STR) + super(WithTradingCalendars, cls).init_class_fixtures() + + cls.trading_calendars = {} + + for cal_str in cls.TRADING_CALENDAR_STRS: + # Set name to allow aliasing. + calendar = get_calendar(cal_str) + setattr(cls, + '{0}_calendar'.format(cal_str.lower()), calendar) + cls.trading_calendars[cal_str] = calendar + for asset_type, cal_str in iteritems( + cls.TRADING_CALENDAR_FOR_ASSET_TYPE): + calendar = get_calendar(cal_str) + setattr(cls, + '{0}_calendar'.format(asset_type), + calendar) + cls.trading_calendars[asset_type] = calendar -class WithTradingEnvironment(WithAssetFinder, WithTradingCalendar): +class WithTradingEnvironment(WithAssetFinder, WithTradingCalendars): """ ZiplineTestCase mixin providing cls.env as a class-level fixture. @@ -493,15 +523,21 @@ class WithSimParams(WithTradingEnvironment): cls.sim_params = cls.make_simparams() -class WithNYSETradingDays(WithTradingCalendar): +class WithTradingSessions(WithTradingCalendars): """ - ZiplineTestCase mixin providing cls.trading_days as a class-level fixture. + ZiplineTestCase mixin providing cls.trading_days, cls.all_trading_sessions + as a class-level fixture. - After init_class_fixtures has been called, `cls.trading_days` is populated - with a DatetimeIndex containing NYSE calendar trading days ranging from: + After init_class_fixtures has been called, `cls.all_trading_sessions` + is populated with a dictionary of calendar name to the DatetimeIndex + containing the calendar trading days ranging from: (DATA_MAX_DAY - (cls.TRADING_DAY_COUNT) -> DATA_MAX_DAY) + `cls.trading_days`, for compatibility with existing tests which make the + assumption that trading days are equity only, defaults to the nyse trading + sessions. + Attributes ---------- DATA_MAX_DAY : datetime @@ -514,15 +550,27 @@ class WithNYSETradingDays(WithTradingCalendar): DATA_MIN_DAY = alias('START_DATE') DATA_MAX_DAY = alias('END_DATE') + # For backwards compatibility, exisitng tests and fixtures refer to + # `trading_days` with the assumption that the value is days of the NYSE + # calendar. + trading_days = alias('nyse_sessions') + @classmethod def init_class_fixtures(cls): - super(WithNYSETradingDays, cls).init_class_fixtures() + super(WithTradingSessions, cls).init_class_fixtures() - all_days = cls.trading_calendar.all_sessions - start_loc = all_days.get_loc(cls.DATA_MIN_DAY, 'bfill') - end_loc = all_days.get_loc(cls.DATA_MAX_DAY, 'ffill') + cls.trading_sessions = {} - cls.trading_days = all_days[start_loc:end_loc + 1] + for name, trading_calendar in iteritems(cls.trading_calendars): + all_sessions = trading_calendar.all_sessions + start_loc = all_sessions.get_loc(cls.DATA_MIN_DAY, 'bfill') + end_loc = all_sessions.get_loc(cls.DATA_MAX_DAY, 'ffill') + + sessions = all_sessions[start_loc:end_loc + 1] + # Set name for aliasing. + setattr(cls, + '{0}_sessions'.format(name.lower()), sessions) + cls.trading_sessions[name] = sessions class WithTmpDir(object): @@ -814,8 +862,9 @@ class WithEquityMinuteBarData(WithTradingEnvironment): @classmethod def make_equity_minute_bar_data(cls): + trading_calendar = cls.equities_calendar return create_minute_bar_data( - cls.trading_calendar.minutes_for_sessions_in_range( + trading_calendar.minutes_for_sessions_in_range( cls.equity_minute_bar_days[0], cls.equity_minute_bar_days[-1], ), @@ -826,19 +875,19 @@ class WithEquityMinuteBarData(WithTradingEnvironment): def init_class_fixtures(cls): super(WithEquityMinuteBarData, cls).init_class_fixtures() if cls.EQUITY_MINUTE_BAR_USE_FULL_CALENDAR: - days = cls.trading_calendar.all_execution_days + days = cls.equites_calendar.all_execution_days else: - first_session = cls.trading_calendar.minute_to_session_label( + first_session = cls.equities_calendar.minute_to_session_label( pd.Timestamp(cls.EQUITY_MINUTE_BAR_START_DATE) ) if cls.EQUITY_MINUTE_BAR_LOOKBACK_DAYS > 0: - first_session = cls.trading_calendar.sessions_window( + first_session = cls.equities_calendar.sessions_window( first_session, -1 * cls.EQUITY_MINUTE_BAR_LOOKBACK_DAYS )[0] - days = cls.trading_calendar.sessions_in_range( + days = cls.equities_calendar.sessions_in_range( first_session, cls.EQUITY_MINUTE_BAR_END_DATE ) @@ -1000,7 +1049,7 @@ class WithAdjustmentReader(WithBcolzEquityDailyBarReader): cls.adjustment_reader = SQLiteAdjustmentReader(conn) -class WithSeededRandomPipelineEngine(WithNYSETradingDays, WithAssetFinder): +class WithSeededRandomPipelineEngine(WithTradingSessions, WithAssetFinder): """ ZiplineTestCase mixin providing class-level fixtures for running pipelines against deterministically-generated random data.