mirror of
https://github.com/saymrwulf/zipline.git
synced 2026-05-14 20:58:10 +00:00
TST/BUG: Cover all reindex session public methods.
Increase coverage on `ReindexSessionBarReader` so that all methods which are considered part of the interface are covered by `test_resample`. Fix bug in `get_value`, exposed by increased coverage, where the `NoDataOnDate` exception was bubbling from the bcolz reader all the way up when a session which was a holidy on the underlying reader was passed to the reindex reader. (The reindex reader should return nan/0 in that case.) Also, move location of data index exceptions so that they are agnostic to bcolz/us_equity_pricing; since the exception is now used by the resample module to fix aforementioned bug.
This commit is contained in:
parent
959baf7fe0
commit
d463a9855b
5 changed files with 131 additions and 20 deletions
|
|
@ -2,3 +2,5 @@
|
|||
omit =
|
||||
*/python?.?/*
|
||||
*/site-packages/nose/*
|
||||
exclude_lines =
|
||||
raise NotImplementedError
|
||||
|
|
|
|||
|
|
@ -616,8 +616,15 @@ class TestReindexSessionBars(WithBcolzEquityDailyBarReader,
|
|||
|
||||
# Dates are chosen to span Thanksgiving, which is not a Holiday on
|
||||
# us_futures.
|
||||
START_DATE = pd.Timestamp('2015-11-01', tz='UTC')
|
||||
START_DATE = pd.Timestamp('2015-11-02', tz='UTC')
|
||||
END_DATE = pd.Timestamp('2015-11-30', tz='UTC')
|
||||
# November 2015
|
||||
# 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
|
||||
|
||||
def init_instance_fixtures(self):
|
||||
super(TestReindexSessionBars, self).init_instance_fixtures()
|
||||
|
|
@ -651,6 +658,18 @@ class TestReindexSessionBars(WithBcolzEquityDailyBarReader,
|
|||
"The reindexed result after dropping nans should have 20 days, "
|
||||
"because Thanksgiving is a NYSE holiday.")
|
||||
|
||||
tday = pd.Timestamp('2015-11-26', tz='UTC')
|
||||
|
||||
# Thanksgiving, 2015-11-26.
|
||||
# Is a holiday in NYSE, but not in us_futures.
|
||||
tday_loc = outer_sessions.get_loc(tday)
|
||||
|
||||
assert_almost_equal(
|
||||
nan,
|
||||
opens[1][tday_loc],
|
||||
err_msg="2015-11-26 should be `nan`, since Thanksgiving is a "
|
||||
"holiday in the reader's calendar.")
|
||||
|
||||
# Thanksgiving, 2015-11-26.
|
||||
# Is a holiday in NYSE, but not in us_futures.
|
||||
tday_loc = outer_sessions.get_loc(pd.Timestamp('2015-11-26', tz='UTC'))
|
||||
|
|
@ -661,6 +680,65 @@ class TestReindexSessionBars(WithBcolzEquityDailyBarReader,
|
|||
err_msg="2015-11-26 should be `nan`, since Thanksgiving is a "
|
||||
"holiday in the reader's calendar.")
|
||||
|
||||
def test_load_raw_arrays_holiday_start(self):
|
||||
tday = pd.Timestamp('2015-11-26', tz='UTC')
|
||||
outer_sessions = self.trading_calendar.sessions_in_range(
|
||||
tday, self.END_DATE)
|
||||
|
||||
result = self.reader.load_raw_arrays(
|
||||
OHLCV, tday, self.END_DATE, [1, 2])
|
||||
|
||||
opens = DataFrame(data=result[0], index=outer_sessions,
|
||||
columns=[1, 2])
|
||||
opens_with_price = opens.dropna()
|
||||
|
||||
self.assertEqual(
|
||||
3,
|
||||
len(opens),
|
||||
"The reindexed result should have 3 days, which is the number of "
|
||||
"business days in from Thanksgiving to end of 2015-11.")
|
||||
self.assertEqual(
|
||||
2,
|
||||
len(opens_with_price),
|
||||
"The reindexed result after dropping nans should have 2 days, "
|
||||
"because Thanksgiving is a NYSE holiday.")
|
||||
|
||||
def test_load_raw_arrays_holiday_end(self):
|
||||
tday = pd.Timestamp('2015-11-26', tz='UTC')
|
||||
outer_sessions = self.trading_calendar.sessions_in_range(
|
||||
self.START_DATE, tday)
|
||||
|
||||
result = self.reader.load_raw_arrays(
|
||||
OHLCV, self.START_DATE, tday, [1, 2])
|
||||
|
||||
opens = DataFrame(data=result[0], index=outer_sessions,
|
||||
columns=[1, 2])
|
||||
opens_with_price = opens.dropna()
|
||||
|
||||
self.assertEqual(
|
||||
19,
|
||||
len(opens),
|
||||
"The reindexed result should have 19 days, which is the number of "
|
||||
"business days in from start of 2015-11 up to Thanksgiving.")
|
||||
self.assertEqual(
|
||||
18,
|
||||
len(opens_with_price),
|
||||
"The reindexed result after dropping nans should have 18 days, "
|
||||
"because Thanksgiving is a NYSE holiday.")
|
||||
|
||||
def test_get_value(self):
|
||||
assert_almost_equal(self.reader.get_value(1, self.START_DATE, 'open'),
|
||||
10.0,
|
||||
err_msg="The open of the fixture data on the "
|
||||
"first session should be 10.")
|
||||
tday = pd.Timestamp('2015-11-26', tz='UTC')
|
||||
assert_almost_equal(self.reader.get_value(1, tday, 'close'), nan,
|
||||
err_msg="Thanksgiving is a NYSE holiday, but "
|
||||
"futures trading is open. Result should be nan.")
|
||||
assert_almost_equal(self.reader.get_value(1, tday, 'volume'), 0,
|
||||
err_msg="Thanksgiving is a NYSE holiday, but "
|
||||
"futures trading is open. Result should be 0.")
|
||||
|
||||
def test_last_availabe_dt(self):
|
||||
self.assertEqual(self.reader.last_available_dt, self.END_DATE)
|
||||
|
||||
|
|
@ -669,3 +747,21 @@ class TestReindexSessionBars(WithBcolzEquityDailyBarReader,
|
|||
self.assertEqual(self.reader.get_last_traded_dt(asset,
|
||||
self.END_DATE),
|
||||
self.END_DATE)
|
||||
|
||||
def test_sessions(self):
|
||||
sessions = self.reader.sessions
|
||||
self.assertEqual(21, len(sessions),
|
||||
"There should be 21 sessions in 2015-11.")
|
||||
self.assertEqual(pd.Timestamp('2015-11-02', tz='UTC'),
|
||||
sessions[0])
|
||||
self.assertEqual(pd.Timestamp('2015-11-30', tz='UTC'),
|
||||
sessions[-1])
|
||||
|
||||
def test_first_trading_day(self):
|
||||
self.assertEqual(self.reader.first_trading_day, self.START_DATE)
|
||||
|
||||
def test_trading_calendar(self):
|
||||
self.assertEqual('us_futures',
|
||||
self.reader.trading_calendar.name,
|
||||
"The calendar for the reindex reader should be the "
|
||||
"specified futures calendar.")
|
||||
|
|
|
|||
|
|
@ -15,11 +15,13 @@ from collections import OrderedDict
|
|||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
import numpy as np
|
||||
from numpy import nan
|
||||
import pandas as pd
|
||||
from pandas import DataFrame
|
||||
from six import with_metaclass
|
||||
|
||||
from zipline.data.minute_bars import MinuteBarReader
|
||||
from zipline.data.us_equity_pricing import NoDataOnDate
|
||||
from zipline.data.session_bars import SessionBarReader
|
||||
from zipline.utils.memoize import lazyval
|
||||
|
||||
|
|
@ -584,15 +586,21 @@ class ReindexBarReader(with_metaclass(ABCMeta)):
|
|||
return self._reader.first_trading_day
|
||||
|
||||
def get_value(self, sid, dt, field):
|
||||
return self._reader.get_value(sid, dt, field)
|
||||
try:
|
||||
return self._reader.get_value(sid, dt, field)
|
||||
except NoDataOnDate:
|
||||
if field == 'volume':
|
||||
return 0
|
||||
else:
|
||||
return nan
|
||||
|
||||
@abstractmethod
|
||||
def _outer_dts(self, start_dt, end_dt):
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def _inner_dts(self, start_dt, end_dt):
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def trading_calendar(self):
|
||||
|
|
|
|||
|
|
@ -15,6 +15,21 @@ from abc import ABCMeta, abstractmethod, abstractproperty
|
|||
from six import with_metaclass
|
||||
|
||||
|
||||
class NoDataOnDate(Exception):
|
||||
"""
|
||||
Raised when a spot price can be found for the sid and date.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NoDataBeforeDate(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class NoDataAfterDate(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SessionBarReader(with_metaclass(ABCMeta)):
|
||||
"""
|
||||
Reader for OHCLV pricing data at a session frequency.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,12 @@ from six import (
|
|||
string_types,
|
||||
)
|
||||
|
||||
from zipline.data.session_bars import SessionBarReader
|
||||
from zipline.data.session_bars import (
|
||||
SessionBarReader,
|
||||
NoDataAfterDate,
|
||||
NoDataBeforeDate,
|
||||
NoDataOnDate,
|
||||
)
|
||||
from zipline.utils.calendars import get_calendar
|
||||
from zipline.utils.functional import apply
|
||||
from zipline.utils.preprocess import call
|
||||
|
|
@ -99,21 +104,6 @@ SQLITE_STOCK_DIVIDEND_PAYOUT_COLUMN_DTYPES = {
|
|||
UINT32_MAX = iinfo(uint32).max
|
||||
|
||||
|
||||
class NoDataOnDate(Exception):
|
||||
"""
|
||||
Raised when a spot price can be found for the sid and date.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class NoDataBeforeDate(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class NoDataAfterDate(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def check_uint32_safe(value, colname):
|
||||
if value >= UINT32_MAX:
|
||||
raise ValueError(
|
||||
|
|
|
|||
Loading…
Reference in a new issue