MAINT: Fix failures/warnings in test_api_shim.py

- Fixes a warning on indexing with a float that ultimately came from
  pd.Timedelta.total_seconds().  Adds ``timedelta_to_integral_seconds``
  and ``timedelta_to_integral_minutes()`` functions and replaces various
  usages of ``int(delta.total_seconds())`` with them.

- Fixes a warnings triggered in ``_create_daily_stats`` from
  passing tz-aware datetimes to np.datetime64.
This commit is contained in:
Scott Sanderson
2016-07-15 12:16:19 -04:00
parent ccc31152a5
commit becf897da9
6 changed files with 73 additions and 34 deletions
+3 -2
View File
@@ -819,8 +819,9 @@ class TradingAlgorithm(object):
else:
self.risk_report = perf
daily_dts = [np.datetime64(perf['period_close'], utc=True)
for perf in daily_perfs]
daily_dts = pd.DatetimeIndex(
[p['period_close'] for p in daily_perfs], tz='UTC'
)
daily_stats = pd.DataFrame(daily_perfs, index=daily_dts)
return daily_stats
+4 -2
View File
@@ -33,6 +33,8 @@ from zipline.lib.adjustment import Float64Multiply
from zipline.assets.asset_writer import (
SQLITE_MAX_VARIABLE_NUMBER as SQLITE_MAX_IN_STATEMENT,
)
from zipline.utils.pandas_utils import timedelta_to_integral_seconds
_SID_QUERY_TEMPLATE = """
SELECT DISTINCT sid FROM {0}
@@ -170,8 +172,8 @@ cpdef load_adjustments_from_sqlite(object adjustments_db, # sqlite3.Connection
index.
"""
cdef int start_date = int((dates[0] - EPOCH).total_seconds())
cdef int end_date = int((dates[-1] - EPOCH).total_seconds())
cdef int start_date = timedelta_to_integral_seconds(dates[0] - EPOCH)
cdef int end_date = timedelta_to_integral_seconds(dates[-1] - EPOCH)
cdef set split_sids = _get_split_sids(
adjustments_db,
+49 -29
View File
@@ -44,6 +44,7 @@ from zipline.utils.math_utils import (
nanstd
)
from zipline.utils.memoize import remember_last, weak_lru_cache
from zipline.utils.pandas_utils import timedelta_to_integral_minutes
from zipline.errors import (
NoTradeDataAvailableTooEarly,
NoTradeDataAvailableTooLate,
@@ -1106,44 +1107,63 @@ class DataPortal(object):
else:
return [assets] if isinstance(assets, Asset) else []
# cache size picked somewhat loosely. this code exists purely to
# handle deprecated API.
@weak_lru_cache(20)
def _get_minute_count_for_transform(self, ending_minute, days_count):
# cache size picked somewhat loosely. this code exists purely to
# handle deprecated API.
# This function works in three steps.
# Step 1. Count the minutes from ``ending_minute`` to the start of its
# session.
# Step 2. Count the minutes from the prior ``days_count - 1`` sessions.
# Step 3. Return the sum of the results from steps (1) and (2).
# bars is the number of days desired. we have to translate that
# into the number of minutes we want.
# we get all the minutes for the last (bars - 1) days, then add
# all the minutes so far today. the +2 is to account for ignoring
# today, and the previous day, in doing the math.
session_for_minute = self.trading_calendar.minute_to_session_label(
ending_minute
)
previous_session = self.trading_calendar.previous_session_label(
session_for_minute
# Example (NYSE Calendar)
# ending_minute = 2016-12-28 9:40 AM US/Eastern
# days_count = 3
# Step 1. Calculate that there are 10 minutes in the ending session.
# Step 2. Calculate that there are 390 + 210 = 600 minutes in the prior
# two sessions. (Prior sessions are 2015-12-23 and 2015-12-24.)
# 2015-12-24 is a half day.
# Step 3. Return 600 + 10 = 610.
cal = self.trading_calendar
ending_session = cal.minute_to_session_label(
ending_minute,
direction="none", # It's an error to pass a non-trading minute.
)
sessions = self.trading_calendar.sessions_in_range(
self.trading_calendar.sessions_window(previous_session,
-days_count + 2)[0],
previous_session,
# Assume that calendar days are always full of contiguous minutes,
# which means we can just take 1 + (number of minutes between the last
# minute and the start of the session). We add one so that we include
# the ending minute in the total.
ending_session_minute_count = timedelta_to_integral_minutes(
ending_minute - cal.open_and_close_for_session(ending_session)[0]
) + 1
if days_count == 1:
# We just need sessions for the active day.
return ending_session_minute_count
# XXX: We're subtracting 2 here to account for two offsets:
# 1. We only want ``days_count - 1`` sessions, since we've already
# accounted for the ending session above.
# 2. The API of ``sessions_window`` is to return one more session than
# the requested number. I don't think any consumers actually want
# that behavior, but it's the tested and documented behavior right
# now, so we have to request one less session than we actually want.
completed_sessions = cal.sessions_window(
cal.previous_session_label(ending_session),
2 - days_count,
)
minutes_count = \
completed_sessions_minute_count = (
self.trading_calendar.minutes_count_for_sessions_in_range(
sessions[0],
sessions[-1]
completed_sessions[0],
completed_sessions[-1]
)
# add the minutes for today
today_open = self.trading_calendar.open_and_close_for_session(
session_for_minute
)[0]
minutes_count += \
((ending_minute - today_open).total_seconds() // 60) + 1
return minutes_count
)
return ending_session_minute_count + completed_sessions_minute_count
def get_simple_transform(self, asset, transform_name, dt, data_frequency,
bars=None):
+2 -1
View File
@@ -50,6 +50,7 @@ from zipline.utils import security_list
from zipline.utils.calendars import get_calendar
from zipline.utils.input_validation import expect_dimensions
from zipline.utils.numpy_utils import as_column
from zipline.utils.pandas_utils import timedelta_to_integral_seconds
from zipline.utils.sentinel import sentinel
import numpy as np
@@ -78,7 +79,7 @@ def str_to_seconds(s):
>>> str_to_seconds('2014-01-01')
1388534400
"""
return int((pd.Timestamp(s, tz='UTC') - EPOCH).total_seconds())
return timedelta_to_integral_seconds(pd.Timestamp(s, tz='UTC') - EPOCH)
def drain_zipline(test, zipline):
+1
View File
@@ -18,6 +18,7 @@ from numpy import (
flatnonzero,
hstack,
nan,
timedelta64,
vectorize,
where
)
+14
View File
@@ -146,3 +146,17 @@ def nearest_unequal_elements(dts, dt):
upper_value = dts[upper_ix] if upper_ix < len(dts) else None
return lower_value, upper_value
def timedelta_to_integral_seconds(delta):
"""
Convert a pd.Timedelta to a number of seconds as an int.
"""
return int(delta.total_seconds())
def timedelta_to_integral_minutes(delta):
"""
Convert a pd.Timedelta to a number of minutes as an int.
"""
return timedelta_to_integral_seconds(delta) // 60