Skip to content

Commit

Permalink
Re-implemented the Calendar API.
Browse files Browse the repository at this point in the history
Instead of having separate ExchangeCalendar and TradingSchedule objects, we
now just have TradingCalendar.  The TradingCalendar keeps track of each
session (defined as a contiguous set of minutes between an open and a close).
It's also responsible for handling the grouping logic of any given minute
to its containing session, or the next/previous session if it's not a market
minute for the given calendar.
  • Loading branch information
Jean Bredeche committed Jul 12, 2016
1 parent db4e060 commit 6fb4923
Show file tree
Hide file tree
Showing 71 changed files with 3,114 additions and 3,976 deletions.
6 changes: 5 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ def build_extensions(self):
Extension(
'zipline.data._minute_bar_internal',
['zipline/data/_minute_bar_internal.pyx']
)
),
Extension(
'zipline.utils.calendars._calendar_helpers',
['zipline/utils/calendars/_calendar_helpers.pyx']
),
]


Expand Down
4 changes: 2 additions & 2 deletions tests/data/bundles/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ def bundle_ingest(environ,
def test_ingest(self):
start = pd.Timestamp('2014-01-06', tz='utc')
end = pd.Timestamp('2014-01-10', tz='utc')
trading_days = get_calendar('NYSE').all_trading_days
trading_days = get_calendar('NYSE').all_sessions
calendar = trading_days[trading_days.slice_indexer(start, end)]
minutes = get_calendar('NYSE').trading_minutes_for_days_in_range(
minutes = get_calendar('NYSE').minutes_for_sessions_in_range(
calendar[0], calendar[-1]
)

Expand Down
2 changes: 1 addition & 1 deletion tests/data/bundles/test_yahoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class YahooBundleTestCase(WithResponses, ZiplineTestCase):
columns = 'open', 'high', 'low', 'close', 'volume'
asset_start = pd.Timestamp('2014-01-02', tz='utc')
asset_end = pd.Timestamp('2014-12-31', tz='utc')
trading_days = get_calendar('NYSE').all_trading_days
trading_days = get_calendar('NYSE').all_sessions
calendar = trading_days[
(trading_days >= asset_start) &
(trading_days <= asset_end)
Expand Down
37 changes: 23 additions & 14 deletions tests/data/test_minute_bars.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

from zipline.testing.fixtures import (
WithInstanceTmpDir,
WithTradingSchedule,
WithTradingCalendar,
ZiplineTestCase,
)

Expand All @@ -56,17 +56,20 @@
TEST_CALENDAR_STOP = Timestamp('2015-12-31', tz='UTC')


class BcolzMinuteBarTestCase(WithTradingSchedule, WithInstanceTmpDir,
class BcolzMinuteBarTestCase(WithTradingCalendar, WithInstanceTmpDir,
ZiplineTestCase):

@classmethod
def init_class_fixtures(cls):
super(BcolzMinuteBarTestCase, cls).init_class_fixtures()
trading_days = cls.trading_schedule.trading_sessions(
TEST_CALENDAR_START, TEST_CALENDAR_STOP
)
cls.market_opens = trading_days.market_open
cls.market_closes = trading_days.market_close

cal = cls.trading_calendar.schedule.loc[
TEST_CALENDAR_START:TEST_CALENDAR_STOP
]

cls.market_opens = cal.market_open
cls.market_closes = cal.market_close

cls.test_calendar_start = cls.market_opens.index[0]
cls.test_calendar_stop = cls.market_opens.index[-1]

Expand Down Expand Up @@ -798,9 +801,9 @@ def test_unadjusted_minutes_early_close(self):
data = {sids[0]: data_1, sids[1]: data_2}

start_minute_loc = \
self.trading_schedule.all_execution_minutes.get_loc(minutes[0])
self.trading_calendar.all_minutes.get_loc(minutes[0])
minute_locs = [
self.trading_schedule.all_execution_minutes.get_loc(minute)
self.trading_calendar.all_minutes.get_loc(minute)
- start_minute_loc
for minute in minutes
]
Expand All @@ -822,9 +825,11 @@ def test_adjust_non_trading_minutes(self):
'close': arange(1, 781),
'volume': arange(1, 781)
}
dts = array(self.trading_schedule.execution_minutes_for_days_in_range(
start_day, end_day
dts = array(self.trading_calendar.minutes_for_sessions_in_range(
self.trading_calendar.minute_to_session_label(start_day),
self.trading_calendar.minute_to_session_label(end_day)
))

self.writer.write_cols(sid, dts, cols)

self.assertEqual(
Expand Down Expand Up @@ -866,9 +871,13 @@ def test_adjust_non_trading_minutes_half_days(self):
'close': arange(1, 601),
'volume': arange(1, 601)
}
dts = array(self.trading_schedule.execution_minutes_for_days_in_range(
start_day, end_day
))
dts = array(
self.trading_calendar.minutes_for_sessions_in_range(
self.trading_calendar.minute_to_session_label(start_day),
self.trading_calendar.minute_to_session_label(end_day)
)
)

self.writer.write_cols(sid, dts, cols)

self.assertEqual(
Expand Down
22 changes: 11 additions & 11 deletions tests/data/test_us_equity_pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
WithBcolzEquityDailyBarReader,
ZiplineTestCase,
)
from zipline.utils.calendars import get_calendar

TEST_CALENDAR_START = Timestamp('2015-06-01', tz='UTC')
TEST_CALENDAR_STOP = Timestamp('2015-06-30', tz='UTC')
Expand Down Expand Up @@ -97,16 +96,17 @@ def make_equity_daily_bar_data(cls):
@classmethod
def init_class_fixtures(cls):
super(BcolzDailyBarTestCase, cls).init_class_fixtures()
cls.trading_days = get_calendar('NYSE').trading_days(
TEST_CALENDAR_START, TEST_CALENDAR_STOP
).index
cls.sessions = cls.trading_calendar.sessions_in_range(
cls.trading_calendar.minute_to_session_label(TEST_CALENDAR_START),
cls.trading_calendar.minute_to_session_label(TEST_CALENDAR_STOP)
)

@property
def assets(self):
return EQUITY_INFO.index

def trading_days_between(self, start, end):
return self.trading_days[self.trading_days.slice_indexer(start, end)]
return self.sessions[self.sessions.slice_indexer(start, end)]

def asset_start(self, asset_id):
return asset_start(EQUITY_INFO, asset_id)
Expand Down Expand Up @@ -181,14 +181,14 @@ def test_write_attrs(self):
expected_calendar_offset,
)
assert_index_equal(
self.trading_days,
self.sessions,
DatetimeIndex(result.attrs['calendar'], tz='UTC'),
)

def test_read_first_trading_day(self):
self.assertEqual(
self.bcolz_equity_daily_bar_reader.first_trading_day,
self.trading_days[0],
self.sessions[0],
)

def _check_read_results(self, columns, assets, start_date, end_date):
Expand Down Expand Up @@ -234,7 +234,7 @@ def test_start_on_asset_start(self):
columns,
self.assets,
start_date=self.asset_start(asset),
end_date=self.trading_days[-1],
end_date=self.sessions[-1],
)

def test_start_on_asset_end(self):
Expand All @@ -248,7 +248,7 @@ def test_start_on_asset_end(self):
columns,
self.assets,
start_date=self.asset_end(asset),
end_date=self.trading_days[-1],
end_date=self.sessions[-1],
)

def test_end_on_asset_start(self):
Expand All @@ -261,7 +261,7 @@ def test_end_on_asset_start(self):
self._check_read_results(
columns,
self.assets,
start_date=self.trading_days[0],
start_date=self.sessions[0],
end_date=self.asset_start(asset),
)

Expand All @@ -275,7 +275,7 @@ def test_end_on_asset_end(self):
self._check_read_results(
columns,
self.assets,
start_date=self.trading_days[0],
start_date=self.sessions[0],
end_date=self.asset_end(asset),
)

Expand Down
8 changes: 4 additions & 4 deletions tests/finance/test_slippage.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ def test_volume_share_slippage(self):
start=normalize_date(self.minutes[0]),
end=normalize_date(self.minutes[-1])
)
with tmp_bcolz_equity_minute_bar_reader(self.trading_schedule, days, assets) \
with tmp_bcolz_equity_minute_bar_reader(self.trading_calendar, days, assets) \
as reader:
data_portal = DataPortal(
self.env.asset_finder, self.trading_schedule,
self.env.asset_finder, self.trading_calendar,
first_trading_day=reader.first_trading_day,
equity_minute_reader=reader,
)
Expand Down Expand Up @@ -481,10 +481,10 @@ def test_orders_stop(self, name, order_data, event_data, expected):
start=normalize_date(self.minutes[0]),
end=normalize_date(self.minutes[-1])
)
with tmp_bcolz_equity_minute_bar_reader(self.trading_schedule, days, assets) \
with tmp_bcolz_equity_minute_bar_reader(self.trading_calendar, days, assets) \
as reader:
data_portal = DataPortal(
self.env.asset_finder, self.trading_schedule,
self.env.asset_finder, self.trading_calendar,
first_trading_day=reader.first_trading_day,
equity_minute_reader=reader,
)
Expand Down
6 changes: 3 additions & 3 deletions tests/pipeline/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
ExplodingObject,
tmp_asset_finder,
)
from zipline.testing.fixtures import ZiplineTestCase, WithTradingSchedule
from zipline.testing.fixtures import ZiplineTestCase, WithTradingCalendar

