mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-15 11:22:18 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user