ENH: Adds ExchangeCalendar, TradingSchedule, and implementations

Conflicts:
	tests/data/test_minute_bars.py
	tests/data/test_us_equity_pricing.py
	tests/finance/test_slippage.py
	tests/pipeline/test_engine.py
	tests/pipeline/test_us_equity_pricing_loader.py
	tests/serialization_cases.py
	tests/test_algorithm.py
	tests/test_assets.py
	tests/test_bar_data.py
	tests/test_benchmark.py
	tests/test_exception_handling.py
	tests/test_fetcher.py
	tests/test_finance.py
	tests/test_history.py
	tests/test_perf_tracking.py
	tests/test_security_list.py
	tests/utils/test_events.py
	zipline/algorithm.py
	zipline/data/data_portal.py
	zipline/data/us_equity_loader.py
	zipline/errors.py
	zipline/finance/trading.py
	zipline/testing/core.py
	zipline/utils/events.py
This commit is contained in:
jfkirk
2016-06-08 13:34:18 -04:00
committed by Jean Bredeche
parent c9b5979f45
commit c8304e8601
46 changed files with 9709 additions and 1137 deletions
+17 -16
View File
@@ -45,8 +45,7 @@ from zipline.data.minute_bars import (
US_EQUITIES_MINUTES_PER_DAY,
BcolzMinuteWriterColumnMismatch
)
from zipline.finance.trading import TradingEnvironment
from zipline.utils.calendars import get_calendar, default_nyse_schedule
# Calendar is set to cover several half days, to check a case where half
# days would be read out of order in cases of windows which spanned over
@@ -59,15 +58,11 @@ class BcolzMinuteBarTestCase(TestCase):
@classmethod
def setUpClass(cls):
cls.env = TradingEnvironment()
all_market_opens = cls.env.open_and_closes.market_open
all_market_closes = cls.env.open_and_closes.market_close
indexer = all_market_opens.index.slice_indexer(
start=TEST_CALENDAR_START,
end=TEST_CALENDAR_STOP
trading_days = get_calendar('NYSE').trading_days(
TEST_CALENDAR_START, TEST_CALENDAR_STOP
)
cls.market_opens = all_market_opens[indexer]
cls.market_closes = all_market_closes[indexer]
cls.market_opens = trading_days.market_open
cls.market_closes = trading_days.market_close
cls.test_calendar_start = cls.market_opens.index[0]
cls.test_calendar_stop = cls.market_opens.index[-1]
@@ -802,10 +797,12 @@ class BcolzMinuteBarTestCase(TestCase):
data = {sids[0]: data_1, sids[1]: data_2}
start_minute_loc = self.env.market_minutes.get_loc(minutes[0])
minute_locs = [self.env.market_minutes.get_loc(minute) -
start_minute_loc
for minute in minutes]
start_minute_loc = \
default_nyse_schedule.all_execution_minutes.get_loc(minutes[0])
minute_locs = [
default_nyse_schedule.all_execution_minutes.get_loc(minute) \
- start_minute_loc
for minute in minutes]
for i, col in enumerate(columns):
for j, sid in enumerate(sids):
@@ -824,7 +821,9 @@ class BcolzMinuteBarTestCase(TestCase):
'close': arange(1, 781),
'volume': arange(1, 781)
}
dts = array(self.env.minutes_for_days_in_range(start_day, end_day))
dts = array(default_nyse_schedule.execution_minutes_for_days_in_range(
start_day, end_day
))
self.writer.write_cols(sid, dts, cols)
self.assertEqual(
@@ -866,7 +865,9 @@ class BcolzMinuteBarTestCase(TestCase):
'close': arange(1, 601),
'volume': arange(1, 601)
}
dts = array(self.env.minutes_for_days_in_range(start_day, end_day))
dts = array(default_nyse_schedule.execution_minutes_for_days_in_range(
start_day, end_day
))
self.writer.write_cols(sid, dts, cols)
self.assertEqual(
+4 -5
View File
@@ -46,6 +46,7 @@ from zipline.testing.fixtures import (
WithBcolzDailyBarReader,
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')
@@ -96,11 +97,9 @@ class BcolzDailyBarTestCase(WithBcolzDailyBarReader, ZiplineTestCase):
@classmethod
def init_class_fixtures(cls):
super(BcolzDailyBarTestCase, cls).init_class_fixtures()
all_trading_days = cls.env.trading_days
cls.trading_days = all_trading_days[
all_trading_days.get_loc(TEST_CALENDAR_START):
all_trading_days.get_loc(TEST_CALENDAR_STOP) + 1
]
cls.trading_days = get_calendar('NYSE').trading_days(
TEST_CALENDAR_START, TEST_CALENDAR_STOP
).index
@property
def assets(self):
+6 -1
View File
@@ -38,6 +38,7 @@ from zipline.testing.fixtures import (
WithSimParams,
ZiplineTestCase,
)
from zipline.utils.calendars import default_nyse_schedule
class SlippageTestCase(WithSimParams, WithDataPortal, ZiplineTestCase):
@@ -93,7 +94,7 @@ class SlippageTestCase(WithSimParams, WithDataPortal, ZiplineTestCase):
)
with tmp_bcolz_minute_bar_reader(self.env, days, assets) as reader:
data_portal = DataPortal(
self.env,
self.env, default_nyse_schedule,
first_trading_day=reader.first_trading_day,
equity_minute_reader=reader,
)
@@ -482,8 +483,12 @@ class SlippageTestCase(WithSimParams, WithDataPortal, ZiplineTestCase):
)
with tmp_bcolz_minute_bar_reader(self.env, days, assets) as reader:
data_portal = DataPortal(
<<<<<<< HEAD
self.env,
first_trading_day=reader.first_trading_day,
=======
self.env, default_nyse_schedule,
>>>>>>> ENH: Adds ExchangeCalendar, TradingSchedule, and implementations
equity_minute_reader=reader,
)
+5 -4
View File
@@ -85,6 +85,7 @@ from zipline.testing.fixtures import (
ZiplineTestCase,
)
from zipline.utils.memoize import lazyval
from zipline.utils.calendars import default_nyse_schedule
class RollingSumDifference(CustomFactor):
@@ -826,7 +827,7 @@ class FrameInputTestCase(WithTradingEnvironment, ZiplineTestCase):
cls.dates = date_range(
cls.start,
cls.end,
freq=cls.env.trading_day,
freq=default_nyse_schedule.day,
tz='UTC',
)
cls.assets = cls.asset_finder.retrieve_all(cls.asset_ids)
@@ -985,7 +986,7 @@ class SyntheticBcolzTestCase(WithAdjustmentReader,
def test_SMA(self):
engine = SimplePipelineEngine(
lambda column: self.pipeline_loader,
self.env.trading_days,
default_nyse_schedule.all_execution_days,
self.asset_finder,
)
window_length = 5
@@ -1039,7 +1040,7 @@ class SyntheticBcolzTestCase(WithAdjustmentReader,
# valuable.
engine = SimplePipelineEngine(
lambda column: self.pipeline_loader,
self.env.trading_days,
default_nyse_schedule.all_execution_days,
self.asset_finder,
)
window_length = 5
@@ -1083,7 +1084,7 @@ class ParameterizedFactorTestCase(WithTradingEnvironment, ZiplineTestCase):
@classmethod
def init_class_fixtures(cls):
super(ParameterizedFactorTestCase, cls).init_class_fixtures()
day = cls.env.trading_day
day = default_nyse_schedule.day
cls.dates = dates = date_range(
'2015-02-01',
+4 -1
View File
@@ -60,7 +60,7 @@ from zipline.testing.fixtures import (
WithDataPortal,
ZiplineTestCase,
)
from zipline.utils.tradingcalendar import trading_day
from zipline.utils.calendars import default_nyse_schedule
TEST_RESOURCE_PATH = join(
@@ -70,6 +70,9 @@ TEST_RESOURCE_PATH = join(
)
trading_day = default_nyse_schedule.day
def rolling_vwap(df, length):
"Simple rolling vwap implementation for testing"
closes = df['close'].values
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -22,7 +22,7 @@ import zipline.finance.risk as risk
from zipline.utils import factory
from zipline.finance.trading import SimulationParameters, TradingEnvironment
from zipline.utils.calendars import default_nyse_schedule
from . import answer_key
ANSWER_KEY = answer_key.ANSWER_KEY
@@ -51,7 +51,7 @@ class TestRisk(unittest.TestCase):
self.sim_params = SimulationParameters(
period_start=start_date,
period_end=end_date,
env=self.env,
trading_schedule=default_nyse_schedule,
)
self.algo_returns_06 = factory.create_returns_from_list(
@@ -60,7 +60,9 @@ class TestRisk(unittest.TestCase):
)
self.cumulative_metrics_06 = risk.RiskMetricsCumulative(
self.sim_params, env=self.env
self.sim_params,
treasury_curves=self.env.treasury_curves,
trading_schedule=default_nyse_schedule,
)
for dt, returns in answer_key.RETURNS_DATA.iterrows():
+39 -15
View File
@@ -26,7 +26,7 @@ import zipline.finance.risk as risk
from zipline.utils import factory
from zipline.finance.trading import SimulationParameters, TradingEnvironment
from zipline.utils.calendars import default_nyse_schedule
from . import answer_key
from . answer_key import AnswerKey
@@ -60,7 +60,7 @@ class TestRisk(unittest.TestCase):
self.sim_params = SimulationParameters(
period_start=start_date,
period_end=end_date,
env=self.env,
trading_schedule=default_nyse_schedule,
)
self.algo_returns_06 = factory.create_returns_from_list(
@@ -75,7 +75,8 @@ class TestRisk(unittest.TestCase):
self.algo_returns_06,
self.sim_params,
benchmark_returns=self.benchmark_returns_06,
env=self.env,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
)
start_08 = datetime.datetime(
@@ -95,7 +96,7 @@ class TestRisk(unittest.TestCase):
self.sim_params08 = SimulationParameters(
period_start=start_08,
period_end=end_08,
env=self.env,
trading_schedule=default_nyse_schedule,
)
def tearDown(self):
@@ -116,8 +117,9 @@ class TestRisk(unittest.TestCase):
returns.index[0],
returns.index[-1],
returns,
env=self.env,
trading_schedule=default_nyse_schedule,
benchmark_returns=self.env.benchmark_returns,
treasury_curves=self.env.treasury_curves,
)
self.assertEqual(metrics.max_drawdown, 0.505)
@@ -142,7 +144,10 @@ class TestRisk(unittest.TestCase):
def test_trading_days_06(self):
returns = factory.create_returns_from_range(self.sim_params)
metrics = risk.RiskReport(returns, self.sim_params, env=self.env)
metrics = risk.RiskReport(returns, self.sim_params,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
benchmark_returns=self.env.benchmark_returns)
self.assertEqual([x.num_trading_days for x in metrics.year_periods],
[251])
self.assertEqual([x.num_trading_days for x in metrics.month_periods],
@@ -366,7 +371,10 @@ class TestRisk(unittest.TestCase):
def test_benchmark_returns_08(self):
returns = factory.create_returns_from_range(self.sim_params08)
metrics = risk.RiskReport(returns, self.sim_params08, env=self.env)
metrics = risk.RiskReport(returns, self.sim_params08,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
benchmark_returns=self.env.benchmark_returns)
self.assertEqual([round(x.benchmark_period_returns, 3)
for x in metrics.month_periods],
@@ -412,7 +420,10 @@ class TestRisk(unittest.TestCase):
def test_trading_days_08(self):
returns = factory.create_returns_from_range(self.sim_params08)
metrics = risk.RiskReport(returns, self.sim_params08, env=self.env)
metrics = risk.RiskReport(returns, self.sim_params08,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
benchmark_returns=self.env.benchmark_returns)
self.assertEqual([x.num_trading_days for x in metrics.year_periods],
[253])
@@ -421,7 +432,10 @@ class TestRisk(unittest.TestCase):
def test_benchmark_volatility_08(self):
returns = factory.create_returns_from_range(self.sim_params08)
metrics = risk.RiskReport(returns, self.sim_params08, env=self.env)
metrics = risk.RiskReport(returns, self.sim_params08,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
benchmark_returns=self.env.benchmark_returns)
self.assertEqual([round(x.benchmark_volatility, 3)
for x in metrics.month_periods],
@@ -469,7 +483,10 @@ class TestRisk(unittest.TestCase):
def test_treasury_returns_06(self):
returns = factory.create_returns_from_range(self.sim_params)
metrics = risk.RiskReport(returns, self.sim_params, env=self.env)
metrics = risk.RiskReport(returns, self.sim_params,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
benchmark_returns=self.env.benchmark_returns)
self.assertEqual([round(x.treasury_period_return, 4)
for x in metrics.month_periods],
[0.0037,
@@ -533,12 +550,15 @@ class TestRisk(unittest.TestCase):
sim_params90s = SimulationParameters(
period_start=start,
period_end=end,
env=self.env,
trading_schedule=default_nyse_schedule,
)
returns = factory.create_returns_from_range(sim_params90s)
returns = returns[:-10] # truncate the returns series to end mid-month
metrics = risk.RiskReport(returns, sim_params90s, env=self.env)
metrics = risk.RiskReport(returns, sim_params90s,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
benchmark_returns=self.env.benchmark_returns)
total_months = 60
self.check_metrics(metrics, total_months, start)
@@ -546,10 +566,13 @@ class TestRisk(unittest.TestCase):
sim_params = SimulationParameters(
period_start=start_date,
period_end=start_date.replace(year=(start_date.year + years)),
env=self.env,
trading_schedule=default_nyse_schedule,
)
returns = factory.create_returns_from_range(sim_params)
metrics = risk.RiskReport(returns, self.sim_params, env=self.env)
metrics = risk.RiskReport(returns, self.sim_params,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
benchmark_returns=self.env.benchmark_returns)
total_months = years * 12
self.check_metrics(metrics, total_months, start_date)
@@ -636,7 +659,8 @@ class TestRisk(unittest.TestCase):
self.algo_returns_06,
self.sim_params,
benchmark_returns=benchmark_returns,
env=self.env,
trading_schedule=default_nyse_schedule,
treasury_curves=self.env.treasury_curves,
)
for risk_period in chain.from_iterable(itervalues(report.to_dict())):
self.assertIsNone(risk_period['beta'])
+35 -24
View File
@@ -166,7 +166,7 @@ from zipline.utils.control_flow import nullctx
import zipline.utils.events
from zipline.utils.events import date_rules, time_rules, Always
import zipline.utils.factory as factory
from zipline.utils.tradingcalendar import trading_day, trading_days
from zipline.utils.calendars import default_nyse_schedule
# Because test cases appear to reuse some resources.
@@ -826,7 +826,7 @@ def before_trading_start(context, data):
self.sim_params.data_frequency = 'daily'
sim_params = factory.create_simulation_parameters(
num_days=4, env=self.env, data_frequency='daily')
num_days=4, data_frequency='daily')
algo = TestRegisterTransformAlgorithm(
sim_params=sim_params,
@@ -835,7 +835,7 @@ def before_trading_start(context, data):
self.assertEqual(algo.sim_params.data_frequency, 'daily')
sim_params = factory.create_simulation_parameters(
num_days=4, env=self.env, data_frequency='minute')
num_days=4, data_frequency='minute')
algo = TestRegisterTransformAlgorithm(
sim_params=sim_params,
@@ -953,7 +953,7 @@ def before_trading_start(context, data):
period_end=period_end,
capital_base=float("1.0e5"),
data_frequency='minute',
env=env
trading_schedule=default_nyse_schedule,
)
data_portal = create_data_portal(
@@ -961,6 +961,7 @@ def before_trading_start(context, data):
tempdir,
sim_params,
equities.index,
default_nyse_schedule,
)
algo = algo_class(sim_params=sim_params, env=env)
algo.run(data_portal)
@@ -1551,9 +1552,10 @@ def handle_data(context, data):
env=self.env,
)
trades = factory.create_daily_trade_source(
[0], self.sim_params, self.env)
[0], self.sim_params, self.env, default_nyse_schedule)
data_portal = create_data_portal_from_trade_history(
self.env, tempdir, self.sim_params, {0: trades})
self.env, default_nyse_schedule, tempdir, self.sim_params,
{0: trades})
results = test_algo.run(data_portal)
all_txns = [
@@ -1640,7 +1642,7 @@ def handle_data(context, data):
params = SimulationParameters(
period_start=pd.Timestamp("2007-01-03", tz='UTC'),
period_end=pd.Timestamp("2007-01-05", tz='UTC'),
env=self.env
trading_schedule=default_nyse_schedule,
)
# order method shouldn't blow up
@@ -2719,7 +2721,6 @@ class TestTradingControls(WithSimParams, WithDataPortal, ZiplineTestCase):
sim_params = factory.create_simulation_parameters(
start=start,
num_days=4,
env=env,
data_frequency='minute',
)
@@ -2727,7 +2728,8 @@ class TestTradingControls(WithSimParams, WithDataPortal, ZiplineTestCase):
env,
tempdir,
sim_params,
[1]
[1],
default_nyse_schedule,
)
def handle_data(algo, data):
@@ -2848,7 +2850,8 @@ class TestTradingControls(WithSimParams, WithDataPortal, ZiplineTestCase):
env,
tempdir,
self.sim_params,
[0]
[0],
default_nyse_schedule,
)
algo.run(data_portal)
@@ -2862,7 +2865,8 @@ class TestTradingControls(WithSimParams, WithDataPortal, ZiplineTestCase):
env,
tempdir,
self.sim_params,
[0]
[0],
default_nyse_schedule,
)
algo = SetAssetDateBoundsAlgorithm(
sim_params=self.sim_params,
@@ -2881,7 +2885,8 @@ class TestTradingControls(WithSimParams, WithDataPortal, ZiplineTestCase):
env,
tempdir,
self.sim_params,
[0]
[0],
default_nyse_schedule,
)
algo = SetAssetDateBoundsAlgorithm(
sim_params=self.sim_params,
@@ -2907,7 +2912,7 @@ class TestAccountControls(WithDataPortal, WithSimParams, ZiplineTestCase):
[100, 100, 100, 300],
timedelta(days=1),
cls.sim_params,
cls.env,
default_nyse_schedule,
),
},
index=cls.sim_params.trading_days,
@@ -3054,7 +3059,7 @@ class TestFutureFlip(WithSimParams, WithDataPortal, ZiplineTestCase):
[1e9, 1e9, 1e9],
timedelta(days=1),
cls.sim_params,
cls.env
default_nyse_schedule,
),
},
index=cls.sim_params.trading_days,
@@ -3064,7 +3069,7 @@ class TestFutureFlip(WithSimParams, WithDataPortal, ZiplineTestCase):
def test_flip_algo(self):
metadata = {1: {'symbol': 'TEST',
'start_date': self.sim_params.trading_days[0],
'end_date': self.env.next_trading_day(
'end_date': default_nyse_schedule.next_execution_day(
self.sim_params.trading_days[-1]),
'multiplier': 5}}
@@ -3206,7 +3211,7 @@ class TestOrderCancelation(WithDataPortal,
sim_params=SimulationParameters(
period_start=self.sim_params.period_start,
period_end=self.sim_params.period_end,
env=self.env,
trading_schedule=self.env,
data_frequency=data_frequency,
emission_rate='minute' if minute_emission else 'daily'
)
@@ -3419,8 +3424,12 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
sids = asset_info.index
env = self.enter_instance_context(tmp_trading_env(equities=asset_info))
market_opens = env.open_and_closes.market_open.loc[self.test_days]
market_closes = env.open_and_closes.market_close.loc[self.test_days]
market_opens = default_nyse_schedule.schedule.market_open.loc[
self.test_days
]
market_closes = default_nyse_schedule.schedule.market_close.loc[
self.test_days
]
if frequency == 'daily':
dates = self.test_days
@@ -3441,12 +3450,12 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
)
reader = BcolzDailyBarReader(path)
data_portal = DataPortal(
env,
env, default_nyse_schedule,
first_trading_day=reader.first_trading_day,
equity_daily_reader=reader,
)
elif frequency == 'minute':
dates = env.minutes_for_days_in_range(
dates = default_nyse_schedule.execution_minutes_for_days_in_range(
self.test_days[0],
self.test_days[-1],
)
@@ -3471,7 +3480,7 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
)
reader = BcolzMinuteBarReader(self.tmpdir.path)
data_portal = DataPortal(
env,
env, default_nyse_schedule,
first_trading_day=reader.first_trading_day,
equity_minute_reader=reader,
)
@@ -3485,7 +3494,6 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
end=self.test_days[-1],
data_frequency=frequency,
emission_rate=frequency,
env=env,
capital_base=capital_base,
)
@@ -3498,7 +3506,7 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
else:
final_prices = {
asset.sid: trade_data_by_sid[asset.sid].loc[
env.get_open_and_close(asset.end_date)[1]
default_nyse_schedule.start_and_end(asset.end_date)[1]
].close
for asset in assets
}
@@ -3852,6 +3860,9 @@ class TestEquityAutoClose(WithTmpDir, ZiplineTestCase):
expected_cash.extend([after_second_auto_close] * (390 + 390))
expected_position_counts.extend([1] * (390 + 390))
# Check list lengths first to avoid expensive comparison
self.assertEqual(len(algo.cash), len(expected_cash))
# TODO find more efficient way to compare these lists
self.assertEqual(algo.cash, expected_cash)
self.assertEqual(
list(output['ending_cash']),
@@ -3987,7 +3998,7 @@ class TestOrderAfterDelist(WithTradingEnvironment, ZiplineTestCase):
sim_params=SimulationParameters(
period_start=pd.Timestamp("2016-01-06", tz='UTC'),
period_end=pd.Timestamp("2016-01-07", tz='UTC'),
env=self.env,
trading_schedule=default_nyse_schedule,
data_frequency="minute"
)
)
+2 -1
View File
@@ -83,7 +83,7 @@ from zipline.testing.fixtures import (
WithAssetFinder,
ZiplineTestCase,
)
from zipline.utils.tradingcalendar import trading_day
from zipline.utils.calendars import default_nyse_schedule
@contextmanager
@@ -776,6 +776,7 @@ class AssetFinderTestCase(ZiplineTestCase):
def test_compute_lifetimes(self):
num_assets = 4
trading_day = default_nyse_schedule.day
first_start = pd.Timestamp('2015-04-01', tz='UTC')
frame = make_rotating_equity_info(
+28 -18
View File
@@ -28,6 +28,7 @@ from zipline.testing.fixtures import (
WithDataPortal,
ZiplineTestCase,
)
from zipline.utils.calendars import default_nyse_schedule
OHLC = ["open", "high", "low", "close"]
OHLCP = OHLC + ["price"]
@@ -165,8 +166,10 @@ class TestMinuteBarData(WithBarDataChecks,
def test_minute_before_assets_trading(self):
# grab minutes that include the day before the asset start
minutes = self.env.market_minutes_for_day(
self.env.previous_trading_day(self.bcolz_minute_bar_days[0])
minutes = self.trading_schedule.execution_minutes_for_day(
self.trading_schedule.previous_execution_day(
self.bcolz_minute_bar_days[0]
)
)
# this entire day is before either asset has started trading
@@ -192,8 +195,8 @@ class TestMinuteBarData(WithBarDataChecks,
self.assertTrue(asset_value is pd.NaT)
def test_regular_minute(self):
minutes = self.env.market_minutes_for_day(
self.bcolz_minute_bar_days[0],
minutes = self.trading_schedule.execution_minutes_for_day(
self.bcolz_minute_bar_days[0]
)
for idx, minute in enumerate(minutes):
@@ -284,7 +287,7 @@ class TestMinuteBarData(WithBarDataChecks,
asset2_value)
def test_minute_of_last_day(self):
minutes = self.env.market_minutes_for_day(
minutes = self.trading_schedule.execution_minutes_for_day(
self.bcolz_daily_bar_days[-1],
)
@@ -296,12 +299,15 @@ class TestMinuteBarData(WithBarDataChecks,
self.assertTrue(bar_data.can_trade(self.ASSET2))
def test_minute_after_assets_stopped(self):
minutes = self.env.market_minutes_for_day(
self.env.next_trading_day(self.bcolz_minute_bar_days[-1])
minutes = self.trading_schedule.execution_minutes_for_day(
self.trading_schedule.next_execution_day(
self.bcolz_minute_bar_days[-1]
)
)
last_trading_minute = \
self.env.market_minutes_for_day(self.bcolz_minute_bar_days[-1])[-1]
last_trading_minute = self.trading_schedule.execution_minutes_for_day(
self.bcolz_minute_bar_days[-1]
)[-1]
# this entire day is after both assets have stopped trading
for idx, minute in enumerate(minutes):
@@ -341,9 +347,9 @@ class TestMinuteBarData(WithBarDataChecks,
)
# ... but that's it's not applied when using spot value
minutes = self.env.minutes_for_days_in_range(
minutes = self.trading_schedule.execution_minutes_for_days_in_range(
start=self.bcolz_minute_bar_days[0],
end=self.bcolz_minute_bar_days[1],
end=self.bcolz_minute_bar_days[1]
)
for idx, minute in enumerate(minutes):
@@ -356,11 +362,11 @@ class TestMinuteBarData(WithBarDataChecks,
def test_spot_price_is_adjusted_if_needed(self):
# on cls.days[1], the first 9 minutes of ILLIQUID_SPLIT_ASSET are
# missing. let's get them.
day0_minutes = self.env.market_minutes_for_day(
self.bcolz_minute_bar_days[0],
day0_minutes = self.trading_schedule.execution_minutes_for_day(
self.bcolz_minute_bar_days[0]
)
day1_minutes = self.env.market_minutes_for_day(
self.bcolz_minute_bar_days[1],
day1_minutes = self.trading_schedule.execution_minutes_for_day(
self.bcolz_minute_bar_days[1]
)
for idx, minute in enumerate(day0_minutes[-10:-1]):
@@ -604,7 +610,7 @@ class TestDailyBarData(WithBarDataChecks,
def make_daily_bar_data(cls):
for sid in cls.sids:
yield sid, create_daily_df_for_asset(
cls.env,
default_nyse_schedule,
cls.bcolz_daily_bar_days[0],
cls.bcolz_daily_bar_days[-1],
interval=2 - sid % 2
@@ -638,7 +644,9 @@ class TestDailyBarData(WithBarDataChecks,
def test_day_before_assets_trading(self):
# use the day before self.bcolz_daily_bar_days[0]
day = self.env.previous_trading_day(self.bcolz_daily_bar_days[0])
day = self.trading_schedule.previous_execution_day(
self.bcolz_daily_bar_days[0]
)
bar_data = BarData(self.data_portal, lambda: day, "daily")
self.check_internal_consistency(bar_data)
@@ -741,7 +749,9 @@ class TestDailyBarData(WithBarDataChecks,
def test_after_assets_dead(self):
# both assets end on self.day[-1], so let's try the next day
next_day = self.env.next_trading_day(self.bcolz_daily_bar_days[-1])
next_day = self.trading_schedule.next_execution_day(
self.bcolz_daily_bar_days[-1]
)
bar_data = BarData(self.data_portal, lambda: next_day, "daily")
self.check_internal_consistency(bar_data)
+8 -3
View File
@@ -32,6 +32,7 @@ from zipline.testing.fixtures import (
WithSimParams,
ZiplineTestCase,
)
from zipline.utils.calendars import default_nyse_schedule
class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase):
@@ -85,7 +86,7 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase):
days_to_use = self.sim_params.trading_days[1:]
source = BenchmarkSource(
1, self.env, days_to_use, self.data_portal
1, self.env, default_nyse_schedule, days_to_use, self.data_portal
)
# should be the equivalent of getting the price history, then doing
@@ -111,6 +112,7 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase):
BenchmarkSource(
3,
self.env,
default_nyse_schedule,
self.sim_params.trading_days[1:],
self.data_portal
)
@@ -125,6 +127,7 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase):
BenchmarkSource(
3,
self.env,
default_nyse_schedule,
self.sim_params.trading_days[120:],
self.data_portal
)
@@ -138,7 +141,7 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase):
def test_asset_IPOed_same_day(self):
# gotta get some minute data up in here.
# add sid 4 for a couple of days
minutes = self.env.minutes_for_days_in_range(
minutes = default_nyse_schedule.execution_minutes_for_days_in_range(
self.sim_params.trading_days[0],
self.sim_params.trading_days[5]
)
@@ -160,6 +163,7 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase):
source = BenchmarkSource(
2,
self.env,
default_nyse_schedule,
self.sim_params.trading_days,
data_portal
)
@@ -188,7 +192,8 @@ class TestBenchmark(WithDataPortal, WithSimParams, ZiplineTestCase):
with self.assertRaises(InvalidBenchmarkAsset) as exc:
BenchmarkSource(
4, self.env, self.sim_params.trading_days, self.data_portal
4, self.env, default_nyse_schedule,
self.sim_params.trading_days, self.data_portal
)
self.assertEqual("4 cannot be used as the benchmark because it has a "
+301
View File
@@ -0,0 +1,301 @@
#
# Copyright 2016 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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 os.path import (
abspath,
dirname,
join,
)
from unittest import TestCase
import pandas as pd
import pytz
from pandas import (
read_csv,
datetime,
Timestamp,
Timedelta,
date_range,
)
from pandas.util.testing import assert_frame_equal
from zipline.utils.calendars.nyse_exchange_calendar import NYSEExchangeCalendar
class ExchangeCalendarTestBase(object):
# Override in subclasses.
answer_key_filename = None
calendar_class = None
@staticmethod
def load_answer_key(filename):
"""
Load a CSV from tests/resources/calendars/{filename}.csv
"""
fullpath = join(
dirname(abspath(__file__)),
'resources',
'calendars',
filename + '.csv',
)
return read_csv(
fullpath,
index_col=0,
# NOTE: Merely passing parse_dates=True doesn't cause pandas to set
# the dtype correctly, and passing all reasonable inputs to the
# dtype kwarg cause read_csv to barf.
parse_dates=[0, 1, 2],
).tz_localize('UTC')
@classmethod
def setupClass(cls):
cls.answers = cls.load_answer_key(cls.answer_key_filename)
cls.start_date = cls.answers.index[0]
cls.end_date = cls.answers.index[-1]
cls.calendar = cls.calendar_class(cls.start_date, cls.end_date)
def test_calculated_against_csv(self):
assert_frame_equal(self.calendar.schedule, self.answers)
def test_is_open_on_minute(self):
for market_minute in self.answers.market_open:
market_minute_utc = market_minute.tz_localize('UTC')
# The exchange should be classified as open on its first minute
self.assertTrue(
self.calendar.is_open_on_minute(market_minute_utc)
)
# Decrement minute by one, to minute where the market was not open
pre_market = market_minute_utc - pd.Timedelta(minutes=1)
self.assertFalse(
self.calendar.is_open_on_minute(pre_market)
)
def test_open_and_close(self):
for index, row in self.answers.iterrows():
o_and_c = self.calendar.open_and_close(index)
self.assertEqual(o_and_c[0],
row['market_open'].tz_localize('UTC'))
self.assertEqual(o_and_c[1],
row['market_close'].tz_localize('UTC'))
def test_no_nones_from_open_and_close(self):
"""
Ensures that, for all minutes in a week, the open_and_close method
never returns a tuple of Nones.
"""
start_week = Timestamp('11/18/2012 12:00AM', tz='EST')
end_week = start_week + Timedelta(days=7)
minutes_in_week = date_range(start_week, end_week, freq='Min')
for dt in minutes_in_week:
open, close = self.calendar.open_and_close(dt)
self.assertIsNotNone(open, "Open value is None")
self.assertIsNotNone(close, "Close value is None")
# def test_minutes_for_date(self):
# for date in self.answers.index:
# mins_for_date = self.calendar.minutes_for_date(date)
def test_minute_window(self):
for open in self.answers.market_open:
open_tz = open.tz_localize('UTC')
window = self.calendar.minute_window(open_tz, 390, 1)
self.assertEqual(len(window), 390)
class NYSECalendarTestCase(ExchangeCalendarTestBase, TestCase):
answer_key_filename = 'nyse'
calendar_class = NYSEExchangeCalendar
def test_newyears(self):
"""
Check whether tradingcalendar contains certain dates.
"""
# January 2012
# 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
start_dt = Timestamp('1/1/12', tz='UTC')
end_dt = Timestamp('12/31/13', tz='UTC')
trading_days = self.calendar.trading_days(start=start_dt,
end=end_dt)
day_after_new_years_sunday = datetime(
2012, 1, 2, tzinfo=pytz.utc)
self.assertNotIn(day_after_new_years_sunday,
trading_days.index,
"""
If NYE falls on a weekend, {0} the Monday after is a holiday.
""".strip().format(day_after_new_years_sunday)
)
first_trading_day_after_new_years_sunday = datetime(
2012, 1, 3, tzinfo=pytz.utc)
self.assertIn(first_trading_day_after_new_years_sunday,
trading_days.index,
"""
If NYE falls on a weekend, {0} the Tuesday after is the first trading day.
""".strip().format(first_trading_day_after_new_years_sunday)
)
# January 2013
# 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
new_years_day = datetime(
2013, 1, 1, tzinfo=pytz.utc)
self.assertNotIn(new_years_day,
trading_days.index,
"""
If NYE falls during the week, e.g. {0}, it is a holiday.
""".strip().format(new_years_day)
)
first_trading_day_after_new_years = datetime(
2013, 1, 2, tzinfo=pytz.utc)
self.assertIn(first_trading_day_after_new_years,
trading_days.index,
"""
If the day after NYE falls during the week, {0} \
is the first trading day.
""".strip().format(first_trading_day_after_new_years)
)
def test_thanksgiving(self):
"""
Check tradingcalendar Thanksgiving dates.
"""
# November 2005
# 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
start_dt = Timestamp('1/1/05', tz='UTC')
end_dt = Timestamp('12/31/12', tz='UTC')
trading_days = self.calendar.trading_days(start=start_dt,
end=end_dt)
thanksgiving_with_four_weeks = datetime(
2005, 11, 24, tzinfo=pytz.utc)
self.assertNotIn(thanksgiving_with_four_weeks,
trading_days.index,
"""
If Nov has 4 Thursdays, {0} Thanksgiving is the last Thursady.
""".strip().format(thanksgiving_with_four_weeks)
)
# November 2006
# 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
thanksgiving_with_five_weeks = datetime(
2006, 11, 23, tzinfo=pytz.utc)
self.assertNotIn(thanksgiving_with_five_weeks,
trading_days.index,
"""
If Nov has 5 Thursdays, {0} Thanksgiving is not the last week.
""".strip().format(thanksgiving_with_five_weeks)
)
first_trading_day_after_new_years_sunday = datetime(
2012, 1, 3, tzinfo=pytz.utc)
self.assertIn(first_trading_day_after_new_years_sunday,
trading_days.index,
"""
If NYE falls on a weekend, {0} the Tuesday after is the first trading day.
""".strip().format(first_trading_day_after_new_years_sunday)
)
def test_day_after_thanksgiving(self):
# November 2012
# 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
fourth_friday_open = Timestamp('11/23/2012 11:00AM', tz='EST')
fourth_friday = Timestamp('11/23/2012 3:00PM', tz='EST')
self.assertTrue(self.calendar.is_open_on_minute(fourth_friday_open))
self.assertFalse(self.calendar.is_open_on_minute(fourth_friday))
# November 2013
# 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
fifth_friday_open = Timestamp('11/29/2013 11:00AM', tz='EST')
fifth_friday = Timestamp('11/29/2013 3:00PM', tz='EST')
self.assertTrue(self.calendar.is_open_on_minute(fifth_friday_open))
self.assertFalse(self.calendar.is_open_on_minute(fifth_friday))
def test_early_close_independence_day_thursday(self):
"""
Until 2013, the market closed early the Friday after an
Independence Day on Thursday. Since then, the early close is on
Wednesday.
"""
# July 2002
# 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
wednesday_before = Timestamp('7/3/2002 3:00PM', tz='EST')
friday_after_open = Timestamp('7/5/2002 11:00AM', tz='EST')
friday_after = Timestamp('7/5/2002 3:00PM', tz='EST')
self.assertTrue(self.calendar.is_open_on_minute(wednesday_before))
self.assertTrue(self.calendar.is_open_on_minute(friday_after_open))
self.assertFalse(self.calendar.is_open_on_minute(friday_after))
# July 2013
# 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
wednesday_before = Timestamp('7/3/2013 3:00PM', tz='EST')
friday_after_open = Timestamp('7/5/2013 11:00AM', tz='EST')
friday_after = Timestamp('7/5/2013 3:00PM', tz='EST')
self.assertFalse(self.calendar.is_open_on_minute(wednesday_before))
self.assertTrue(self.calendar.is_open_on_minute(friday_after_open))
self.assertTrue(self.calendar.is_open_on_minute(friday_after))
+5 -2
View File
@@ -28,6 +28,7 @@ from zipline.testing.fixtures import (
WithSimParams,
ZiplineTestCase,
)
from zipline.utils.calendars import default_nyse_schedule
from .resources.fetcher_inputs.fetcher_test_data import (
AAPL_CSV_DATA,
AAPL_IBM_CSV_DATA,
@@ -108,7 +109,8 @@ class FetcherTestCase(WithResponses,
data_frequency=data_frequency
)
results = test_algo.run(FetcherDataPortal(self.env))
results = test_algo.run(FetcherDataPortal(self.env,
default_nyse_schedule))
return results
@@ -141,7 +143,8 @@ def handle_data(context, data):
# manually setting data portal and getting generator because we need
# the minutely emission packets here. TradingAlgorithm.run() only
# returns daily packets.
test_algo.data_portal = FetcherDataPortal(self.env)
test_algo.data_portal = FetcherDataPortal(self.env,
default_nyse_schedule)
gen = test_algo.get_generator()
perf_packets = list(gen)
+31 -27
View File
@@ -50,6 +50,10 @@ from zipline.testing.fixtures import (
)
import zipline.utils.factory as factory
from zipline.utils.calendars import (
default_nyse_schedule,
get_calendar,
)
DEFAULT_TIMEOUT = 15 # seconds
EXTENDED_TIMEOUT = 90
@@ -199,7 +203,7 @@ class FinanceTestCase(WithLogger,
data_frequency="minute"
)
minutes = env.market_minute_window(
minutes = default_nyse_schedule.minute_window(
sim_params.first_open,
int((trade_interval.total_seconds() / 60) * trade_count)
+ 100)
@@ -217,8 +221,9 @@ class FinanceTestCase(WithLogger,
}
write_bcolz_minute_data(
env,
env.days_in_range(minutes[0], minutes[-1]),
default_nyse_schedule,
default_nyse_schedule.execution_days_in_range(minutes[0],
minutes[-1]),
tempdir.path,
iteritems(assets),
)
@@ -226,7 +231,7 @@ class FinanceTestCase(WithLogger,
equity_minute_reader = BcolzMinuteBarReader(tempdir.path)
data_portal = DataPortal(
env,
env, default_nyse_schedule,
first_trading_day=equity_minute_reader.first_trading_day,
equity_minute_reader=equity_minute_reader,
)
@@ -254,7 +259,7 @@ class FinanceTestCase(WithLogger,
equity_daily_reader = BcolzDailyBarReader(path)
data_portal = DataPortal(
env,
env, default_nyse_schedule,
first_trading_day=equity_daily_reader.first_trading_day,
equity_daily_reader=equity_daily_reader,
)
@@ -417,25 +422,25 @@ class TradingEnvironmentTestCase(WithLogger,
]
for holiday in holidays:
self.assertTrue(not self.env.is_trading_day(holiday))
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.env.is_trading_day(workday))
self.assertTrue(self.cal.is_open_on_day(workday))
def test_simulation_parameters(self):
env = SimulationParameters(
sp = SimulationParameters(
period_start=datetime(2008, 1, 1, tzinfo=pytz.utc),
period_end=datetime(2008, 12, 31, tzinfo=pytz.utc),
capital_base=100000,
env=self.env,
trading_schedule=default_nyse_schedule,
)
self.assertTrue(env.last_close.month == 12)
self.assertTrue(env.last_close.day == 31)
self.assertTrue(sp.last_close.month == 12)
self.assertTrue(sp.last_close.day == 31)
@timed(DEFAULT_TIMEOUT)
def test_sim_params_days_in_period(self):
@@ -452,7 +457,7 @@ class TradingEnvironmentTestCase(WithLogger,
period_start=datetime(2007, 12, 31, tzinfo=pytz.utc),
period_end=datetime(2008, 1, 7, tzinfo=pytz.utc),
capital_base=100000,
env=self.env,
trading_schedule=default_nyse_schedule,
)
expected_trading_days = (
@@ -473,7 +478,7 @@ class TradingEnvironmentTestCase(WithLogger,
params.trading_days.tolist())
@timed(DEFAULT_TIMEOUT)
def test_market_minute_window(self):
def test_minute_window(self):
# January 2008
# Su Mo Tu We Th Fr Sa
@@ -488,10 +493,10 @@ class TradingEnvironmentTestCase(WithLogger,
# 10:01 AM Eastern on January 7th..
start = us_east.localize(datetime(2008, 1, 7, 10, 1))
utc_start = start.astimezone(utc)
utc_start = pd.Timestamp(start.astimezone(utc))
# Get the next 10 minutes
minutes = self.env.market_minute_window(
minutes = self.cal.minute_window(
utc_start, 10,
)
self.assertEqual(len(minutes), 10)
@@ -499,7 +504,7 @@ class TradingEnvironmentTestCase(WithLogger,
self.assertEqual(minutes[i], utc_start + timedelta(minutes=i))
# Get the previous 10 minutes.
minutes = self.env.market_minute_window(
minutes = self.cal.minute_window(
utc_start, 10, step=-1,
)
self.assertEqual(len(minutes), 10)
@@ -512,14 +517,14 @@ class TradingEnvironmentTestCase(WithLogger,
# 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.env.market_minute_window(
utc_start, 900,
minutes = self.cal.minute_window(
start, 900,
)
today = self.env.market_minutes_for_day(start)[30:]
tomorrow = self.env.market_minutes_for_day(
today = self.cal.minutes_for_date(utc_start)[30:]
tomorrow = self.cal.minutes_for_date(
start + timedelta(days=1)
)
last_day = self.env.market_minutes_for_day(
last_day = self.cal.minutes_for_date(
start + timedelta(days=2))[:150]
self.assertEqual(len(minutes), 900)
@@ -534,17 +539,17 @@ class TradingEnvironmentTestCase(WithLogger,
# 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.env.market_minute_window(
utc_start, 801, step=-1,
minutes = self.cal.minute_window(
start, 801, step=-1,
)
today = self.env.market_minutes_for_day(start)[30::-1]
today = self.cal.minutes_for_date(utc_start)[30::-1]
# minus an extra two days from each of these to account for the two
# weekend days we skipped
friday = self.env.market_minutes_for_day(
friday = self.cal.minutes_for_date(
start + timedelta(days=-3),
)[::-1]
thursday = self.env.market_minutes_for_day(
thursday = self.cal.minutes_for_date(
start + timedelta(days=-4),
)[:9:-1]
@@ -566,6 +571,5 @@ class TradingEnvironmentTestCase(WithLogger,
max_date = pd.Timestamp('2008-08-01', tz='UTC')
env = TradingEnvironment(max_date=max_date)
self.assertLessEqual(env.last_trading_day, max_date)
self.assertLessEqual(env.treasury_curves.index[-1],
max_date)
+33 -26
View File
@@ -24,6 +24,7 @@ from zipline.testing import (
str_to_seconds,
MockDailyBarReader,
)
from zipline.utils.calendars import default_nyse_schedule
from zipline.testing.fixtures import (
WithBcolzMinuteBarReader,
WithDataPortal,
@@ -78,7 +79,7 @@ class WithHistory(WithDataPortal):
@classmethod
def init_class_fixtures(cls):
super(WithHistory, cls).init_class_fixtures()
cls.trading_days = cls.env.days_in_range(
cls.trading_days = default_nyse_schedule.execution_days_in_range(
start=cls.TRADING_START_DT,
end=cls.TRADING_END_DT
)
@@ -455,14 +456,14 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
for sid in sids:
asset = cls.asset_finder.retrieve_asset(sid)
data[sid] = create_minute_df_for_asset(
cls.env,
default_nyse_schedule,
asset.start_date,
asset.end_date,
start_val=2,
)
data[1] = create_minute_df_for_asset(
cls.env,
default_nyse_schedule,
pd.Timestamp('2014-01-03', tz='utc'),
pd.Timestamp('2016-01-30', tz='utc'),
start_val=2,
@@ -509,7 +510,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
))
asset3 = cls.asset_finder.retrieve_asset(3)
data[3] = create_minute_df_for_asset(
cls.env,
default_nyse_schedule,
asset3.start_date,
asset3.end_date,
start_val=2,
@@ -539,7 +540,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
capital_base=float('1.0e5'),
data_frequency='minute',
emission_rate='daily',
env=self.env,
trading_schedule=default_nyse_schedule,
)
test_algo = TradingAlgorithm(
@@ -678,8 +679,10 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
def test_minute_before_assets_trading(self):
# since asset2 and asset3 both started trading on 1/5/2015, let's do
# some history windows that are completely before that
minutes = self.env.market_minutes_for_day(
self.env.previous_trading_day(pd.Timestamp('2015-01-05', tz='UTC'))
minutes = default_nyse_schedule.execution_minutes_for_day(
default_nyse_schedule.previous_execution_day(
pd.Timestamp('2015-01-05', tz='UTC')
)
)[0:60]
for idx, minute in enumerate(minutes):
@@ -726,7 +729,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
# 10 minutes
asset = self.env.asset_finder.retrieve_asset(sid)
minutes = self.env.market_minutes_for_day(
minutes = default_nyse_schedule.execution_minutes_for_day(
pd.Timestamp('2015-01-05', tz='UTC')
)[0:60]
@@ -737,7 +740,9 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
def test_minute_midnight(self):
midnight = pd.Timestamp('2015-01-06', tz='UTC')
last_minute = self.env.previous_open_and_close(midnight)[1]
last_minute = default_nyse_schedule.start_and_end(
default_nyse_schedule.previous_execution_day(midnight)
)[1]
midnight_bar_data = \
BarData(self.data_portal, lambda: midnight, 'minute')
@@ -755,7 +760,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
def test_minute_after_asset_stopped(self):
# SHORT_ASSET's last day was 2015-01-06
# get some history windows that straddle the end
minutes = self.env.market_minutes_for_day(
minutes = default_nyse_schedule.execution_minutes_for_day(
pd.Timestamp('2015-01-07', tz='UTC')
)[0:60]
@@ -850,7 +855,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
# before any of the adjustments, last 10 minutes of jan 5
window1 = self.data_portal.get_history_window(
[asset],
self.env.get_open_and_close(jan5)[1],
default_nyse_schedule.start_and_end(jan5)[1],
10,
'1m',
'close'
@@ -1099,20 +1104,21 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
def test_minute_different_lifetimes(self):
# at trading start, only asset1 existed
day = self.env.next_trading_day(self.TRADING_START_DT)
day = default_nyse_schedule.next_execution_day(self.TRADING_START_DT)
asset1_minutes = self.env.minutes_for_days_in_range(
asset1_minutes = \
default_nyse_schedule.execution_minutes_for_days_in_range(
start=self.ASSET1.start_date,
end=self.ASSET1.end_date
)
asset1_idx = asset1_minutes.searchsorted(
self.env.get_open_and_close(day)[0]
default_nyse_schedule.start_and_end(day)[0]
)
window = self.data_portal.get_history_window(
[self.ASSET1, self.ASSET2],
self.env.get_open_and_close(day)[0],
default_nyse_schedule.start_and_end(day)[0],
100,
'1m',
'close'
@@ -1130,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
first_day_minutes = self.env.market_minutes_for_day(
first_day_minutes = default_nyse_schedule.execution_minutes_for_day(
self.TRADING_START_DT
)
exp_msg = (
@@ -1150,7 +1156,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
# January 2015 has both daily and minute data for ASSET2
day = pd.Timestamp('2015-01-07', tz='UTC')
minutes = self.env.market_minutes_for_day(day)
minutes = default_nyse_schedule.execution_minutes_for_day(day)
# minute data, baseline:
# Jan 5: 2 to 391
@@ -1214,7 +1220,7 @@ class MinuteEquityHistoryTestCase(WithHistory, ZiplineTestCase):
# January 2015 has both daily and minute data for ASSET2
day = pd.Timestamp('2015-01-08', tz='UTC')
minutes = self.env.market_minutes_for_day(day)
minutes = default_nyse_schedule.execution_minutes_for_day(day)
# minute data, baseline:
# Jan 5: 2 to 391
@@ -1333,7 +1339,8 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
@classmethod
def create_df_for_asset(cls, start_day, end_day, interval=1,
force_zeroes=False):
days = cls.env.days_in_range(start_day, end_day)
days = default_nyse_schedule.execution_days_in_range(start_day,
end_day)
days_count = len(days)
# default to 2 because the low array subtracts 1, and we don't
@@ -1362,7 +1369,7 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
def test_daily_before_assets_trading(self):
# asset2 and asset3 both started trading in 2015
days = self.env.days_in_range(
days = default_nyse_schedule.execution_days_in_range(
start=pd.Timestamp('2014-12-15', tz='UTC'),
end=pd.Timestamp('2014-12-18', tz='UTC'),
)
@@ -1400,9 +1407,9 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
# get the first 30 days of 2015
jan5 = pd.Timestamp('2015-01-04')
days = self.env.days_in_range(
days = default_nyse_schedule.execution_days_in_range(
start=jan5,
end=self.env.add_trading_days(30, jan5)
end=default_nyse_schedule.add_execution_days(30, jan5)
)
for idx, day in enumerate(days):
@@ -1445,7 +1452,7 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
def test_daily_after_asset_stopped(self):
# SHORT_ASSET trades on 1/5, 1/6, that's it.
days = self.env.days_in_range(
days = default_nyse_schedule.execution_days_in_range(
start=pd.Timestamp('2015-01-07', tz='UTC'),
end=pd.Timestamp('2015-01-08', tz='UTC')
)
@@ -1637,7 +1644,7 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
# trading_start is 2/3/2014
# get a history window that starts before that, and ends after that
second_day = self.env.next_trading_day(self.TRADING_START_DT)
second_day = default_nyse_schedule.next_execution_day(self.TRADING_START_DT)
exp_msg = (
'History window extends before 2014-01-03. To use this history '
@@ -1663,7 +1670,7 @@ class DailyEquityHistoryTestCase(WithHistory, ZiplineTestCase):
)[self.ASSET1]
# Use a minute to force minute mode.
first_minute = self.env.open_and_closes.market_open[
first_minute = default_nyse_schedule.open_and_closes.market_open[
self.TRADING_START_DT]
with self.assertRaisesRegexp(HistoryWindowStartsBeforeData, exp_msg):
@@ -1794,7 +1801,7 @@ class MinuteToDailyAggregationTestCase(WithBcolzMinuteBarReader,
# Set up a fresh data portal for each test, since order of calling
# needs to be tested.
self.equity_daily_aggregator = DailyHistoryAggregator(
self.env.open_and_closes.market_open,
default_nyse_schedule.schedule.market_open,
self.bcolz_minute_bar_reader,
)
+68 -41
View File
@@ -59,6 +59,7 @@ from zipline.testing.fixtures import (
WithTradingEnvironment,
ZiplineTestCase,
)
from zipline.utils.calendars import default_nyse_schedule
logger = logging.getLogger('Test Perf Tracking')
@@ -175,7 +176,9 @@ def calculate_results(sim_params,
splits = splits or {}
commissions = commissions or {}
perf_tracker = perf.PerformanceTracker(sim_params, env)
perf_tracker = perf.PerformanceTracker(sim_params,
default_nyse_schedule,
env)
results = []
@@ -240,7 +243,9 @@ def setup_env_data(env, sim_params, sids, futures_sids=[]):
for sid in sids:
data[sid] = {
"start_date": sim_params.trading_days[0],
"end_date": env.next_trading_day(sim_params.trading_days[-1])
"end_date": default_nyse_schedule.next_execution_day(
sim_params.trading_days[-1]
)
}
env.write_data(equities_data=data)
@@ -249,7 +254,9 @@ def setup_env_data(env, sim_params, sids, futures_sids=[]):
for future_sid in futures_sids:
futures_data[future_sid] = {
"start_date": sim_params.trading_days[0],
"end_date": env.next_trading_day(sim_params.trading_days[-1]),
"end_date": default_nyse_schedule.next_execution_day(
sim_params.trading_days[-1]
),
"multiplier": 100
}
@@ -271,7 +278,9 @@ class TestSplitPerformance(WithSimParams, WithTmpDir, ZiplineTestCase):
def test_multiple_splits(self):
# if multiple positions all have splits at the same time, verify that
# the total leftover cash is correct
perf_tracker = perf.PerformanceTracker(self.sim_params, self.env)
perf_tracker = perf.PerformanceTracker(self.sim_params,
default_nyse_schedule,
self.env)
asset1 = self.asset_finder.retrieve_asset(1)
asset2 = self.asset_finder.retrieve_asset(2)
@@ -300,13 +309,14 @@ class TestSplitPerformance(WithSimParams, WithTmpDir, ZiplineTestCase):
[100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
# set up a long position in sid 1
# 100 shares at $20 apiece = $2000 position
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.tmpdir,
self.sim_params,
{1: events},
@@ -411,7 +421,7 @@ class TestDividendPerformance(WithSimParams,
after = factory.get_next_trading_dt(
before,
timedelta(days=1),
self.env,
default_nyse_schedule,
)
self.assertEqual(after.hour, 13)
@@ -423,7 +433,7 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
@@ -431,7 +441,7 @@ class TestDividendPerformance(WithSimParams,
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -446,6 +456,7 @@ class TestDividendPerformance(WithSimParams,
adjustment_reader = SQLiteAdjustmentReader(dbpath)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: events},
@@ -488,7 +499,7 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
@@ -496,7 +507,7 @@ class TestDividendPerformance(WithSimParams,
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -522,6 +533,7 @@ class TestDividendPerformance(WithSimParams,
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
events,
@@ -562,7 +574,7 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
@@ -570,7 +582,7 @@ class TestDividendPerformance(WithSimParams,
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -586,6 +598,7 @@ class TestDividendPerformance(WithSimParams,
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: events},
@@ -623,7 +636,7 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
@@ -631,7 +644,7 @@ class TestDividendPerformance(WithSimParams,
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -647,6 +660,7 @@ class TestDividendPerformance(WithSimParams,
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: events},
@@ -685,14 +699,14 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
@@ -709,6 +723,7 @@ class TestDividendPerformance(WithSimParams,
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: events},
@@ -745,20 +760,21 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
pay_date = self.sim_params.first_open
# find pay date that is much later.
for i in range(30):
pay_date = factory.get_next_trading_dt(pay_date, oneday, self.env)
pay_date = factory.get_next_trading_dt(pay_date, oneday,
default_nyse_schedule)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -774,6 +790,7 @@ class TestDividendPerformance(WithSimParams,
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: events},
@@ -811,7 +828,7 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
@@ -819,7 +836,7 @@ class TestDividendPerformance(WithSimParams,
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -835,6 +852,7 @@ class TestDividendPerformance(WithSimParams,
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: events},
@@ -869,7 +887,7 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
@@ -877,7 +895,7 @@ class TestDividendPerformance(WithSimParams,
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -893,6 +911,7 @@ class TestDividendPerformance(WithSimParams,
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: events},
@@ -925,7 +944,7 @@ class TestDividendPerformance(WithSimParams,
[100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
dbpath = self.instance_tmpdir.getpath('adjustments.sqlite')
@@ -933,7 +952,7 @@ class TestDividendPerformance(WithSimParams,
writer = SQLiteAdjustmentWriter(
dbpath,
MockDailyBarReader(),
self.env.trading_days,
default_nyse_schedule.all_execution_days,
)
splits = mergers = create_empty_splits_mergers_frame()
dividends = pd.DataFrame({
@@ -942,8 +961,9 @@ class TestDividendPerformance(WithSimParams,
'declared_date': np.array([events[-3].dt], dtype='datetime64[ns]'),
'ex_date': np.array([events[-2].dt], dtype='datetime64[ns]'),
'record_date': np.array([events[0].dt], dtype='datetime64[ns]'),
'pay_date': np.array([self.env.next_trading_day(events[-1].dt)],
dtype='datetime64[ns]'),
'pay_date': np.array(
[default_nyse_schedule.next_execution_day(events[-1].dt)],
dtype='datetime64[ns]'),
})
writer.write(splits, mergers, dividends)
adjustment_reader = SQLiteAdjustmentReader(dbpath)
@@ -957,10 +977,11 @@ class TestDividendPerformance(WithSimParams,
)
sim_params.period_end = events[-1].dt
sim_params.update_internal_from_env(self.env)
sim_params.update_internal_from_trading_schedule(default_nyse_schedule)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
sim_params,
{1: events},
@@ -1049,7 +1070,7 @@ class TestPositionPerformance(WithInstanceTmpDir, ZiplineTestCase):
[100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
trades_2 = factory.create_trade_history(
@@ -1058,11 +1079,12 @@ class TestPositionPerformance(WithInstanceTmpDir, ZiplineTestCase):
[100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: trades_1, 2: trades_2}
@@ -1154,11 +1176,12 @@ class TestPositionPerformance(WithInstanceTmpDir, ZiplineTestCase):
[100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: trades})
@@ -1245,11 +1268,12 @@ class TestPositionPerformance(WithInstanceTmpDir, ZiplineTestCase):
[100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: trades})
@@ -1360,13 +1384,14 @@ single short-sale transaction"""
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
trades_1 = trades[:-2]
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: trades})
@@ -1593,11 +1618,12 @@ cost of sole txn in test"
[100, 100, 100, 100],
oneday,
sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{3: trades}
@@ -1712,11 +1738,12 @@ single short-sale transaction"""
[100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{3: trades}
@@ -1956,11 +1983,12 @@ trade after cover"""
[100, 100, 100, 100, 100, 100, 100, 100, 100, 100],
oneday,
self.sim_params,
env=self.env
trading_schedule=default_nyse_schedule,
)
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: trades})
@@ -2042,13 +2070,14 @@ shares in position"
[100, 100, 100, 100, 100],
oneday,
self.sim_params,
self.env
default_nyse_schedule,
)
trades = factory.create_trade_history(*history_args)
transactions = factory.create_txn_history(*history_args)[:4]
data_portal = create_data_portal_from_trade_history(
self.env,
default_nyse_schedule,
self.instance_tmpdir,
self.sim_params,
{1: trades})
@@ -2167,7 +2196,7 @@ shares in position"
[200, -100, -100, 100, -300, 100, 500, 400],
oneday,
self.sim_params,
self.env
default_nyse_schedule,
)
cost_bases = [10, 10, 0, 8, 9, 9, 13, 13.5]
@@ -2318,9 +2347,7 @@ class TestPositionTracker(WithTradingEnvironment,
Originally this bug was due to np.dot([], []) returning
np.bool_(False)
"""
sim_params = factory.create_simulation_parameters(
num_days=4, env=self.env
)
sim_params = factory.create_simulation_parameters(num_days=4)
pt = perf.PositionTracker(self.env.asset_finder,
sim_params.data_frequency)
+10 -6
View File
@@ -18,6 +18,7 @@ from zipline.utils.security_list import (
SecurityListSet,
load_from_directory,
)
from zipline.utils.calendars import default_nyse_schedule
LEVERAGED_ETFS = load_from_directory('leveraged_etf_list')
@@ -87,7 +88,7 @@ class SecurityListTestCase(WithLogger, ZiplineTestCase):
cls.sim_params = factory.create_simulation_parameters(
start=start,
num_days=4,
env=cls.env
trading_schedule=default_nyse_schedule
)
cls.sim_params2 = sp2 = factory.create_simulation_parameters(
@@ -110,13 +111,15 @@ class SecurityListTestCase(WithLogger, ZiplineTestCase):
tempdir=cls.tempdir,
sim_params=cls.sim_params,
sids=range(0, 5),
trading_schedule=default_nyse_schedule,
)
cls.data_portal2 = create_data_portal(
env=cls.env2,
tempdir=cls.tempdir2,
sim_params=cls.sim_params2,
sids=range(0, 5)
sids=range(0, 5),
trading_schedule=default_nyse_schedule,
)
def test_iterate_over_restricted_list(self):
@@ -212,14 +215,14 @@ class SecurityListTestCase(WithLogger, ZiplineTestCase):
def test_algo_with_rl_violation_after_knowledge_date(self):
sim_params = factory.create_simulation_parameters(
start=list(
LEVERAGED_ETFS.keys())[0] + timedelta(days=7), num_days=5,
env=self.env)
LEVERAGED_ETFS.keys())[0] + timedelta(days=7), num_days=5)
data_portal = create_data_portal(
self.env,
self.tempdir,
sim_params=sim_params,
sids=range(0, 5)
sids=range(0, 5),
trading_schedule=default_nyse_schedule,
)
algo = RestrictedAlgoWithoutCheck(symbol='BZQ',
@@ -270,7 +273,8 @@ class SecurityListTestCase(WithLogger, ZiplineTestCase):
env,
new_tempdir,
sim_params,
range(0, 5)
range(0, 5),
trading_schedule=default_nyse_schedule,
)
algo = RestrictedAlgoWithoutCheck(
+58
View File
@@ -0,0 +1,58 @@
from unittest import TestCase
from pandas import (
Timestamp,
date_range,
)
from zipline.utils.calendars import (
get_calendar,
ExchangeTradingSchedule,
normalize_date,
)
class TestExchangeTradingSchedule(TestCase):
@classmethod
def setUpClass(cls):
cls.nyse_cal = get_calendar('NYSE')
cls.nyse_exchange_schedule = ExchangeTradingSchedule(cal=cls.nyse_cal)
def test_nyse_data_availability_time(self):
"""
Ensure that the NYSE schedule's data availability time is the market
open.
"""
# This is a time on the day after Thanksgiving when the market was open
test_dt = Timestamp('11/23/2012 11:00AM', tz='EST')
test_date = normalize_date(test_dt)
desired_data_time = Timestamp('11/23/2012 9:31AM', tz='EST')
# Get the data availability time from the NYSE schedule
data_time = self.nyse_exchange_schedule.data_availability_time(
date=test_date
)
# Check the schedule answer against the hard-coded answer
self.assertEqual(data_time, desired_data_time,
"Data availability time is not the market open")
def test_nyse_execution_time(self):
"""
Runs a series of times through both the NYSE calendar and NYSE
schedule, ensuring that the schedule and calendar agree.
"""
# Get all of the minutes in a 24-hour day
start_range = Timestamp('11/23/2012 12:00AM', tz='EST')
end_range = Timestamp('11/23/2012 11:59PM', tz='EST')
time_range = date_range(start_range, end_range, freq='Min')
for dt in time_range:
cal_open = self.nyse_cal.is_open_on_minute(dt)
sched_exec = self.nyse_exchange_schedule.is_executing_on_minute(dt)
self.assertEqual(
cal_open, sched_exec,
"Mismatch between schedule: %s and calendar: %s at time %s"
% (cal_open, sched_exec, dt)
)
-265
View File
@@ -1,265 +0,0 @@
#
# Copyright 2013 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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 unittest import TestCase
from zipline.utils import tradingcalendar
from zipline.utils import tradingcalendar_lse
from zipline.utils import tradingcalendar_tse
from zipline.utils import tradingcalendar_bmf
import pytz
import datetime
from zipline.finance.trading import TradingEnvironment
from nose.tools import nottest
class TestTradingCalendar(TestCase):
def test_calendar_vs_environment(self):
"""
test_calendar_vs_environment checks whether the
historical data from yahoo matches our rule based system.
handy, if not canonical, reference:
http://www.chronos-st.org/NYSE_Observed_Holidays-1885-Present.html
"""
env = TradingEnvironment()
bench_days = env.benchmark_returns[tradingcalendar.start:].index
bounds = env.trading_days.slice_locs(start=tradingcalendar.start,
end=bench_days[-1])
env_days = env.trading_days[bounds[0]:bounds[1]]
self.check_days(env_days, bench_days)
@nottest
def test_lse_calendar_vs_environment(self):
env = TradingEnvironment(
bm_symbol='^FTSE',
exchange_tz='Europe/London'
)
env_start_index = \
env.trading_days.searchsorted(tradingcalendar_lse.start)
env_days = env.trading_days[env_start_index:]
cal_days = tradingcalendar_lse.trading_days
self.check_days(env_days, cal_days)
@nottest
def test_tse_calendar_vs_environment(self):
env = TradingEnvironment(
bm_symbol='^GSPTSE',
exchange_tz='US/Eastern'
)
env_start_index = \
env.trading_days.searchsorted(tradingcalendar_tse.start)
env_days = env.trading_days[env_start_index:]
cal_days = tradingcalendar_tse.trading_days
self.check_days(env_days, cal_days)
@nottest
def test_bmf_calendar_vs_environment(self):
env = TradingEnvironment(
bm_symbol='^BVSP',
exchange_tz='America/Sao_Paulo'
)
env_start_index = \
env.trading_days.searchsorted(tradingcalendar_bmf.start)
env_days = env.trading_days[env_start_index:]
cal_days = tradingcalendar_bmf.trading_days
self.check_days(env_days, cal_days)
def check_days(self, env_days, cal_days):
diff = env_days.difference(cal_days)
self.assertEqual(
len(diff),
0,
"{diff} should be empty".format(diff=diff)
)
diff2 = cal_days.difference(env_days)
self.assertEqual(
len(diff2),
0,
"{diff} should be empty".format(diff=diff2)
)
def test_newyears(self):
"""
Check whether tradingcalendar contains certain dates.
"""
# January 2012
# 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
day_after_new_years_sunday = datetime.datetime(
2012, 1, 2, tzinfo=pytz.utc)
self.assertNotIn(day_after_new_years_sunday,
tradingcalendar.trading_days,
"""
If NYE falls on a weekend, {0} the Monday after is a holiday.
""".strip().format(day_after_new_years_sunday)
)
first_trading_day_after_new_years_sunday = datetime.datetime(
2012, 1, 3, tzinfo=pytz.utc)
self.assertIn(first_trading_day_after_new_years_sunday,
tradingcalendar.trading_days,
"""
If NYE falls on a weekend, {0} the Tuesday after is the first trading day.
""".strip().format(first_trading_day_after_new_years_sunday)
)
# January 2013
# 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
new_years_day = datetime.datetime(
2013, 1, 1, tzinfo=pytz.utc)
self.assertNotIn(new_years_day,
tradingcalendar.trading_days,
"""
If NYE falls during the week, e.g. {0}, it is a holiday.
""".strip().format(new_years_day)
)
first_trading_day_after_new_years = datetime.datetime(
2013, 1, 2, tzinfo=pytz.utc)
self.assertIn(first_trading_day_after_new_years,
tradingcalendar.trading_days,
"""
If the day after NYE falls during the week, {0} \
is the first trading day.
""".strip().format(first_trading_day_after_new_years)
)
def test_thanksgiving(self):
"""
Check tradingcalendar Thanksgiving dates.
"""
# November 2005
# 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
thanksgiving_with_four_weeks = datetime.datetime(
2005, 11, 24, tzinfo=pytz.utc)
self.assertNotIn(thanksgiving_with_four_weeks,
tradingcalendar.trading_days,
"""
If Nov has 4 Thursdays, {0} Thanksgiving is the last Thursady.
""".strip().format(thanksgiving_with_four_weeks)
)
# November 2006
# 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
thanksgiving_with_five_weeks = datetime.datetime(
2006, 11, 23, tzinfo=pytz.utc)
self.assertNotIn(thanksgiving_with_five_weeks,
tradingcalendar.trading_days,
"""
If Nov has 5 Thursdays, {0} Thanksgiving is not the last week.
""".strip().format(thanksgiving_with_five_weeks)
)
first_trading_day_after_new_years_sunday = datetime.datetime(
2012, 1, 3, tzinfo=pytz.utc)
self.assertIn(first_trading_day_after_new_years_sunday,
tradingcalendar.trading_days,
"""
If NYE falls on a weekend, {0} the Tuesday after is the first trading day.
""".strip().format(first_trading_day_after_new_years_sunday)
)
def test_day_after_thanksgiving(self):
early_closes = tradingcalendar.get_early_closes(
tradingcalendar.start,
tradingcalendar.end.replace(year=tradingcalendar.end.year + 1)
)
# November 2012
# 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
fourth_friday = datetime.datetime(2012, 11, 23, tzinfo=pytz.utc)
self.assertIn(fourth_friday, early_closes)
# November 2013
# 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
fifth_friday = datetime.datetime(2013, 11, 29, tzinfo=pytz.utc)
self.assertIn(fifth_friday, early_closes)
def test_early_close_independence_day_thursday(self):
"""
Until 2013, the market closed early the Friday after an
Independence Day on Thursday. Since then, the early close is on
Wednesday.
"""
early_closes = tradingcalendar.get_early_closes(
tradingcalendar.start,
tradingcalendar.end.replace(year=tradingcalendar.end.year + 1)
)
# July 2002
# 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
wednesday_before = datetime.datetime(2002, 7, 3, tzinfo=pytz.utc)
friday_after = datetime.datetime(2002, 7, 5, tzinfo=pytz.utc)
self.assertNotIn(wednesday_before, early_closes)
self.assertIn(friday_after, early_closes)
# July 2013
# 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
wednesday_before = datetime.datetime(2013, 7, 3, tzinfo=pytz.utc)
friday_after = datetime.datetime(2013, 7, 5, tzinfo=pytz.utc)
self.assertIn(wednesday_before, early_closes)
self.assertNotIn(friday_after, early_closes)
+29 -44
View File
@@ -28,6 +28,7 @@ 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
from zipline.utils.events import (
EventRule,
StatelessRule,
@@ -165,7 +166,7 @@ class TestEventManager(TestCase):
class CountingRule(Always):
count = 0
def should_trigger(self, dt, env):
def should_trigger(self, dt):
CountingRule.count += 1
return True
@@ -174,9 +175,7 @@ class TestEventManager(TestCase):
Event(r(), lambda context, data: None)
)
mock_algo_class = namedtuple('FakeAlgo', ['trading_environment'])
mock_algo = mock_algo_class(trading_environment="fake_env")
self.em.handle_data(mock_algo, None, datetime.datetime.now())
self.em.handle_data(None, None, datetime.datetime.now())
self.assertEqual(CountingRule.count, 5)
@@ -188,7 +187,7 @@ class TestEventRule(TestCase):
def test_not_implemented(self):
with self.assertRaises(NotImplementedError):
super(Always, Always()).should_trigger('a', env=None)
super(Always, Always()).should_trigger('a')
def minutes_for_days(ordered_days=False):
@@ -207,7 +206,7 @@ def minutes_for_days(ordered_days=False):
Iterating over this yields a single day, iterating over the day yields
the minutes for that day.
"""
env = TradingEnvironment()
cal = get_calendar('NYSE')
random.seed('deterministic')
if ordered_days:
# Get a list of 500 trading days, in order. As a performance
@@ -223,16 +222,15 @@ def minutes_for_days(ordered_days=False):
# Other than AfterOpen and BeforeClose, we don't rely on the the nature
# of the clock, so we don't care.
def day_picker(day):
return random.choice(env.trading_days[:-1])
return random.choice(cal.all_trading_days[:-1])
return ((env.market_minutes_for_day(day_picker(cnt)),)
return ((cal.trading_minutes_for_day(day_picker(cnt)),)
for cnt in range(500))
class RuleTestCase(TestCase):
@classmethod
def setUpClass(cls):
cls.env = TradingEnvironment()
# On the AfterOpen and BeforeClose tests, we want ensure that the
# functions are pure, and that running them with the same input will
# provide the same output, regardless of whether the function is run 1
@@ -244,9 +242,6 @@ class RuleTestCase(TestCase):
cls.after_open = AfterOpen(hours=1, minutes=5)
cls.class_ = None # Mark that this is the base class.
@classmethod
def tearDownClass(cls):
del cls.env
def test_completeness(self):
"""
@@ -280,32 +275,31 @@ class TestStatelessRules(RuleTestCase):
cls.class_ = StatelessRule
cls.sept_days = cls.env.days_in_range(
cls.nyse_cal = get_calendar('NYSE')
cls.sept_days = cls.nyse_cal.trading_days_in_range(
pd.Timestamp('2014-09-01'),
pd.Timestamp('2014-09-30'),
)
cls.sept_week = cls.env.minutes_for_days_in_range(
cls.sept_week = cls.nyse_cal.trading_minutes_for_days_in_range(
datetime.date(year=2014, month=9, day=21),
datetime.date(year=2014, month=9, day=26),
)
@subtest(minutes_for_days(), 'ms')
def test_Always(self, ms):
should_trigger = partial(Always().should_trigger, env=self.env)
should_trigger = Always().should_trigger
self.assertTrue(all(map(should_trigger, ms)))
@subtest(minutes_for_days(), 'ms')
def test_Never(self, ms):
should_trigger = partial(Never().should_trigger, env=self.env)
should_trigger = Never().should_trigger
self.assertFalse(any(map(should_trigger, ms)))
@subtest(minutes_for_days(ordered_days=True), 'ms')
def test_AfterOpen(self, ms):
should_trigger = partial(
self.after_open.should_trigger,
env=self.env,
)
should_trigger = self.after_open.should_trigger
for i, m in enumerate(ms):
# Should only trigger at the 64th minute
if i != 64:
@@ -316,10 +310,7 @@ class TestStatelessRules(RuleTestCase):
@subtest(minutes_for_days(ordered_days=True), 'ms')
def test_BeforeClose(self, ms):
ms = list(ms)
should_trigger = partial(
self.before_close.should_trigger,
env=self.env
)
should_trigger = self.before_close.should_trigger
for m in ms:
# Should only trigger at the 65th-to-last minute
if m != ms[-66]:
@@ -329,7 +320,7 @@ class TestStatelessRules(RuleTestCase):
@subtest(minutes_for_days(), 'ms')
def test_NotHalfDay(self, ms):
should_trigger = partial(NotHalfDay().should_trigger, env=self.env)
should_trigger = NotHalfDay().should_trigger
self.assertTrue(should_trigger(FULL_DAY))
self.assertFalse(should_trigger(HALF_DAY))
@@ -340,14 +331,13 @@ class TestStatelessRules(RuleTestCase):
"""
self.assertTrue(
NthTradingDayOfWeek(0).should_trigger(
self.env.trading_days[0], self.env
self.nyse_cal.all_trading_days[0]
)
)
@subtest(param_range(MAX_WEEK_RANGE), 'n')
def test_NthTradingDayOfWeek(self, n):
should_trigger = partial(NthTradingDayOfWeek(n).should_trigger,
env=self.env)
should_trigger = NthTradingDayOfWeek(n).should_trigger
prev_day = self.sept_week[0].date()
n_tdays = 0
for m in self.sept_week:
@@ -362,17 +352,15 @@ class TestStatelessRules(RuleTestCase):
@subtest(param_range(MAX_WEEK_RANGE), 'n')
def test_NDaysBeforeLastTradingDayOfWeek(self, n):
should_trigger = partial(
NDaysBeforeLastTradingDayOfWeek(n).should_trigger, env=self.env
)
should_trigger = NDaysBeforeLastTradingDayOfWeek(n).should_trigger
for m in self.sept_week:
if should_trigger(m):
n_tdays = 0
date = m.to_datetime().date()
next_date = self.env.next_trading_day(date)
next_date = self.nyse_cal.next_trading_day(date)
while next_date.weekday() > date.weekday():
date = next_date
next_date = self.env.next_trading_day(date)
next_date = self.nyse_cal.next_trading_day(date)
n_tdays += 1
self.assertEqual(n_tdays, n)
@@ -486,10 +474,9 @@ class TestStatelessRules(RuleTestCase):
@subtest(param_range(MAX_MONTH_RANGE), 'n')
def test_NthTradingDayOfMonth(self, n):
should_trigger = partial(NthTradingDayOfMonth(n).should_trigger,
env=self.env)
should_trigger = NthTradingDayOfMonth(n).should_trigger
for n_tdays, d in enumerate(self.sept_days):
for m in self.env.market_minutes_for_day(d):
for m in self.nyse_cal.trading_minutes_for_day(d):
if should_trigger(m):
self.assertEqual(n_tdays, n)
else:
@@ -497,11 +484,9 @@ class TestStatelessRules(RuleTestCase):
@subtest(param_range(MAX_MONTH_RANGE), 'n')
def test_NDaysBeforeLastTradingDayOfMonth(self, n):
should_trigger = partial(
NDaysBeforeLastTradingDayOfMonth(n).should_trigger, env=self.env
)
should_trigger = NDaysBeforeLastTradingDayOfMonth(n).should_trigger
for n_days_before, d in enumerate(reversed(self.sept_days)):
for m in self.env.market_minutes_for_day(d):
for m in self.nyse_cal.trading_minutes_for_day(d):
if should_trigger(m):
self.assertEqual(n_days_before, n)
else:
@@ -513,7 +498,7 @@ class TestStatelessRules(RuleTestCase):
rule2 = Never()
composed = rule1 & rule2
should_trigger = partial(composed.should_trigger, env=self.env)
should_trigger = composed.should_trigger
self.assertIsInstance(composed, ComposedRule)
self.assertIs(composed.first, rule1)
self.assertIs(composed.second, rule2)
@@ -536,14 +521,14 @@ class TestStatefulRules(RuleTestCase):
"""
count = 0
def should_trigger(self, dt, env):
st = self.rule.should_trigger(dt, env)
def should_trigger(self, dt):
st = self.rule.should_trigger(dt)
if st:
self.count += 1
return st
rule = RuleCounter(OncePerDay())
for m in ms:
rule.should_trigger(m, env=self.env)
rule.should_trigger(m)
self.assertEqual(rule.count, 1)