Merge pull request #1128 from quantopian/remove-extra-parameter-to-position-of-minute

Fix regression on retrieval of minute positions.
This commit is contained in:
Eddie Hebert
2016-04-14 10:23:18 -04:00
2 changed files with 32 additions and 54 deletions
+3 -31
View File
@@ -38,8 +38,7 @@ def minute_value(ndarray[long_t, ndim=1] market_opens,
def find_position_of_minute(ndarray[long_t, ndim=1] market_opens,
ndarray[long_t, ndim=1] market_closes,
long_t minute_val,
short minutes_per_day,
bool adjust_half_day_minutes):
short minutes_per_day):
"""
Finds the position of a given minute in the given array of market opens.
If not a market minute, adjusts to the last market minute.
@@ -58,26 +57,6 @@ def find_position_of_minute(ndarray[long_t, ndim=1] market_opens,
minutes_per_day: int
The number of minutes per day (e.g. 390 for NYSE).
adjust_half_day_minutes: boolean
Whether or not we want to adjust non trading minutes to early close on
half days as opposed to normal close.
Further explanation of the use adjust_half_day_minutes:
adjust_half_day_minutes=True:
We are using this method for the purpose finding a value for a
minute, and therefore, all non market minutes must be adjusted to
the last available (e.g. 9 pm EST -> 4 pm EST, 2 pm EST -> 1 pm EST
on a half day)
adjust_half_day_minutes=False:
We are using this method for the purpose of finding the positions
of minutes we want to ignore (1 pm to 4 pm EST on half days).
The minute bar reader tape has 390 bars per day, with 0's filled in
for the extra bars on half days. If we index a minute between
1:01 pm and 4 pm on a half day, we want a position for that
unadjusted time, not adjusted to 1 pm as in the above case
(e.g. for all days: 9 pm EST -> 4 pm EST, 2 pm EST -> 2 pm EST)
Returns
-------
int: The position of the given minute in the market opens array.
@@ -89,14 +68,7 @@ def find_position_of_minute(ndarray[long_t, ndim=1] market_opens,
market_open = market_opens[market_open_loc]
market_close = market_closes[market_open_loc]
if adjust_half_day_minutes:
# The min of the distance to market open from minute_val and number
# of trading minutes for that day
delta = int_min(minute_val - market_open, market_close - market_open)
else:
# The min of the distance to market open from minute_val and number
# of trading minutes for a normal day (390)
delta = int_min(minute_val - market_open, minutes_per_day)
delta = int_min(minute_val - market_open, market_close - market_open)
return (market_open_loc * minutes_per_day) + delta
@@ -140,7 +112,7 @@ def find_last_traded_position_internal(
minute_pos = int_min(
find_position_of_minute(market_opens, market_closes, end_minute,
minutes_per_day, True),
minutes_per_day),
len(volumes) - 1
)
+29 -23
View File
@@ -16,7 +16,7 @@ from textwrap import dedent
import bcolz
from bcolz import ctable
from intervaltree import IntervalTree
from numpy import nan_to_num, timedelta64
from numpy import nan_to_num
from os.path import join
import json
import os
@@ -30,7 +30,7 @@ from zipline.data._minute_bar_internal import (
find_last_traded_position_internal
)
from zipline.utils.memoize import remember_last, lazyval
from zipline.utils.memoize import lazyval
US_EQUITIES_MINUTES_PER_DAY = 390
@@ -618,6 +618,9 @@ class BcolzMinuteBarReader(object):
'volume': {},
}
self._last_get_value_dt_position = None
self._last_get_value_dt_value = None
def _get_metadata(self):
return BcolzMinuteBarMetadata.read(self._rootdir)
@@ -646,12 +649,11 @@ class BcolzMinuteBarReader(object):
minutes_per_day = (market_closes - market_opens).astype(np.int64)
early_indices = np.where(
minutes_per_day != US_EQUITIES_MINUTES_PER_DAY - 1)[0]
regular_closes = market_opens[early_indices] + timedelta64(
US_EQUITIES_MINUTES_PER_DAY - 1, 'm')
early_closes = market_closes[early_indices]
minutes = [pd.date_range(early, regular, freq='min')
for early, regular
in zip(early_closes + 1, regular_closes)]
early_opens = self._market_opens[early_indices]
early_closes = self._market_closes[early_indices]
minutes = [(market_open, early_close)
for market_open, early_close
in zip(early_opens, early_closes)]
return minutes
@lazyval
@@ -673,11 +675,15 @@ class BcolzMinuteBarReader(object):
because of early closes.
"""
itree = IntervalTree()
for minute_range in self._minutes_to_exclude():
# setting adjust_half_day_minutes to False because we want to find
# the positions of minutes 211 to 390 on a 390-bar day
start_pos = self._find_position_of_minute(minute_range[0], False)
end_pos = self._find_position_of_minute(minute_range[-1], False)
for market_open, early_close in self._minutes_to_exclude():
start_pos = self._find_position_of_minute(early_close) + 1
end_pos = (
self._find_position_of_minute(market_open)
+
US_EQUITIES_MINUTES_PER_DAY
-
1
)
data = (start_pos, end_pos)
itree[start_pos:end_pos + 1] = data
return itree
@@ -744,7 +750,13 @@ class BcolzMinuteBarReader(object):
Returns the integer value of the volume.
(A volume of 0 signifies no trades for the given dt.)
"""
minute_pos = self._find_position_of_minute(dt, True)
if self._last_get_value_dt_value == dt.value:
minute_pos = self._last_get_value_dt_position
else:
minute_pos = self._find_position_of_minute(dt)
self._last_get_value_dt_value = dt.value
self._last_get_value_dt_position = minute_pos
value = self._open_minute_file(field, sid)[minute_pos]
if value == 0:
if field == 'volume':
@@ -787,8 +799,7 @@ class BcolzMinuteBarReader(object):
return pd.Timestamp(minute_epoch, tz='UTC', unit="m")
@remember_last
def _find_position_of_minute(self, minute_dt, adjust_half_day_minutes):
def _find_position_of_minute(self, minute_dt):
"""
Internal method that returns the position of the given minute in the
list of every trading minute since market open of the first trading
@@ -802,10 +813,6 @@ class BcolzMinuteBarReader(object):
minute_dt: pd.Timestamp
The minute whose position should be calculated.
adjust_half_day_minutes: boolean
Whether or not we want to adjust minutes to early close on half
days.
Returns
-------
int: The position of the given minute in the list of all trading
@@ -816,7 +823,6 @@ class BcolzMinuteBarReader(object):
self._market_close_values,
minute_dt.value / NANOS_IN_MINUTE,
US_EQUITIES_MINUTES_PER_DAY,
adjust_half_day_minutes
)
def unadjusted_window(self, fields, start_dt, end_dt, sids):
@@ -839,8 +845,8 @@ class BcolzMinuteBarReader(object):
(sids, minutes in range) with a dtype of float64, containing the
values for the respective field over start and end dt range.
"""
start_idx = self._find_position_of_minute(start_dt, True)
end_idx = self._find_position_of_minute(end_dt, True)
start_idx = self._find_position_of_minute(start_dt)
end_idx = self._find_position_of_minute(end_dt)
num_minutes = (end_idx - start_idx + 1)