def test_preprocess_on_function(self, args, kwargs): decorators = [ preprocess(a=call(str), b=call(float), c=call(lambda x: x + 1)), ] for decorator in decorators: @decorator def func(a, b, c=3): return a, b, c self.assertEqual(func(*args, **kwargs), ('1', 2.0, 4))
def expect_dtypes(**named): """ Preprocessing decorator that verifies inputs have expected numpy dtypes. Usage ----- >>> from numpy import dtype, arange, int8, float64 >>> @expect_dtypes(x=dtype(int8)) ... def foo(x, y): ... return x, y ... >>> foo(arange(3, dtype=int8), 'foo') (array([0, 1, 2], dtype=int8), 'foo') >>> foo(arange(3, dtype=float64), 'foo') # doctest: +NORMALIZE_WHITESPACE ... # doctest: +ELLIPSIS Traceback (most recent call last): ... TypeError: ...foo() expected a value with dtype 'int8' for argument 'x', but got 'float64' instead. """ for name, type_ in iteritems(named): if not isinstance(type_, (dtype, tuple)): raise TypeError( "expect_dtypes() expected a numpy dtype or tuple of dtypes" " for argument {name!r}, but got {dtype} instead.".format( name=name, dtype=dtype, ) ) @preprocess(dtypes=call(lambda x: x if isinstance(x, tuple) else (x,))) def _expect_dtype(dtypes): """ Factory for dtype-checking functions that work with the @preprocess decorator. """ def error_message(func, argname, value): # If the bad value has a dtype, but it's wrong, show the dtype # name. Otherwise just show the value. try: value_to_show = value.dtype.name except AttributeError: value_to_show = value return ( "{funcname}() expected a value with dtype {dtype_str} " "for argument {argname!r}, but got {value!r} instead." ).format( funcname=_qualified_name(func), dtype_str=' or '.join(repr(d.name) for d in dtypes), argname=argname, value=value_to_show, ) def _actual_preprocessor(func, argname, argvalue): if getattr(argvalue, 'dtype', object()) not in dtypes: raise TypeError(error_message(func, argname, argvalue)) return argvalue return _actual_preprocessor return preprocess(**valmap(_expect_dtype, named))
def expect_kinds(**named): """ Preprocessing decorator that verifies inputs have expected dtype kinds. Usage ----- >>> from numpy import int64, int32, float32 >>> @expect_kinds(x='i') ... def foo(x): ... return x ... >>> foo(int64(2)) 2 >>> foo(int32(2)) 2 >>> foo(float32(2)) Traceback (most recent call last): ...n TypeError: foo() expected a numpy object of kind 'i' for argument 'x', but got 'f' instead. # noqa """ for name, kind in iteritems(named): if not isinstance(kind, (str, tuple)): raise TypeError( "expect_dtype_kinds() expected a string or tuple of strings" " for argument {name!r}, but got {kind} instead.".format( name=name, kind=dtype, ) ) @preprocess(kinds=call(lambda x: x if isinstance(x, tuple) else (x,))) def _expect_kind(kinds): """ Factory for kind-checking functions that work the @preprocess decorator. """ def error_message(func, argname, value): # If the bad value has a dtype, but it's wrong, show the dtype # kind. Otherwise just show the value. try: value_to_show = value.dtype.kind except AttributeError: value_to_show = value return ( "{funcname}() expected a numpy object of kind {kinds} " "for argument {argname!r}, but got {value!r} instead." ).format( funcname=_qualified_name(func), kinds=' or '.join(map(repr, kinds)), argname=argname, value=value_to_show, ) def _actual_preprocessor(func, argname, argvalue): if getattrs(argvalue, ('dtype', 'kind'), object()) not in kinds: raise TypeError(error_message(func, argname, argvalue)) return argvalue return _actual_preprocessor return preprocess(**valmap(_expect_kind, named))
def expect_kinds(**named): """ Preprocessing decorator that verifies inputs have expected dtype kinds. Usage ----- >>> from numpy import int64, int32, float32 >>> @expect_kinds(x='i') ... def foo(x): ... return x ... >>> foo(int64(2)) 2 >>> foo(int32(2)) 2 >>> foo(float32(2)) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS Traceback (most recent call last): ... TypeError: ...foo() expected a numpy object of kind 'i' for argument 'x', but got 'f' instead. """ for name, kind in iteritems(named): if not isinstance(kind, (str, tuple)): raise TypeError( "expect_dtype_kinds() expected a string or tuple of strings" " for argument {name!r}, but got {kind} instead.".format( name=name, kind=dtype, )) @preprocess(kinds=call(lambda x: x if isinstance(x, tuple) else (x, ))) def _expect_kind(kinds): """ Factory for kind-checking functions that work the @preprocess decorator. """ def error_message(func, argname, value): # If the bad value has a dtype, but it's wrong, show the dtype # kind. Otherwise just show the value. try: value_to_show = value.dtype.kind except AttributeError: value_to_show = value return ( "{funcname}() expected a numpy object of kind {kinds} " "for argument {argname!r}, but got {value!r} instead.").format( funcname=_qualified_name(func), kinds=' or '.join(map(repr, kinds)), argname=argname, value=value_to_show, ) def _actual_preprocessor(func, argname, argvalue): if getattrs(argvalue, ('dtype', 'kind'), object()) not in kinds: raise TypeError(error_message(func, argname, argvalue)) return argvalue return _actual_preprocessor return preprocess(**valmap(_expect_kind, named))
def test_preprocess_on_method(self, args, kwargs): decorators = [preprocess(a=call(str), b=call(float), c=call(lambda x: x + 1))] for decorator in decorators: class Foo(object): @decorator def method(self, a, b, c=3): return a, b, c @classmethod @decorator def clsmeth(cls, a, b, c=3): return a, b, c self.assertEqual(Foo.clsmeth(*args, **kwargs), ("1", 2.0, 4)) self.assertEqual(Foo().method(*args, **kwargs), ("1", 2.0, 4))
def test_preprocess_on_method(self, args, kwargs): decorators = [ preprocess(a=call(str), b=call(float), c=call(lambda x: x + 1)), ] for decorator in decorators: class Foo: @decorator def method(self, a, b, c=3): return a, b, c @classmethod @decorator def clsmeth(cls, a, b, c=3): return a, b, c self.assertEqual(Foo.clsmeth(*args, **kwargs), ('1', 2.0, 4)) self.assertEqual(Foo().method(*args, **kwargs), ('1', 2.0, 4))
def test_preprocess_on_method(self, args, kwargs): decorators = [ preprocess(a=call(str), b=call(float), c=call(lambda x: x + 1)), ] for decorator in decorators: class Foo(object): @decorator def method(self, a, b, c=3): return a, b, c @classmethod @decorator def clsmeth(cls, a, b, c=3): return a, b, c assert Foo.clsmeth(*args, **kwargs) == ("1", 2.0, 4) assert Foo().method(*args, **kwargs) == ("1", 2.0, 4)
class PanelBarReader(SessionBarReader): """ Reader for data passed as Panel. DataPanel Structure ------- items : Int64Index Asset identifiers. Must be unique. major_axis : DatetimeIndex Dates for data provided provided by the Panel. Must be unique. minor_axis : ['open', 'high', 'low', 'close', 'volume'] Price attributes. Must be unique. Attributes ---------- The table with which this loader interacts contains the following attributes: panel : pd.Panel The panel from which to read OHLCV data. first_trading_day : pd.Timestamp The first trading day in the dataset. """ @preprocess(panel=call(verify_indices_all_unique)) @expect_element(data_frequency={'daily', 'minute'}) def __init__(self, trading_calendar, panel, data_frequency): panel = panel.copy() if 'volume' not in panel.minor_axis: # Fake volume if it does not exist. panel.loc[:, :, 'volume'] = int(1e9) self.trading_calendar = trading_calendar self._first_trading_day = trading_calendar.minute_to_session_label( panel.major_axis[0]) last_trading_day = trading_calendar.minute_to_session_label( panel.major_axis[-1]) self.sessions = trading_calendar.sessions_in_range( self.first_trading_day, last_trading_day) if data_frequency == 'daily': self._calendar = self.sessions elif data_frequency == 'minute': self._calendar = trading_calendar.minutes_for_sessions_in_range( self.first_trading_day, last_trading_day) self.panel = panel sessions = None @property def last_available_dt(self): return self._calendar[-1] trading_calendar = None def load_raw_arrays(self, columns, start_dt, end_dt, assets): cal = self._calendar return self.panel.loc[list(assets), start_dt:end_dt, list(columns)].reindex( major_axis=cal[cal.slice_indexer( start_dt, end_dt)]).values.T def get_value(self, sid, dt, field): """ Parameters ---------- sid : int The asset identifier. day : datetime64-like Midnight of the day for which data is requested. field : string The price field. e.g. ('open', 'high', 'low', 'close', 'volume') Returns ------- float The spot price for colname of the given sid on the given day. Raises a NoDataOnDate exception if the given day and sid is before or after the date range of the equity. Returns -1 if the day is within the date range, but the price is 0. """ return self.panel.loc[sid, dt, field] def get_last_traded_dt(self, asset, dt): """ Parameters ---------- asset : zipline.asset.Asset The asset identifier. dt : datetime64-like Midnight of the day for which data is requested. Returns ------- pd.Timestamp : The last know dt for the asset and dt; NaT if no trade is found before the given dt. """ try: return self.panel.loc[int(asset), :dt, 'close'].last_valid_index() except IndexError: return NaT @property def first_trading_day(self): return self._first_trading_day
class PanelDailyBarReader(DailyBarReader): """ Reader for data passed as Panel. DataPanel Structure ------- items : Int64Index Asset identifiers. Must be unique. major_axis : DatetimeIndex Dates for data provided provided by the Panel. Must be unique. minor_axis : ['open', 'high', 'low', 'close', 'volume'] Price attributes. Must be unique. Attributes ---------- The table with which this loader interacts contains the following attributes: panel : pd.Panel The panel from which to read OHLCV data. first_trading_day : pd.Timestamp The first trading day in the dataset. """ @preprocess(panel=call(verify_indices_all_unique)) def __init__(self, calendar, panel): panel = panel.copy() if 'volume' not in panel.minor_axis: # Fake volume if it does not exist. panel.loc[:, :, 'volume'] = int(1e9) self.first_trading_day = panel.major_axis[0] self._calendar = calendar self.panel = panel @property def last_available_dt(self): return self._calendar[-1] def load_raw_arrays(self, columns, start_date, end_date, assets): columns = list(columns) cal = self._calendar index = cal[cal.slice_indexer(start_date, end_date)] shape = (len(index), len(assets)) results = [] for col in columns: outbuf = zeros(shape=shape) for i, asset in enumerate(assets): data = self.panel.loc[asset, start_date:end_date, col] data = data.reindex_axis(index).values outbuf[:, i] = data results.append(outbuf) return results def spot_price(self, sid, day, colname): """ Parameters ---------- sid : int The asset identifier. day : datetime64-like Midnight of the day for which data is requested. colname : string The price field. e.g. ('open', 'high', 'low', 'close', 'volume') Returns ------- float The spot price for colname of the given sid on the given day. Raises a NoDataOnDate exception if the given day and sid is before or after the date range of the equity. Returns -1 if the day is within the date range, but the price is 0. """ return self.panel.loc[sid, day, colname] def get_last_traded_dt(self, sid, dt): """ Parameters ---------- sid : int The asset identifier. dt : datetime64-like Midnight of the day for which data is requested. Returns ------- pd.Timestamp : The last know dt for the asset and dt; NaT if no trade is found before the given dt. """ while dt in self.panel.major_axis: freq = self.panel.major_axis.freq if not isnull(self.panel.loc[sid, dt, 'close']): return dt dt -= freq else: return NaT