diff --git a/tests/finance/test_slippage.py b/tests/finance/test_slippage.py index 4c7778ea..7eebc418 100644 --- a/tests/finance/test_slippage.py +++ b/tests/finance/test_slippage.py @@ -38,7 +38,6 @@ from zipline.testing.fixtures import ( WithSimParams, ZiplineTestCase, ) -from zipline.utils.calendars import default_nyse_schedule class SlippageTestCase(WithSimParams, WithDataPortal, ZiplineTestCase): @@ -92,9 +91,10 @@ class SlippageTestCase(WithSimParams, WithDataPortal, ZiplineTestCase): start=normalize_date(self.minutes[0]), end=normalize_date(self.minutes[-1]) ) - with tmp_bcolz_minute_bar_reader(self.env, days, assets) as reader: + with tmp_bcolz_minute_bar_reader(self.trading_schedule, days, assets) \ + as reader: data_portal = DataPortal( - self.env, default_nyse_schedule, + self.env, self.trading_schedule, first_trading_day=reader.first_trading_day, equity_minute_reader=reader, ) @@ -481,14 +481,11 @@ class SlippageTestCase(WithSimParams, WithDataPortal, ZiplineTestCase): start=normalize_date(self.minutes[0]), end=normalize_date(self.minutes[-1]) ) - with tmp_bcolz_minute_bar_reader(self.env, days, assets) as reader: + with tmp_bcolz_minute_bar_reader(self.trading_schedule, days, assets) \ + as reader: data_portal = DataPortal( -<<<<<<< HEAD - self.env, + self.env, self.trading_schedule, first_trading_day=reader.first_trading_day, -======= - self.env, default_nyse_schedule, ->>>>>>> ENH: Adds ExchangeCalendar, TradingSchedule, and implementations equity_minute_reader=reader, ) diff --git a/tests/pipeline/test_engine.py b/tests/pipeline/test_engine.py index cd89387a..251ea547 100644 --- a/tests/pipeline/test_engine.py +++ b/tests/pipeline/test_engine.py @@ -931,7 +931,7 @@ class SyntheticBcolzTestCase(WithAdjustmentReader, cls.equity_info = ret = make_rotating_equity_info( num_assets=6, first_start=cls.first_asset_start, - frequency=cls.TRADING_ENV_TRADING_CALENDAR.trading_day, + frequency=cls.trading_schedule.day, periods_between_starts=4, asset_lifetime=8, ) @@ -992,9 +992,9 @@ class SyntheticBcolzTestCase(WithAdjustmentReader, window_length = 5 asset_ids = self.all_asset_ids dates = date_range( - self.first_asset_start + self.env.trading_day, + self.first_asset_start + self.trading_schedule.day, self.last_asset_end, - freq=self.env.trading_day, + freq=self.trading_schedule.day, ) dates_to_test = dates[window_length:] @@ -1014,7 +1014,7 @@ class SyntheticBcolzTestCase(WithAdjustmentReader, # **previous** day's data. expected_raw = rolling_mean( expected_bar_values_2d( - dates - self.env.trading_day, + dates - self.trading_schedule.day, self.equity_info, 'close', ), @@ -1046,9 +1046,9 @@ class SyntheticBcolzTestCase(WithAdjustmentReader, window_length = 5 asset_ids = self.all_asset_ids dates = date_range( - self.first_asset_start + self.env.trading_day, + self.first_asset_start + self.trading_schedule.day, self.last_asset_end, - freq=self.env.trading_day, + freq=self.trading_schedule.day, ) dates_to_test = dates[window_length:] diff --git a/tests/test_algorithm.py b/tests/test_algorithm.py index 5f529cd0..84c4be95 100644 --- a/tests/test_algorithm.py +++ b/tests/test_algorithm.py @@ -751,7 +751,7 @@ class TestTransformAlgorithm(WithLogger, [100, 100, 100, 300], timedelta(days=1), cls.sim_params, - cls.env + cls.trading_schedule, ) for sid in cls.sids }, index=cls.sim_params.trading_days, @@ -1023,10 +1023,11 @@ class TestBeforeTradingStart(WithDataPortal, @classmethod def make_minute_bar_data(cls): - asset_minutes = cls.env.minutes_for_days_in_range( - cls.data_start, - cls.END_DATE, - ) + asset_minutes = \ + cls.trading_schedule.execution_minutes_for_days_in_range( + cls.data_start, + cls.END_DATE, + ) minutes_count = len(asset_minutes) minutes_arr = np.arange(minutes_count) + 1 split_data = pd.DataFrame( @@ -1042,13 +1043,13 @@ class TestBeforeTradingStart(WithDataPortal, split_data.iloc[780:] = split_data.iloc[780:] / 2.0 for sid in (1, 8554): yield sid, create_minute_df_for_asset( - cls.env, + cls.trading_schedule, cls.data_start, cls.sim_params.period_end, ) yield 2, create_minute_df_for_asset( - cls.env, + cls.trading_schedule, cls.data_start, cls.sim_params.period_end, 50, @@ -1069,7 +1070,7 @@ class TestBeforeTradingStart(WithDataPortal, def make_daily_bar_data(cls): for sid in cls.ASSET_FINDER_EQUITY_SIDS: yield sid, create_daily_df_for_asset( - cls.env, + cls.trading_schedule, cls.data_start, cls.sim_params.period_end, ) @@ -1397,7 +1398,8 @@ class TestAlgoScript(WithLogger, @classmethod def make_daily_bar_data(cls): - days = len(cls.env.days_in_range(cls.START_DATE, cls.END_DATE)) + days = len(cls.trading_schedule.execution_days_in_range(cls.START_DATE, + cls.END_DATE)) return trades_by_sid_to_dfs( { 0: factory.create_trade_history( @@ -1406,14 +1408,14 @@ class TestAlgoScript(WithLogger, [100] * days, timedelta(days=1), cls.sim_params, - cls.env), + cls.trading_schedule), 3: factory.create_trade_history( 3, [10.0] * days, [100] * days, timedelta(days=1), cls.sim_params, - cls.env) + cls.trading_schedule) }, index=cls.sim_params.trading_days, ) @@ -3169,10 +3171,11 @@ class TestOrderCancelation(WithDataPortal, @classmethod def make_minute_bar_data(cls): - asset_minutes = cls.env.minutes_for_days_in_range( - cls.sim_params.period_start, - cls.sim_params.period_end, - ) + asset_minutes = \ + cls.trading_schedule.execution_minutes_for_days_in_range( + cls.sim_params.period_start, + cls.sim_params.period_end, + ) minutes_count = len(asset_minutes) minutes_arr = np.arange(1, 1 + minutes_count) diff --git a/tests/test_bar_data.py b/tests/test_bar_data.py index f12dad1e..ac3837f9 100644 --- a/tests/test_bar_data.py +++ b/tests/test_bar_data.py @@ -111,21 +111,21 @@ class TestMinuteBarData(WithBarDataChecks, # illiquid_split_asset trades every 10 minutes for sid in (1, cls.SPLIT_ASSET_SID): yield sid, create_minute_df_for_asset( - cls.env, + cls.trading_schedule, cls.bcolz_minute_bar_days[0], cls.bcolz_minute_bar_days[-1], ) for sid in (2, cls.ILLIQUID_SPLIT_ASSET_SID): yield sid, create_minute_df_for_asset( - cls.env, + cls.trading_schedule, cls.bcolz_minute_bar_days[0], cls.bcolz_minute_bar_days[-1], 10, ) yield cls.HILARIOUSLY_ILLIQUID_ASSET_SID, create_minute_df_for_asset( - cls.env, + cls.trading_schedule, cls.bcolz_minute_bar_days[0], cls.bcolz_minute_bar_days[-1], 50, diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py index e39e2535..73a28e83 100644 --- a/tests/test_benchmark.py +++ b/tests/test_benchmark.py @@ -147,13 +147,13 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase): ) tmp_reader = tmp_bcolz_minute_bar_reader( - self.env, - self.env.trading_days, + self.trading_schedule, + self.trading_schedule.all_execution_days, create_minute_bar_data(minutes, [2]), ) with tmp_reader as reader: data_portal = DataPortal( - self.env, + self.env, self.trading_schedule, first_trading_day=reader.first_trading_day, equity_minute_reader=reader, equity_daily_reader=self.bcolz_daily_bar_reader, @@ -163,7 +163,7 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase): source = BenchmarkSource( 2, self.env, - default_nyse_schedule, + self.trading_schedule, self.sim_params.trading_days, data_portal ) diff --git a/tests/test_finance.py b/tests/test_finance.py index 2ab293d5..2640aa76 100644 --- a/tests/test_finance.py +++ b/tests/test_finance.py @@ -394,44 +394,6 @@ class TradingEnvironmentTestCase(WithLogger, """ Tests for date management utilities in zipline.finance.trading. """ - @timed(DEFAULT_TIMEOUT) - def test_is_trading_day(self): - # holidays taken from: http://www.nyse.com/press/1191407641943.html - new_years = datetime(2008, 1, 1, tzinfo=pytz.utc) - mlk_day = datetime(2008, 1, 21, tzinfo=pytz.utc) - presidents = datetime(2008, 2, 18, tzinfo=pytz.utc) - good_friday = datetime(2008, 3, 21, tzinfo=pytz.utc) - memorial_day = datetime(2008, 5, 26, tzinfo=pytz.utc) - july_4th = datetime(2008, 7, 4, tzinfo=pytz.utc) - labor_day = datetime(2008, 9, 1, tzinfo=pytz.utc) - tgiving = datetime(2008, 11, 27, tzinfo=pytz.utc) - christmas = datetime(2008, 5, 25, tzinfo=pytz.utc) - a_saturday = datetime(2008, 8, 2, tzinfo=pytz.utc) - a_sunday = datetime(2008, 10, 12, tzinfo=pytz.utc) - holidays = [ - new_years, - mlk_day, - presidents, - good_friday, - memorial_day, - july_4th, - labor_day, - tgiving, - christmas, - a_saturday, - a_sunday - ] - - for holiday in holidays: - self.assertTrue(not self.cal.is_open_on_day(holiday)) - - first_trading_day = datetime(2008, 1, 2, tzinfo=pytz.utc) - last_trading_day = datetime(2008, 12, 31, tzinfo=pytz.utc) - workdays = [first_trading_day, last_trading_day] - - for workday in workdays: - self.assertTrue(self.cal.is_open_on_day(workday)) - def test_simulation_parameters(self): sp = SimulationParameters( period_start=datetime(2008, 1, 1, tzinfo=pytz.utc), @@ -477,85 +439,3 @@ class TradingEnvironmentTestCase(WithLogger, self.assertEquals(num_expected_trading_days, params.days_in_period) np.testing.assert_array_equal(expected_trading_days, params.trading_days.tolist()) - - @timed(DEFAULT_TIMEOUT) - def test_minute_window(self): - - # January 2008 - # 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 31 - - us_east = pytz.timezone('US/Eastern') - utc = pytz.utc - - # 10:01 AM Eastern on January 7th.. - start = us_east.localize(datetime(2008, 1, 7, 10, 1)) - utc_start = pd.Timestamp(start.astimezone(utc)) - - # Get the next 10 minutes - minutes = self.cal.trading_minute_window( - utc_start, 10, - ) - self.assertEqual(len(minutes), 10) - for i in range(10): - self.assertEqual(minutes[i], utc_start + timedelta(minutes=i)) - - # Get the previous 10 minutes. - minutes = self.cal.trading_minute_window( - utc_start, 10, step=-1, - ) - self.assertEqual(len(minutes), 10) - for i in range(10): - self.assertEqual(minutes[i], utc_start + timedelta(minutes=-i)) - - # Get the next 900 minutes, including utc_start, rolling over into the - # next two days. - # Should include: - # Today: 10:01 AM -> 4:00 PM (360 minutes) - # Tomorrow: 9:31 AM -> 4:00 PM (390 minutes, 750 total) - # Last Day: 9:31 AM -> 12:00 PM (150 minutes, 900 total) - minutes = self.cal.trading_minute_window( - start, 900, - ) - today = self.cal.trading_minutes_for_day(utc_start)[30:] - tomorrow = self.cal.trading_minutes_for_day( - start + timedelta(days=1) - ) - last_day = self.cal.trading_minutes_for_day( - start + timedelta(days=2))[:150] - - self.assertEqual(len(minutes), 900) - self.assertEqual(minutes[0], utc_start) - self.assertTrue(all(today == minutes[:360])) - self.assertTrue(all(tomorrow == minutes[360:750])) - self.assertTrue(all(last_day == minutes[750:])) - - # Get the previous 801 minutes, including utc_start, rolling over into - # Friday the 4th and Thursday the 3rd. - # Should include: - # Today: 10:01 AM -> 9:31 AM (31 minutes) - # Friday: 4:00 PM -> 9:31 AM (390 minutes, 421 total) - # Thursday: 4:00 PM -> 9:41 AM (380 minutes, 801 total) - minutes = self.cal.trading_minute_window( - start, 801, step=-1, - ) - - today = self.cal.trading_minutes_for_day(utc_start)[30::-1] - # minus an extra two days from each of these to account for the two - # weekend days we skipped - friday = self.cal.trading_minutes_for_day( - start + timedelta(days=-3), - )[::-1] - thursday = self.cal.trading_minutes_for_day( - start + timedelta(days=-4), - )[:9:-1] - - self.assertEqual(len(minutes), 801) - self.assertEqual(minutes[0], utc_start) - self.assertTrue(all(today == minutes[:31])) - self.assertTrue(all(friday == minutes[31:421])) - self.assertTrue(all(thursday == minutes[421:])) diff --git a/tests/test_history.py b/tests/test_history.py index 74c993f4..f73726ed 100644 --- a/tests/test_history.py +++ b/tests/test_history.py @@ -1136,7 +1136,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase): def test_history_window_before_first_trading_day(self): # trading_start is 2/3/2014 # get a history window that starts before that, and ends after that - self.data_portal._first_trading_day = self.TRADING_START_DT + self.data_portal.set_first_trading_day(self.TRADING_START_DT) first_day_minutes = default_nyse_schedule.execution_minutes_for_day( self.TRADING_START_DT ) @@ -1645,6 +1645,7 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase): # trading_start is 2/3/2014 # get a history window that starts before that, and ends after that + self.data_portal.set_first_trading_day(self.TRADING_START_DT) second_day = default_nyse_schedule.next_execution_day( self.TRADING_START_DT ) diff --git a/tests/utils/test_events.py b/tests/utils/test_events.py index d7503804..efa3d074 100644 --- a/tests/utils/test_events.py +++ b/tests/utils/test_events.py @@ -395,7 +395,7 @@ class TestStatelessRules(RuleTestCase): sim_start = pd.Timestamp('01-06-2014', tz='UTC') + \ timedelta(days=start_offset) - jan_minutes = self.env.minutes_for_days_in_range( + jan_minutes = self.nyse_cal.trading_minutes_for_days_in_range( datetime.date(year=2014, month=1, day=6) + timedelta(days=start_offset), datetime.date(year=2014, month=1, day=31) @@ -426,9 +426,8 @@ class TestStatelessRules(RuleTestCase): trigger_dates = \ [x - timedelta(days=rule_offset) for x in trigger_dates] - should_trigger = partial( - rule(rule_offset).should_trigger, env=self.env - ) + rule.cal = self.nyse_cal + should_trigger = rule(rule_offset).should_trigger # If offset is 4, there is not enough trading days in the short week, # and so it should not trigger @@ -439,9 +438,9 @@ class TestStatelessRules(RuleTestCase): trigger_dates = [x for x in trigger_dates if x >= sim_start] # Get all the minutes on the trigger dates - trigger_dts = self.env.market_minutes_for_day(trigger_dates[0]) + trigger_dts = self.nyse_cal.trading_minutes_for_day(trigger_dates[0]) for dt in trigger_dates[1:]: - trigger_dts += self.env.market_minutes_for_day(dt) + trigger_dts += self.nyse_cal.trading_minutes_for_day(dt) expected_n_triggered = len(trigger_dts) trigger_dts = iter(trigger_dts) @@ -460,11 +459,14 @@ class TestStatelessRules(RuleTestCase): NDaysBeforeLastTradingDayOfWeek(4) time_rule = AfterOpen(minutes=60) + week_rule.cal = self.nyse_cal + time_rule.cal = self.nyse_cal + composed_rule = week_rule & time_rule - should_trigger = partial(composed_rule.should_trigger, env=self.env) + should_trigger = composed_rule.should_trigger - week_minutes = self.env.minutes_for_days_in_range( + week_minutes = self.nyse_cal.trading_minutes_for_days_in_range( datetime.date(year=2014, month=1, day=6), datetime.date(year=2014, month=1, day=10) ) diff --git a/zipline/algorithm.py b/zipline/algorithm.py index b7c8fb24..d35d063a 100644 --- a/zipline/algorithm.py +++ b/zipline/algorithm.py @@ -617,8 +617,8 @@ class TradingAlgorithm(object): self.sim_params.period_end = data.major_axis[-1] # Changing period_start and period_close might require # updating of first_open and last_close. - self.sim_params.update_internal_from_env( - env=self.trading_environment + self.sim_params.update_internal_from_trading_schedule( + trading_schedule=self.trading_schedule ) copy_panel = data.rename( @@ -753,7 +753,7 @@ class TradingAlgorithm(object): fake_sids = range(first_sid, first_sid + len(new_symbols)) frame_to_write = make_simple_equity_info( sids=fake_sids, - start_date=self.sim_params.period_start, + start_date=as_of_date, end_date=self.sim_params.period_end, symbols=new_symbols, ) diff --git a/zipline/data/data_portal.py b/zipline/data/data_portal.py index d8ca3a7a..a83b5f50 100644 --- a/zipline/data/data_portal.py +++ b/zipline/data/data_portal.py @@ -545,8 +545,6 @@ class DataPortal(object): self._future_daily_reader = future_daily_reader self._future_minute_reader = future_minute_reader - self._first_trading_day = first_trading_day - if self._equity_minute_reader is not None: self._equity_daily_aggregator = DailyHistoryAggregator( self.trading_schedule.schedule.market_open, @@ -559,6 +557,26 @@ class DataPortal(object): self.MINUTE_PRICE_ADJUSTMENT_FACTOR = \ self._equity_minute_reader._ohlc_inverse + self.set_first_trading_day(first_trading_day) + + def set_first_trading_day(self, first_trading_day): + self._first_trading_day = first_trading_day + + # Get the first trading minute + if self._first_trading_day is not None: + self._first_trading_minute, _ = \ + self.trading_schedule.start_and_end(self._first_trading_day) + + # Store the locs of the first day and first minute + self._first_trading_day_loc = \ + self.trading_schedule.all_execution_days.get_loc( + self.trading_schedule.session_date(self._first_trading_day) + ) + self._first_trading_minute_loc = \ + self.trading_schedule.all_execution_minutes.get_loc( + self._first_trading_minute + ) + def _reindex_extra_source(self, df, source_date_index): return df.reindex(index=source_date_index, method='ffill') diff --git a/zipline/finance/performance/tracker.py b/zipline/finance/performance/tracker.py index 038445e3..5dc01ded 100644 --- a/zipline/finance/performance/tracker.py +++ b/zipline/finance/performance/tracker.py @@ -299,14 +299,17 @@ class PerformanceTracker(object): # date comes. if held_sids: - asset_finder = self.env.asset_finder - - cash_dividends = adjustment_reader.\ - get_dividends_with_ex_date(held_sids, next_trading_day, - asset_finder) + cash_dividends = adjustment_reader.get_dividends_with_ex_date( + held_sids, + next_trading_day, + self.asset_finder + ) stock_dividends = adjustment_reader.\ - get_stock_dividends_with_ex_date(held_sids, next_trading_day, - asset_finder) + get_stock_dividends_with_ex_date( + held_sids, + next_trading_day, + self.asset_finder + ) position_tracker.earn_dividends( cash_dividends, diff --git a/zipline/testing/fixtures.py b/zipline/testing/fixtures.py index 77414de1..4e9262b8 100644 --- a/zipline/testing/fixtures.py +++ b/zipline/testing/fixtures.py @@ -47,7 +47,10 @@ from zipline.pipeline.loaders.utils import ( get_values_for_date_ranges, zip_with_dates ) -from zipline.utils.calendars import default_nyse_schedule +from zipline.utils.calendars import ( + get_calendar, + ExchangeTradingSchedule, +) class ZiplineTestCase(with_metaclass(FinalMeta, TestCase)): @@ -365,7 +368,41 @@ class WithAssetFinder(WithDefaultDateBounds): cls.asset_finder = cls.make_asset_finder() -class WithTradingEnvironment(WithAssetFinder): +class WithTradingSchedule(object): + """ + ZiplineTestCase mixing providing cls.trading_schedule as a class-level + fixture. + + After ``init_class_fixtures`` has been called, `cls.trading_schedule` is + populated with a trading schedule. + + Attributes + ---------- + TRADING_SCHEDULE_CALENDAR : ExchangeCalendar + The ExchangeCalendar to be wrapped in an ExchangeTradingSchedule. + + Methods + ------- + make_trading_schedule() -> TradingSchedule + A class method that constructs the trading schedule for the class. + + See Also + -------- + :class:`zipline.utils.calendars.trading_schedule.TradingSchedule` + """ + TRADING_SCHEDULE_CALENDAR = get_calendar('NYSE') + + @classmethod + def make_trading_schedule(cls): + return ExchangeTradingSchedule(cls.TRADING_SCHEDULE_CALENDAR) + + @classmethod + def init_class_fixtures(cls): + super(WithTradingSchedule, cls).init_class_fixtures() + cls.trading_schedule = cls.make_trading_schedule() + + +class WithTradingEnvironment(WithAssetFinder, WithTradingSchedule): """ ZiplineTestCase mixin providing cls.env as a class-level fixture. @@ -398,7 +435,6 @@ class WithTradingEnvironment(WithAssetFinder): -------- :class:`zipline.finance.trading.TradingEnvironment` """ - TRADING_ENV_TRADING_SCHEDULE = default_nyse_schedule @classmethod def make_load_function(cls): @@ -409,7 +445,7 @@ class WithTradingEnvironment(WithAssetFinder): return TradingEnvironment( load=cls.make_load_function(), asset_db_path=cls.asset_finder.engine, - trading_schedule=cls.TRADING_ENV_TRADING_SCHEDULE, + trading_schedule=cls.trading_schedule, ) @classmethod @@ -450,7 +486,6 @@ class WithSimParams(WithTradingEnvironment): SIM_PARAMS_NUM_DAYS = None SIM_PARAMS_DATA_FREQUENCY = 'daily' SIM_PARAMS_EMISSION_RATE = 'daily' - SIM_PARAMS_TRADING_SCHEDULE = default_nyse_schedule SIM_PARAMS_START = alias('START_DATE') SIM_PARAMS_END = alias('END_DATE') @@ -465,7 +500,7 @@ class WithSimParams(WithTradingEnvironment): capital_base=cls.SIM_PARAMS_CAPITAL_BASE, data_frequency=cls.SIM_PARAMS_DATA_FREQUENCY, emission_rate=cls.SIM_PARAMS_EMISSION_RATE, - trading_schedule=cls.SIM_PARAMS_TRADING_SCHEDULE, + trading_schedule=cls.trading_schedule, ) @classmethod @@ -474,7 +509,7 @@ class WithSimParams(WithTradingEnvironment): cls.sim_params = cls.make_simparams() -class WithNYSETradingDays(object): +class WithNYSETradingDays(WithTradingSchedule): """ ZiplineTestCase mixin providing cls.trading_days as a class-level fixture. @@ -499,7 +534,7 @@ class WithNYSETradingDays(object): def init_class_fixtures(cls): super(WithNYSETradingDays, cls).init_class_fixtures() - all_days = default_nyse_schedule.all_execution_days + all_days = cls.trading_schedule.all_execution_days start_loc = all_days.get_loc(cls.DATA_MIN_DAY, 'bfill') end_loc = all_days.get_loc(cls.DATA_MAX_DAY, 'ffill') @@ -609,7 +644,6 @@ class WithBcolzDailyBarReader(WithTradingEnvironment, WithTmpDir): BCOLZ_DAILY_BAR_END_DATE = alias('END_DATE') BCOLZ_DAILY_BAR_READ_ALL_THRESHOLD = None BCOLZ_DAILY_BAR_SOURCE_FROM_MINUTE = False - BCOLZ_TRADING_SCHEDULE = default_nyse_schedule # allows WithBcolzDailyBarReaderFromCSVs to call the `write_csvs` method # without needing to reimplement `init_class_fixtures` _write_method_name = 'write' @@ -678,13 +712,13 @@ class WithBcolzDailyBarReader(WithTradingEnvironment, WithTmpDir): cls.BCOLZ_DAILY_BAR_PATH, ) if cls.BCOLZ_DAILY_BAR_USE_FULL_CALENDAR: - days = cls.env.trading_days + days = cls.trading_schedule.all_execution_days else: - days = cls.env.days_in_range( - cls.env.trading_days[ - cls.env.get_index(cls.BCOLZ_DAILY_BAR_START_DATE) - - cls.BCOLZ_DAILY_BAR_LOOKBACK_DAYS - ], + days = cls.trading_schedule.execution_days_in_range( + cls.trading_schedule.add_execution_days( + -1 * cls.BCOLZ_DAILY_BAR_LOOKBACK_DAYS, + cls.BCOLZ_DAILY_BAR_START_DATE, + ), cls.BCOLZ_DAILY_BAR_END_DATE, ) cls.bcolz_daily_bar_days = days @@ -760,7 +794,7 @@ class WithBcolzMinuteBarReader(WithTradingEnvironment, WithTmpDir): @classmethod def make_minute_bar_data(cls): return create_minute_bar_data( - cls.env.minutes_for_days_in_range( + cls.trading_schedule.execution_minutes_for_days_in_range( cls.bcolz_minute_bar_days[0], cls.bcolz_minute_bar_days[-1], ), @@ -774,21 +808,21 @@ class WithBcolzMinuteBarReader(WithTradingEnvironment, WithTmpDir): cls.BCOLZ_MINUTE_BAR_PATH, ) if cls.BCOLZ_MINUTE_BAR_USE_FULL_CALENDAR: - days = cls.env.trading_days + days = cls.trading_schedule.all_execution_days else: - days = cls.env.days_in_range( - cls.env.trading_days[ - cls.env.get_index(cls.BCOLZ_MINUTE_BAR_START_DATE) - - cls.BCOLZ_MINUTE_BAR_LOOKBACK_DAYS - ], + days = cls.trading_schedule.execution_days_in_range( + cls.trading_schedule.add_execution_days( + -1 * cls.BCOLZ_MINUTE_BAR_LOOKBACK_DAYS, + cls.BCOLZ_MINUTE_BAR_START_DATE, + ), cls.BCOLZ_MINUTE_BAR_END_DATE, ) cls.bcolz_minute_bar_days = days writer = BcolzMinuteBarWriter( days[0], p, - cls.env.open_and_closes.market_open.loc[days], - cls.env.open_and_closes.market_close.loc[days], + cls.trading_schedule.schedule.market_open.loc[days], + cls.trading_schedule.schedule.market_close.loc[days], US_EQUITIES_MINUTES_PER_DAY ) writer.write(cls.make_minute_bar_data()) @@ -1164,6 +1198,7 @@ class WithDataPortal(WithAdjustmentReader, return DataPortal( self.env, + self.trading_schedule, first_trading_day=first_trading_day, equity_daily_reader=( self.bcolz_daily_bar_reader diff --git a/zipline/utils/calendars/trading_schedule.py b/zipline/utils/calendars/trading_schedule.py index 99a46cb5..84e5f199 100644 --- a/zipline/utils/calendars/trading_schedule.py +++ b/zipline/utils/calendars/trading_schedule.py @@ -180,12 +180,10 @@ class TradingSchedule(with_metaclass(ABCMeta)): raise NotImplementedError() @property - @remember_last def all_execution_days(self): return self.schedule.index @property - @remember_last def all_execution_minutes(self): return all_scheduled_minutes(self.all_execution_days, self.execution_minutes_for_days_in_range) @@ -331,6 +329,14 @@ class ExchangeTradingSchedule(TradingSchedule): self._exchange_calendar = cal super(ExchangeTradingSchedule, self).__init__() + @property + def all_execution_days(self): + return self._exchange_calendar.all_trading_days + + @property + def all_execution_minutes(self): + return self._exchange_calendar.all_trading_minutes + @property def day(self): return self._exchange_calendar.day diff --git a/zipline/utils/events.py b/zipline/utils/events.py index 6a3869a4..eafaddce 100644 --- a/zipline/utils/events.py +++ b/zipline/utils/events.py @@ -427,14 +427,14 @@ class TradingDayOfWeekRule(six.with_metaclass(ABCMeta, StatelessRule)): self.next_midnight_timestamp = None @abstractmethod - def date_func(self, dt): + def date_func(self, dt, cal): raise NotImplementedError def calculate_start_and_end(self, dt): next_trading_day = _coerce_datetime( self.cal.add_trading_days( self.td_delta, - self.date_func(dt), + self.date_func(dt, self.cal), ) ) @@ -445,7 +445,7 @@ class TradingDayOfWeekRule(six.with_metaclass(ABCMeta, StatelessRule)): next_trading_day = _coerce_datetime( self.cal.add_trading_days( self.td_delta, - self.date_func(dt), + self.date_func(dt, self.cal), ) ) @@ -497,7 +497,7 @@ class NthTradingDayOfWeek(TradingDayOfWeekRule): if dt is None: return prev - if cal.is_trading_day(prev): + if cal.is_open_on_day(prev): return prev.date() else: return cal.next_trading_day(prev).date() @@ -522,7 +522,7 @@ class NDaysBeforeLastTradingDayOfWeek(TradingDayOfWeekRule): prev = dt dt = cal.next_trading_day(dt) - if cal.is_trading_day(prev): + if cal.is_open_on_day(prev): return prev.date() else: return cal.previous_trading_day(prev).date()