TST: Make room for multiple calendars in tests.

When adding fixtures for futures data, there will be a need for multiple
calendars in the fixture ecosystem. e.g. a test that includes both
equities and futures would need an overall calendar which encompasses
both equities and futures; however, the test data for equities should
still still be limited to the bounds set by the NYSE calendar.

Make the fixtures that setup trading calendars and values dervied from
the trading calendar (e.g. trading sessions) accept an iterable of
calendars which need to be created, then populate those values into a
dict keyed by the calendar name.

Change `WithNYSETradingDays` to include sessions in the name,
since we are moving to session as the name for the 'day' unit.

Provide `trading_days` which is really "NYSE trading sessions` on
`WithTradingSessions` for backwards compatibility.
This commit is contained in:
Eddie Hebert
2016-08-05 12:17:27 -04:00
parent 7075a24ba7
commit e934c6aeaf
9 changed files with 97 additions and 43 deletions
+3 -2
View File
@@ -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
+5 -2
View File
@@ -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):
+2 -2
View File
@@ -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')
+2 -2
View File
@@ -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.
+2 -2
View File
@@ -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):
+2 -2
View File
@@ -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')
+3 -2
View File
@@ -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],
+2 -2
View File
@@ -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):
+76 -27
View File
@@ -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.