from zipline.utils.functional import dzip_exact
from zipline.utils.pandas_utils import explode
Expand Down Expand Up @@ -50,14 +50,14 @@ def method(self, *args, **kwargs):
with_default_shape = with_defaults(shape=lambda self: self.default_shape)


class BasePipelineTestCase(WithTradingSchedule, ZiplineTestCase):
class BasePipelineTestCase(WithTradingCalendar, ZiplineTestCase):

@classmethod
def init_class_fixtures(cls):
super(BasePipelineTestCase, cls).init_class_fixtures()

cls.__calendar = date_range('2014', '2015',
freq=cls.trading_schedule.day)
freq=cls.trading_calendar.day)
cls.__assets = assets = Int64Index(arange(1, 20))
cls.__tmp_finder_ctx = tmp_asset_finder(
equities=make_simple_equity_info(
Expand Down
20 changes: 10 additions & 10 deletions tests/pipeline/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ def init_class_fixtures(cls):
cls.dates = date_range(
cls.start,
cls.end,
freq=cls.trading_schedule.day,
freq=cls.trading_calendar.day,
tz='UTC',
)
cls.assets = cls.asset_finder.retrieve_all(cls.asset_ids)
Expand Down Expand Up @@ -886,7 +886,7 @@ def make_equity_info(cls):
cls.equity_info = ret = make_rotating_equity_info(
num_assets=6,
first_start=cls.first_asset_start,
frequency=cls.trading_schedule.day,
frequency=cls.trading_calendar.day,
periods_between_starts=4,
asset_lifetime=8,
)
Expand Down Expand Up @@ -941,15 +941,15 @@ def write_nans(self, df):
def test_SMA(self):
engine = SimplePipelineEngine(
lambda column: self.pipeline_loader,
self.trading_schedule.all_execution_days,
self.trading_calendar.all_sessions,
self.asset_finder,
)
window_length = 5
asset_ids = self.all_asset_ids
dates = date_range(
self.first_asset_start + self.trading_schedule.day,
self.first_asset_start + self.trading_calendar.day,
self.last_asset_end,
freq=self.trading_schedule.day,
freq=self.trading_calendar.day,
)
dates_to_test = dates[window_length:]

Expand All @@ -969,7 +969,7 @@ def test_SMA(self):
# **previous** day's data.
expected_raw = rolling_mean(
expected_bar_values_2d(
dates - self.trading_schedule.day,
dates - self.trading_calendar.day,
self.equity_info,
'close',
),
Expand All @@ -995,15 +995,15 @@ def test_drawdown(self):
# valuable.
engine = SimplePipelineEngine(
lambda column: self.pipeline_loader,
self.trading_schedule.all_execution_days,
self.trading_calendar.all_sessions,
self.asset_finder,
)
window_length = 5
asset_ids = self.all_asset_ids
dates = date_range(
self.first_asset_start + self.trading_schedule.day,
self.first_asset_start + self.trading_calendar.day,
self.last_asset_end,
freq=self.trading_schedule.day,
freq=self.trading_calendar.day,
)
dates_to_test = dates[window_length:]

Expand Down Expand Up @@ -1039,7 +1039,7 @@ class ParameterizedFactorTestCase(WithTradingEnvironment, ZiplineTestCase):
@classmethod
def init_class_fixtures(cls):
super(ParameterizedFactorTestCase, cls).init_class_fixtures()
day = cls.trading_schedule.day
day = cls.trading_calendar.day

cls.dates = dates = date_range(
'2015-02-01',
Expand Down
21 changes: 10 additions & 11 deletions tests/pipeline/test_frameload.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,21 @@
from zipline.pipeline.loaders.frame import (
DataFrameLoader,
)
from zipline.utils.calendars import default_nyse_schedule


trading_day = default_nyse_schedule.day
from zipline.utils.calendars import get_calendar


class DataFrameLoaderTestCase(TestCase):

def setUp(self):
self.trading_day = get_calendar("NYSE").day

self.nsids = 5
self.ndates = 20

self.sids = Int64Index(range(self.nsids))
self.dates = DatetimeIndex(
start='2014-01-02',
freq=trading_day,
freq=self.trading_day,
periods=self.ndates,
)

Expand Down Expand Up @@ -161,17 +160,17 @@ def test_adjustments(self):
},
{ # Date Before Known Data
'sid': 2,
'start_date': self.dates[0] - (2 * trading_day),
'end_date': self.dates[0] - trading_day,
'apply_date': self.dates[0] - trading_day,
'start_date': self.dates[0] - (2 * self.trading_day),
'end_date': self.dates[0] - self.trading_day,
'apply_date': self.dates[0] - self.trading_day,
'value': -9999.0,
'kind': OVERWRITE,
},
{ # Date After Known Data
'sid': 2,
'start_date': self.dates[-1] + trading_day,
'end_date': self.dates[-1] + (2 * trading_day),
'apply_date': self.dates[-1] + (3 * trading_day),
'start_date': self.dates[-1] + self.trading_day,
'end_date': self.dates[-1] + (2 * self.trading_day),
'apply_date': self.dates[-1] + (3 * self.trading_day),
'value': -9999.0,
'kind': OVERWRITE,
},
Expand Down
Loading

0 comments on commit 6fb4923

Please sign in to comment.