PERF: Remove module-scope calendar creations.

Remove module scope invocations of `get_calendar('NYSE')`, which cuts
zipline import time in half on my machine. This make the zipline CLI
noticeably more responsive, and it reduces memory consumed at import
time from 130MB to 90MB.

Before:

$ time python -c 'import zipline'

real    0m1.262s
user    0m1.128s
sys     0m0.120s

After:

$ time python -c 'import zipline'

real    0m0.676s
user    0m0.536s
sys     0m0.132s
This commit is contained in:
Scott Sanderson
2016-09-06 09:57:23 -04:00
parent 9a301dc59b
commit 1ca23f2583
10 changed files with 330 additions and 107 deletions
@@ -0,0 +1,95 @@
"""
Tests for TradingCalendarDispatcher.
"""
from zipline.errors import (
CalendarNameCollision,
CyclicCalendarAlias,
InvalidCalendarName,
)
from zipline.testing import ZiplineTestCase
from zipline.utils.calendars.calendar_utils import TradingCalendarDispatcher
from zipline.utils.calendars.exchange_calendar_ice import ICEExchangeCalendar
class CalendarAliasTestCase(ZiplineTestCase):
@classmethod
def init_class_fixtures(cls):
super(CalendarAliasTestCase, cls).init_class_fixtures()
# Make a calendar once so that we don't spend time in every test
# instantiating calendars.
cls.dispatcher_kwargs = dict(
calendars={'ICE': ICEExchangeCalendar()},
calendar_factories={},
aliases={
'ICE_ALIAS': 'ICE',
'ICE_ALIAS_ALIAS': 'ICE_ALIAS',
},
)
def init_instance_fixtures(self):
super(CalendarAliasTestCase, self).init_instance_fixtures()
self.dispatcher = TradingCalendarDispatcher(
# Make copies here so that tests that mutate the dispatcher dicts
# are isolated from one another.
**{k: v.copy() for k, v in self.dispatcher_kwargs.items()}
)
def test_follow_alias_chain(self):
self.assertIs(
self.dispatcher.get_calendar('ICE'),
self.dispatcher.get_calendar('ICE_ALIAS'),
)
self.assertIs(
self.dispatcher.get_calendar('ICE'),
self.dispatcher.get_calendar('ICE_ALIAS_ALIAS'),
)
def test_add_new_aliases(self):
with self.assertRaises(InvalidCalendarName):
self.dispatcher.get_calendar('NOT_ICE')
self.dispatcher.register_calendar_alias('NOT_ICE', 'ICE')
self.assertIs(
self.dispatcher.get_calendar('ICE'),
self.dispatcher.get_calendar('NOT_ICE'),
)
self.dispatcher.register_calendar_alias(
'ICE_ALIAS_ALIAS_ALIAS',
'ICE_ALIAS_ALIAS'
)
self.assertIs(
self.dispatcher.get_calendar('ICE'),
self.dispatcher.get_calendar('ICE_ALIAS_ALIAS_ALIAS'),
)
def test_remove_aliases(self):
self.dispatcher.deregister_calendar('ICE_ALIAS_ALIAS')
with self.assertRaises(InvalidCalendarName):
self.dispatcher.get_calendar('ICE_ALIAS_ALIAS')
def test_reject_alias_that_already_exists(self):
with self.assertRaises(CalendarNameCollision):
self.dispatcher.register_calendar_alias('ICE', 'NOT_ICE')
with self.assertRaises(CalendarNameCollision):
self.dispatcher.register_calendar_alias('ICE_ALIAS', 'NOT_ICE')
def test_allow_alias_override_with_force(self):
self.dispatcher.register_calendar_alias('ICE', 'NOT_ICE', force=True)
with self.assertRaises(InvalidCalendarName):
self.dispatcher.get_calendar('ICE')
def test_reject_cyclic_aliases(self):
add_alias = self.dispatcher.register_calendar_alias
add_alias('A', 'B')
add_alias('B', 'C')
with self.assertRaises(CyclicCalendarAlias) as e:
add_alias('C', 'A')
expected = "Cycle in calendar aliases: ['C' -> 'A' -> 'B' -> 'C']"
self.assertEqual(str(e.exception), expected)
+2 -2
View File
@@ -155,7 +155,7 @@ class BundleCoreTestCase(WithInstanceTmpDir,
@self.register(
'bundle',
calendar=calendar,
calendar_name='NYSE',
start_session=self.START_DATE,
end_session=self.END_DATE,
)
@@ -369,7 +369,7 @@ class BundleCoreTestCase(WithInstanceTmpDir,
"""
if not self.bundles:
@self.register('bundle',
calendar=get_calendar('NYSE'),
calendar_name=('NYSE'),
start_session=pd.Timestamp('2014', tz='UTC'),
end_session=pd.Timestamp('2014', tz='UTC'))
def _(environ,
+4 -3
View File
@@ -5,6 +5,7 @@ import pandas as pd
from toolz import merge
import toolz.curried.operator as op
from zipline import get_calendar
from zipline.data.bundles import ingest, load, bundles
from zipline.data.bundles.quandl import (
format_wiki_url,
@@ -28,9 +29,9 @@ class QuandlBundleTestCase(ZiplineTestCase):
asset_start = pd.Timestamp('2014-01', tz='utc')
asset_end = pd.Timestamp('2015-01', tz='utc')
bundle = bundles['quandl']
calendar = bundle.calendar
start_date = bundle.start_session
end_date = bundle.end_session
calendar = get_calendar(bundle.calendar_name)
start_date = calendar.first_session
end_date = calendar.last_session
api_key = 'ayylmao'
columns = 'open', 'high', 'low', 'close', 'volume'
+1 -1
View File
@@ -157,7 +157,7 @@ class YahooBundleTestCase(WithResponses, ZiplineTestCase):
self.register(
'bundle',
yahoo_equities(self.symbols),
calendar=self.calendar,
calendar_name='NYSE',
start_session=self.asset_start,
end_session=self.asset_end,
)