A common need when using the pipeline API is the ability to apply a simple mathematical function to every value produced by a Factor
. This operation is so common, in fact, that the Factor
base class has a large number of methods for applying common scalar transformations.
A useful application of this functionality is calculating daily log-returns, which are given by taking log(1 + return)
.
import numpy as np
from quantopian.research import run_pipeline
from quantopian.pipeline import Pipeline
from quantopian.pipeline.factors import Factor, Returns, CustomFactor
The Pipeline API comes with a builtin factor for simple close-to-close returns.
# window_length is 2 because daily returns are calculated by comparing two days' worth of close prices.
daily_returns = Returns(window_length=2)
We can build a LogReturns factor relatively easily using CustomFactor
...
class LogReturns(CustomFactor):
inputs = [daily_returns]
window_length=1
def compute(self, today, assets, out, returns):
# This is equivalent to, but slightly faster than `out[:] = np.log1p(returns)`.
# Many numpy ufuncs provide an `out` parameter for speedups when
# the desired behavior is to copy the result of a calculation into an already-
# existing array.
np.log1p(returns.ravel(), out=out)
manual_log_returns = LogReturns()
... but we don't actually need to! Factor
has a log1p
method that behaves identically to our custom LogReturns
.
builtin_log_returns = daily_returns.log1p()
pipe = Pipeline({
'returns': daily_returns,
'manual_log': manual_log_returns,
'builtin_log': builtin_log_returns,
})
pipe.show_graph('png')
result = run_pipeline(pipe, '2014', '2014-02')
result.head(10)
(result.manual_log.fillna(0.) == result.builtin_log.fillna(0.)).all()
Under the hood, Factor
uses the excellent numexpr library to efficiently execute scalar transformations of pipeline values (incidentally, this is also how most of the binary operators like +
and -
work on Factor
).
As of the time of this writing, the full list of the supported numexpr scalar operations is defined in Zipline here:
[
Factor.abs,
Factor.arccos,
Factor.arccosh,
Factor.arcsin,
Factor.arcsinh,
Factor.arctan,
Factor.arctanh,
Factor.cos,
Factor.cosh,
Factor.exp,
Factor.expm1,
Factor.log,
Factor.log10,
Factor.log1p,
Factor.sin,
Factor.sinh,
Factor.sqrt,
Factor.tan,
Factor.tanh,
]
Most of these probably aren't useful (I'm not sure who would want to take the inverse cosine of a price series), but there are certainly applications for log*
, exp*
, and sqrt
. We get the rest for free with some fancy metaprogramming tricks, so if you really want to, you can calculate inverse-hyperbolic-tangent-returns :).