Our trading strategy will buy recent winners as computed by our end-of-day pipeline. But we will try to improve the strategy performance by adding an intraday twist: we will only buy if the security is down for the day. In other words, we will enter positions on a counter-move.
Testing the performance of intraday trading rules generally requires running a full backtest. However, to facilitate writing the code, you can access intraday data in a notebook using the same API that is available in a Zipline strategy. This allows you to get your code semantics right before transitioning to a backtest.
In a Zipline strategy, two parameters are passed to user-defined functions: the context
parameter, which provides access to account and portfolio details and also allows users to store custom variables about the algorithm's state, and the data
parameter, which is used to access intraday (and optionally end-of-day) price data:
import zipline.api as algo
# click on Context or BarData and press control for more details about the object
def handle_data(context: algo.Context, data: algo.BarData):
...
The data
parameter passed to Zipline functions is always tied to the current simulation minute. That is, if it is currently 2020-07-01 at 3:30 PM within the backtest simulation, the data
object allows you to query prices as of that minute and looking backward from that minute.
You can access the data
object in notebooks by specifying a particular "as-of" minute you want to use:
from zipline.research import get_data
data = get_data("2020-07-01 15:30:00") # no bundle specified, so the default bundle will be used
The data
object's methods take one or more Zipline assets (zipline.assets.Asset
) as their first argument. There are two ways to get assets in a notebook.
The first option is to run a pipeline and get the assets from the factor data. For example, using our previous pipeline, we could have accessed assets like this:
factors = run_pipeline(pipeline, start_date="2018-01-01", end_date="2012-01-01")
assets = factors.xs("2018-01-02").index
The second option, which we will demonstrate here, is to use the symbol
function to load asset objects by symbol.
from zipline.research import symbol
aapl = symbol("AAPL") # no bundle specified, so the default bundle will be used
jnj = symbol("JNJ")
Now we can use the data
object to calculate the intraday return as of the simulation minute we chose:
current_prices = data.current([aapl, jnj], "price")
prior_closes = data.history([aapl, jnj], "close", 2, "1d").iloc[0]
intraday_returns = (current_prices - prior_closes) / prior_closes
intraday_returns
Equity(FIBBG000B9XRY4 [AAPL]) -0.000713 Equity(FIBBG000BMHYD1 [JNJ]) 0.001387 dtype: float64
We will later transfer this snippet of code to our Zipline .py
file, where it will be used to determine whether to enter.