MAINT: Moved auto_close_date to Asset

Handle custom data source with non-int sids
This commit is contained in:
Richard Frank
2016-02-04 10:58:08 -05:00
parent ede1eb7aa0
commit 79aff84aed
2 changed files with 42 additions and 26 deletions
+15 -13
View File
@@ -37,7 +37,7 @@ cimport numpy as np
# IMPORTANT NOTE: You must change this template if you change
# Asset.__reduce__, or else we'll attempt to unpickle an old version of this
# class
CACHE_FILE_TEMPLATE = '/tmp/.%s-%s.v5.cache'
CACHE_FILE_TEMPLATE = '/tmp/.%s-%s.v6.cache'
cdef class Asset:
@@ -51,6 +51,7 @@ cdef class Asset:
cdef readonly object start_date
cdef readonly object end_date
cdef public object first_traded
cdef readonly object auto_close_date
cdef readonly object exchange
@@ -61,6 +62,7 @@ cdef class Asset:
object start_date=None,
object end_date=None,
object first_traded=None,
object auto_close_date=None,
object exchange="",
*args,
**kwargs):
@@ -73,6 +75,7 @@ cdef class Asset:
self.start_date = start_date
self.end_date = end_date
self.first_traded = first_traded
self.auto_close_date = auto_close_date
def __int__(self):
return self.sid
@@ -127,7 +130,7 @@ cdef class Asset:
def __repr__(self):
attrs = ('symbol', 'asset_name', 'exchange',
'start_date', 'end_date', 'first_traded')
'start_date', 'end_date', 'first_traded', 'auto_close_date')
tuples = ((attr, repr(getattr(self, attr, None)))
for attr in attrs)
strings = ('%s=%s' % (t[0], t[1]) for t in tuples)
@@ -147,6 +150,7 @@ cdef class Asset:
self.start_date,
self.end_date,
self.first_traded,
self.auto_close_date,
self.exchange,))
cpdef to_dict(self):
@@ -160,6 +164,7 @@ cdef class Asset:
'start_date': self.start_date,
'end_date': self.end_date,
'first_traded': self.first_traded,
'auto_close_date': self.auto_close_date,
'exchange': self.exchange,
}
@@ -181,7 +186,7 @@ cdef class Equity(Asset):
def __repr__(self):
attrs = ('symbol', 'asset_name', 'exchange',
'start_date', 'end_date', 'first_traded')
'start_date', 'end_date', 'first_traded', 'auto_close_date')
tuples = ((attr, repr(getattr(self, attr, None)))
for attr in attrs)
strings = ('%s=%s' % (t[0], t[1]) for t in tuples)
@@ -227,10 +232,8 @@ cdef class Future(Asset):
cdef readonly object root_symbol
cdef readonly object notice_date
cdef readonly object expiration_date
cdef readonly object auto_close_date
cdef readonly object tick_size
cdef readonly float multiplier
cdef readonly object effective_expiration
def __cinit__(self,
int sid, # sid is required
@@ -250,16 +253,16 @@ cdef class Future(Asset):
self.root_symbol = root_symbol
self.notice_date = notice_date
self.expiration_date = expiration_date
self.auto_close_date = auto_close_date
self.tick_size = tick_size
self.multiplier = multiplier
if notice_date is None:
self.effective_expiration = expiration_date
elif expiration_date is None:
self.effective_expiration = notice_date
else:
self.effective_expiration = min(notice_date, expiration_date)
if auto_close_date is None:
if notice_date is None:
self.auto_close_date = expiration_date
elif expiration_date is None:
self.auto_close_date = notice_date
else:
self.auto_close_date = min(notice_date, expiration_date)
def __str__(self):
if self.symbol:
@@ -307,7 +310,6 @@ cdef class Future(Asset):
super_dict['root_symbol'] = self.root_symbol
super_dict['notice_date'] = self.notice_date
super_dict['expiration_date'] = self.expiration_date
super_dict['auto_close_date'] = self.auto_close_date
super_dict['tick_size'] = self.tick_size
super_dict['multiplier'] = self.multiplier
return super_dict
+27 -13
View File
@@ -19,6 +19,7 @@ from contextlib2 import ExitStack
from logbook import Logger, Processor
from pandas.tslib import normalize_date
from zipline.errors import SidsNotFound
from zipline.finance.trading import NoFurtherDataError
from zipline.protocol import (
BarData,
@@ -57,19 +58,32 @@ class AlgorithmSimulator(object):
# Snapshot Setup
# ==============
def _get_effective_expiration(sid,
finder=self.env.asset_finder,
default=self.sim_params.last_close
+ timedelta(days=1)):
asset = finder.retrieve_asset(sid)
return getattr(asset, 'effective_expiration', None) or default
def _get_asset_close_date(sid,
finder=self.env.asset_finder,
default=self.sim_params.last_close
+ timedelta(days=1)):
try:
asset = finder.retrieve_asset(sid)
except ValueError:
# Handle sid not an int, such as from a custom source.
# So that they don't compare equal to other sids, and we'd
# blow up comparing strings to ints, let's give them unique
# close dates.
return default + timedelta(microseconds=id(sid))
except SidsNotFound:
return default
# Default is used when the asset has no auto close date,
# and is set to a time after the simulation ends, so that the
# relevant asset isn't removed from the universe at all
# (at least not for this reason).
return asset.auto_close_date or default
self._get_expiration = _get_effective_expiration
self._get_asset_close = _get_asset_close_date
# The algorithm's data as of our most recent event.
# We want an object that will have empty objects as default
# values on missing keys.
self.current_data = BarData(SortedDict(self._get_expiration))
# Maintain sids in order by asset close date, so that we can more
# efficiently remove them when their times come...
self.current_data = BarData(SortedDict(self._get_asset_close))
# We don't have a datetime for the current snapshot until we
# receive a message.
@@ -110,11 +124,11 @@ class AlgorithmSimulator(object):
self.simulation_dt = date
self.on_dt_changed(date)
expired = list(takewhile(
lambda asset_id: self._get_expiration(asset_id) < date,
closed = list(takewhile(
lambda asset_id: self._get_asset_close(asset_id) < date,
self.current_data
))
for sid in expired:
for sid in closed:
try:
del self.current_data[sid]
except KeyError: