WIP: Refactors tests to use TradingSchedule

This commit is contained in:
jfkirk
2016-06-08 13:34:19 -04:00
committed by Jean Bredeche
parent c8304e8601
commit 4b7390ac81
17 changed files with 91 additions and 82 deletions
+3 -2
View File
@@ -21,7 +21,7 @@ from zipline.testing import (
from zipline.utils.functional import dzip_exact
from zipline.utils.pandas_utils import explode
from zipline.utils.tradingcalendar import trading_day
from zipline.utils.calendars import default_nyse_schedule
def with_defaults(**default_funcs):
@@ -55,7 +55,8 @@ class BasePipelineTestCase(TestCase):
@classmethod
def setUpClass(cls):
cls.__calendar = date_range('2014', '2015', freq=trading_day)
cls.__calendar = date_range('2014', '2015',
freq=default_nyse_schedule.day)
cls.__assets = assets = Int64Index(arange(1, 20))
cls.__tmp_finder_ctx = tmp_asset_finder(
equities=make_simple_equity_info(
+6 -5
View File
@@ -3211,7 +3211,7 @@ class TestOrderCancelation(WithDataPortal,
sim_params=SimulationParameters(
period_start=self.sim_params.period_start,
period_end=self.sim_params.period_end,
trading_schedule=self.env,
trading_schedule=default_nyse_schedule,
data_frequency=data_frequency,
emission_rate='minute' if minute_emission else 'daily'
)
@@ -3401,6 +3401,7 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
@classmethod
def init_class_fixtures(cls):
super(TestEquityAutoClose, cls).init_class_fixtures()
trading_days = default_nyse_schedule.all_execution_days
start_date = pd.Timestamp('2015-01-05', tz='UTC')
start_date_loc = trading_days.get_loc(start_date)
test_duration = 7
@@ -3416,7 +3417,7 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
num_assets=3,
start_date=self.test_days[0],
first_end=self.first_asset_expiration,
frequency=trading_day,
frequency=default_nyse_schedule.day,
periods_between_ends=2,
auto_close_delta=auto_close_delta,
)
@@ -3578,7 +3579,7 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
Make sure that after an equity gets delisted, our portfolio holds the
correct number of equities and correct amount of cash.
"""
auto_close_delta = trading_day * auto_close_lag
auto_close_delta = default_nyse_schedule.day * auto_close_lag
resources = self.make_data(auto_close_delta, 'daily', capital_base)
assets = resources.assets
@@ -3738,7 +3739,7 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
canceled. Unless an equity is auto closed, any open orders for that
equity will persist indefinitely.
"""
auto_close_delta = trading_day
auto_close_delta = default_nyse_schedule.day
resources = self.make_data(auto_close_delta, 'daily')
env = resources.env
assets = resources.assets
@@ -3810,7 +3811,7 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
)
def test_minutely_delisted_equities(self):
resources = self.make_data(trading_day, 'minute')
resources = self.make_data(default_nyse_schedule.day, 'minute')
env = resources.env
assets = resources.assets
+8 -7
View File
@@ -19,6 +19,7 @@ from zipline.testing.fixtures import (
ZiplineTestCase,
)
from zipline.zipline_warnings import ZiplineDeprecationWarning
from zipline.utils.calendars import default_nyse_schedule
simple_algo = """
from zipline.api import sid, order
@@ -124,7 +125,7 @@ class TestAPIShim(WithDataPortal, WithSimParams, ZiplineTestCase):
def make_minute_bar_data(cls):
for sid in cls.sids:
yield sid, create_minute_df_for_asset(
cls.env,
default_nyse_schedule,
cls.SIM_PARAMS_START,
cls.SIM_PARAMS_END,
)
@@ -133,7 +134,7 @@ class TestAPIShim(WithDataPortal, WithSimParams, ZiplineTestCase):
def make_daily_bar_data(cls):
for sid in cls.sids:
yield sid, create_daily_df_for_asset(
cls.env,
default_nyse_schedule,
cls.SIM_PARAMS_START,
cls.SIM_PARAMS_END,
)
@@ -179,10 +180,10 @@ class TestAPIShim(WithDataPortal, WithSimParams, ZiplineTestCase):
similar) and the new data API(data.current(sid(N), field) and
similar) hit the same code paths on the DataPortal.
"""
test_start_minute = self.env.market_minutes_for_day(
test_start_minute = default_nyse_schedule.execution_minutes_for_day(
self.sim_params.trading_days[0]
)[1]
test_end_minute = self.env.market_minutes_for_day(
test_end_minute = default_nyse_schedule.execution_minutes_for_day(
self.sim_params.trading_days[0]
)[-1]
bar_data = BarData(
@@ -260,7 +261,7 @@ class TestAPIShim(WithDataPortal, WithSimParams, ZiplineTestCase):
period_start=test_start_minute,
period_end=test_end_minute,
data_frequency="minute",
env=self.env
trading_schedule=default_nyse_schedule,
)
history_algorithm = self.create_algo(
@@ -381,7 +382,7 @@ class TestAPIShim(WithDataPortal, WithSimParams, ZiplineTestCase):
capital_base=self.sim_params.capital_base,
data_frequency=self.sim_params.data_frequency,
emission_rate=self.sim_params.emission_rate,
env=self.env,
trading_schedule=default_nyse_schedule,
)
algo = self.create_algo(history_algo,
@@ -424,7 +425,7 @@ class TestAPIShim(WithDataPortal, WithSimParams, ZiplineTestCase):
period_start=self.sim_params.trading_days[8],
period_end=self.sim_params.trading_days[-1],
data_frequency="minute",
env=self.env
trading_schedule=default_nyse_schedule,
)
algo = self.create_algo(simple_transforms_algo,
+2 -2
View File
@@ -439,8 +439,8 @@ class TestMinuteBarData(WithBarDataChecks,
def test_can_trade_at_midnight(self):
# make sure that if we use `can_trade` at midnight, we don't pretend
# we're in the previous day's last minute
the_day_after = self.env.next_trading_day(
self.bcolz_minute_bar_days[-1],
the_day_after = self.trading_schedule.next_execution_day(
self.bcolz_minute_bar_days[-1]
)
bar_data = BarData(self.data_portal, lambda: the_day_after, "minute")
+5 -3
View File
@@ -16,6 +16,7 @@ from pandas.tslib import Timedelta
from zipline.data.data_portal import DataPortal
from zipline.testing.fixtures import WithTradingEnvironment, ZiplineTestCase
from zipline.utils.calendars import default_nyse_schedule
import pandas as pd
@@ -26,7 +27,8 @@ class TestDataPortal(WithTradingEnvironment, ZiplineTestCase):
def init_instance_fixtures(self):
super(TestDataPortal, self).init_instance_fixtures()
self.data_portal = DataPortal(self.env, first_trading_day=None)
self.data_portal = DataPortal(self.env, default_nyse_schedule,
first_trading_day=None)
def test_bar_count_for_simple_transforms(self):
# July 2015
@@ -40,7 +42,7 @@ class TestDataPortal(WithTradingEnvironment, ZiplineTestCase):
# half an hour into july 9, getting a 4-"day" window should get us
# all the minutes of 7/6, 7/7, 7/8, and 31 minutes of 7/9
july_9_dt = self.env.get_open_and_close(
july_9_dt = default_nyse_schedule.start_and_end(
pd.Timestamp("2015-07-09")
)[0] + Timedelta("30 minutes")
@@ -63,7 +65,7 @@ class TestDataPortal(WithTradingEnvironment, ZiplineTestCase):
# half an hour into nov 30, getting a 4-"day" window should get us
# all the minutes of 11/24, 11/25, 11/27 (half day!), and 31 minutes
# of 11/30
nov_30_dt = self.env.get_open_and_close(
nov_30_dt = default_nyse_schedule.start_and_end(
pd.Timestamp("2015-11-30")
)[0] + Timedelta("30 minutes")
+2 -16
View File
@@ -280,7 +280,8 @@ class FinanceTestCase(WithLogger,
else:
alternator = 1
tracker = PerformanceTracker(sim_params, self.env)
tracker = PerformanceTracker(sim_params, default_nyse_schedule,
self.env)
# replicate what tradesim does by going through every minute or day
# of the simulation and processing open orders each time
@@ -558,18 +559,3 @@ class TradingEnvironmentTestCase(WithLogger,
self.assertTrue(all(today == minutes[:31]))
self.assertTrue(all(friday == minutes[31:421]))
self.assertTrue(all(thursday == minutes[421:]))
def test_min_date(self):
min_date = pd.Timestamp('2016-03-04', tz='UTC')
env = TradingEnvironment(min_date=min_date)
self.assertGreaterEqual(env.first_trading_day, min_date)
self.assertGreaterEqual(env.treasury_curves.index[0],
min_date)
def test_max_date(self):
max_date = pd.Timestamp('2008-08-01', tz='UTC')
env = TradingEnvironment(max_date=max_date)
self.assertLessEqual(env.treasury_curves.index[-1],
max_date)
+3 -2
View File
@@ -1136,6 +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
first_day_minutes = default_nyse_schedule.execution_minutes_for_day(
self.TRADING_START_DT
)
@@ -1670,8 +1671,8 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
)[self.ASSET1]
# Use a minute to force minute mode.
first_minute = default_nyse_schedule.open_and_closes.market_open[
self.TRADING_START_DT]
first_minute = \
default_nyse_schedule.schedule.market_open[self.TRADING_START_DT]
with self.assertRaisesRegexp(HistoryWindowStartsBeforeData, exp_msg):
self.data_portal.get_history_window(
+1 -3
View File
@@ -12,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from collections import namedtuple
import datetime
from functools import partial
from inspect import isabstract
@@ -25,7 +24,6 @@ import pandas as pd
from six import iteritems
from six.moves import range, map
from zipline.finance.trading import TradingEnvironment
from zipline.testing import subtest, parameter_space
import zipline.utils.events
from zipline.utils.calendars import get_calendar
@@ -213,7 +211,7 @@ def minutes_for_days(ordered_days=False):
# optimization in AfterOpen and BeforeClose, we rely on the fact that
# the clock only ever moves forward in a simulation. For those cases,
# we guarantee that the list of trading days we test is ordered.
ordered_day_list = random.sample(list(env.trading_days), 500)
ordered_day_list = random.sample(list(cal.all_trading_days), 500)
ordered_day_list.sort()
def day_picker(day):
+5 -2
View File
@@ -906,7 +906,8 @@ class TradingAlgorithm(object):
url,
pre_func,
post_func,
self.trading_environment,
self.asset_finder,
self.trading_schedule.day,
self.sim_params.period_start,
self.sim_params.period_end,
date_column,
@@ -1945,7 +1946,9 @@ class TradingAlgorithm(object):
# If we are in before_trading_start, we need to get the window
# as of the previous market minute
adjusted_dt = \
self.data_portal.env.previous_market_minute(self.datetime)
self.data_portal.trading_schedule.previous_execution_minute(
self.datetime
)
window = self.data_portal.get_history_window(
assets,
+16 -11
View File
@@ -1018,12 +1018,13 @@ class DataPortal(object):
tds = self.trading_schedule.all_execution_days
end_loc = tds.get_loc(end_date)
start_loc = end_loc - bar_count + 1
start_dt = tds[start_loc]
if start_dt < self._first_trading_day:
if start_loc < self._first_trading_day_loc:
raise HistoryWindowStartsBeforeData(
first_trading_day=self._first_trading_day.date(),
bar_count=bar_count,
suggested_start_day=tds[bar_count].date(),
suggested_start_day=tds[
self._first_trading_day_loc + bar_count
].date(),
)
return tds[start_loc:end_loc + 1]
@@ -1175,12 +1176,14 @@ class DataPortal(object):
mm = self.trading_schedule.all_execution_minutes
end_loc = mm.get_loc(end_dt)
start_loc = end_loc - bar_count + 1
if start_loc < 0:
suggested_start_day = \
(mm[bar_count] + self.trading_schedule.day).date()
if start_loc < self._first_trading_minute_loc:
suggested_start_day = (
mm[
self._first_trading_minute_loc + bar_count
] + self.trading_schedule.day
).date()
raise HistoryWindowStartsBeforeData(
first_trading_day=\
self.trading_schedule.first_execution_day.date(),
first_trading_day=self._first_trading_day.date(),
bar_count=bar_count,
suggested_start_day=suggested_start_day,
)
@@ -1704,11 +1707,13 @@ class DataPortal(object):
previous_day,
)
minutes_count = \
sum(210 if day in self.env.early_closes else 390 for day in days)
minutes_count = sum(
210 if day in self.trading_schedule.early_ends
else 390 for day in days
)
# add the minutes for today
today_open = self.env.get_open_and_close(ending_minute)[0]
today_open = self.trading_schedule.start_and_end(ending_minute)[0]
minutes_count += \
((ending_minute - today_open).total_seconds() // 60) + 1
@@ -384,7 +384,7 @@ class PositionTracker(object):
last_sale_price = data_portal.get_adjusted_value(
asset,
'price',
data_portal.env.previous_market_minute(dt),
data_portal.trading_schedule.previous_execution_minute(dt),
dt,
self.data_frequency
)
+7 -9
View File
@@ -78,8 +78,6 @@ class TradingEnvironment(object):
load=None,
bm_symbol='^GSPC',
exchange_tz="US/Eastern",
min_date=None,
max_date=None,
trading_schedule=default_nyse_schedule,
asset_db_path=':memory:'
):
@@ -94,13 +92,13 @@ class TradingEnvironment(object):
self.bm_symbol,
)
if max_date:
tr_c = self.treasury_curves
# Mask the treasury curves down to the current date.
# In the case of live trading, the last date in the treasury
# curves would be the day before the date considered to be
# 'today'.
self.treasury_curves = tr_c[tr_c.index <= max_date]
#if max_date:
# tr_c = self.treasury_curves
# # Mask the treasury curves down to the current date.
# # In the case of live trading, the last date in the treasury
# # curves would be the day before the date considered to be
# # 'today'.
# self.treasury_curves = tr_c[tr_c.index <= max_date]
self.exchange_tz = exchange_tz
+13 -10
View File
@@ -26,14 +26,14 @@ from zipline.assets import Equity
logger = Logger('Requests Source Logger')
def roll_dts_to_midnight(dts, env):
def roll_dts_to_midnight(dts, trading_day):
if len(dts) == 0:
return dts
return pd.DatetimeIndex(
(dts.tz_convert('US/Eastern') - pd.Timedelta(hours=16)).date,
tz='UTC',
) + env.trading_day
) + trading_day
class FetcherEvent(Event):
@@ -144,7 +144,8 @@ class PandasCSV(with_metaclass(ABCMeta, object)):
def __init__(self,
pre_func,
post_func,
env,
asset_finder,
trading_day,
start_date,
end_date,
date_column,
@@ -175,8 +176,8 @@ class PandasCSV(with_metaclass(ABCMeta, object)):
self.symbol = symbol
self.env = env
self.finder = env.asset_finder
self.finder = asset_finder
self.trading_day = trading_day
self.pre_func = pre_func
self.post_func = post_func
@@ -194,7 +195,7 @@ class PandasCSV(with_metaclass(ABCMeta, object)):
@staticmethod
def parse_date_str_series(format_str, tz, date_str_series, data_frequency,
env):
trading_day):
"""
Efficient parsing for a 1d Pandas/numpy object containing string
representations of dates.
@@ -233,7 +234,7 @@ class PandasCSV(with_metaclass(ABCMeta, object)):
).tz_localize(tz_str).tz_convert('UTC')
if data_frequency == 'daily':
parsed = roll_dts_to_midnight(parsed, env)
parsed = roll_dts_to_midnight(parsed, trading_day)
return parsed
def mask_pandas_args(self, kwargs):
@@ -290,7 +291,7 @@ class PandasCSV(with_metaclass(ABCMeta, object)):
self.timezone,
df[self.date_column],
self.data_frequency,
self.env
self.trading_day,
).values
# ignore rows whose dates we couldn't parse
@@ -456,7 +457,8 @@ class PandasRequestsCSV(PandasCSV):
url,
pre_func,
post_func,
env,
asset_finder,
trading_day,
start_date,
end_date,
date_column,
@@ -488,7 +490,8 @@ class PandasRequestsCSV(PandasCSV):
super(PandasRequestsCSV, self).__init__(
pre_func,
post_func,
env,
asset_finder,
trading_day,
start_date,
end_date,
date_column,
+5 -3
View File
@@ -702,9 +702,11 @@ class FakeDataPortal(DataPortal):
def get_history_window(self, assets, end_dt, bar_count, frequency, field,
ffill=True):
if frequency == "1d":
end_idx = self.env.trading_days.searchsorted(end_dt)
days = \
self.env.trading_days[(end_idx - bar_count + 1):(end_idx + 1)]
end_idx = \
self.trading_schedule.all_execution_days.searchsorted(end_dt)
days = self.trading_schedule.all_execution_days[
(end_idx - bar_count + 1):(end_idx + 1)
]
df = pd.DataFrame(
np.full((bar_count, len(assets)), 100),
-4
View File
@@ -398,8 +398,6 @@ class WithTradingEnvironment(WithAssetFinder):
--------
:class:`zipline.finance.trading.TradingEnvironment`
"""
TRADING_ENV_MIN_DATE = None
TRADING_ENV_MAX_DATE = None
TRADING_ENV_TRADING_SCHEDULE = default_nyse_schedule
@classmethod
@@ -411,8 +409,6 @@ class WithTradingEnvironment(WithAssetFinder):
return TradingEnvironment(
load=cls.make_load_function(),
asset_db_path=cls.asset_finder.engine,
min_date=cls.TRADING_ENV_MIN_DATE,
max_date=cls.TRADING_ENV_MAX_DATE,
trading_schedule=cls.TRADING_ENV_TRADING_SCHEDULE,
)
@@ -280,6 +280,14 @@ class TradingSchedule(object):
"""
raise NotImplementedError()
@abstractproperty
def early_ends(self):
"""
Returns a DatetimeIndex containing the session dates on-which there is
an early end to trading.
"""
raise NotImplementedError()
class ExchangeTradingSchedule(TradingSchedule):
"""
@@ -355,6 +363,10 @@ class ExchangeTradingSchedule(TradingSchedule):
count=count,
step=step)
@property
def early_ends(self):
return self._exchange_calendar.early_closes
class NYSETradingSchedule(ExchangeTradingSchedule):
"""
+2 -2
View File
@@ -348,7 +348,7 @@ class AfterOpen(StatelessRule):
def calculate_dates(self, dt):
# given a dt, find that day's open and period end (open + offset)
self._period_start, self._period_close = \
_static_nyse_cal.get_open_and_close(dt)
_static_nyse_cal.open_and_close(dt)
self._period_end = \
self._period_start + self.offset - self._one_minute
@@ -392,7 +392,7 @@ class BeforeClose(StatelessRule):
def calculate_dates(self, dt):
# given a dt, find that day's close and period start (close - offset)
self._period_end = _static_nyse_cal.get_open_and_close(dt)[1]
self._period_end = _static_nyse_cal.open_and_close(dt)[1]
self._period_start = \
self._period_end - self.offset
self._period_close = self._period_end