BUG: Fix multiple bugs in PanelDailyBarReader.

- Return a value from `verify_all_indices_unique` so that `panel` isn't
  unconditionally `None` in `PanelDailyBarReader`.

- Fix a bug where we always set the volume of every asset to `1e9`.

- Add minimal suite of tests for get_spot_value, which catch both of the
  above.

NOTE: There are still several issues with `PanelDailyBarReader`.  The
docstring for `get_spot_value` claims that it will return -1 on days
where an asset didn't trade, which isn't the case.  It also claims that
it will raise `NoDataOnDate` when a request is made outside the panel
range, but it just raises a KeyError.  We also still have no coverage
for `load_raw_arrays`, so it's likely that there are more bugs lurking.
This commit is contained in:
Scott Sanderson
2016-05-06 10:59:14 -04:00
parent a068eb374a
commit 3395b33f1e
3 changed files with 53 additions and 6 deletions
+49 -4
View File
@@ -13,16 +13,60 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from itertools import permutations
from itertools import permutations, product
import numpy as np
import pandas as pd
from zipline.data.us_equity_pricing import PanelDailyBarReader
from zipline.testing import ExplodingObject
from zipline.testing.fixtures import ZiplineTestCase
from zipline.testing.fixtures import (
WithAssetFinder,
WithNYSETradingDays,
ZiplineTestCase,
)
class TestPanelDailyBarReader(ZiplineTestCase):
class TestPanelDailyBarReader(WithAssetFinder,
WithNYSETradingDays,
ZiplineTestCase):
START_DATE = pd.Timestamp('2006-01-03', tz='utc')
END_DATE = pd.Timestamp('2006-02-01', tz='utc')
@classmethod
def init_class_fixtures(cls):
super(TestPanelDailyBarReader, cls).init_class_fixtures()
finder = cls.asset_finder
days = cls.trading_days
items = finder.retrieve_all(finder.sids)
major_axis = days
minor_axis = ['open', 'high', 'low', 'close', 'volume']
shape = tuple(map(len, [items, major_axis, minor_axis]))
raw_data = np.arange(shape[0] * shape[1] * shape[2]).reshape(shape)
cls.panel = pd.Panel(
raw_data,
items=items,
major_axis=major_axis,
minor_axis=minor_axis,
)
cls.reader = PanelDailyBarReader(days, cls.panel)
def test_spot_price(self):
panel = self.panel
reader = self.reader
for asset, date, field in product(*panel.axes):
self.assertEqual(
panel.loc[asset, date, field],
reader.spot_price(asset, date, field),
)
def test_duplicate_values(self):
UNIMPORTANT_VALUE = 57
@@ -37,8 +81,9 @@ class TestPanelDailyBarReader(ZiplineTestCase):
axis_names = ['items', 'major_axis', 'minor_axis']
for axis_order in permutations((0, 1, 2)):
transposed = panel.transpose(*axis_order)
with self.assertRaises(ValueError) as e:
PanelDailyBarReader(unused, panel.transpose(*axis_order))
PanelDailyBarReader(unused, transposed)
expected = (
"Duplicate entries in Panel.{name}: ['a', 'b'].".format(
+1 -1
View File
@@ -719,7 +719,7 @@ class PanelDailyBarReader(DailyBarReader):
def __init__(self, calendar, panel):
panel = panel.copy()
if 'volume' not in panel.items:
if 'volume' not in panel.minor_axis:
# Fake volume if it does not exist.
panel.loc[:, :, 'volume'] = int(1e9)
+3 -1
View File
@@ -37,7 +37,8 @@ def verify_indices_all_unique(obj):
Returns
-------
None
obj : pd.Series / pd.DataFrame / pd.Panel
The validated object, unchanged.
Raises
------
@@ -61,6 +62,7 @@ def verify_indices_all_unique(obj):
dupes=sorted(index[index.duplicated()]),
)
)
return obj
def optionally(preprocessor):