The strategy code is provided in winners.py.
To "install" the strategy, execute the following cell to move the strategy file to the /codeload/zipline
directory, where Zipline looks:
The ! sytax below lets us execute terminal commands from inside the notebook.
# make directory if doesn't exist
!mkdir -p /codeload/zipline
!mv winners.py /codeload/zipline/
We define our pipeline in a helper function called make_pipeline
, using code copied from an earlier notebook:
def make_pipeline():
"""
Create a pipeline that filters by dollar volume and
calculates 1-year return.
"""
pipeline = Pipeline(
columns={
"1y_returns": Returns(window_length=252),
},
screen=AverageDollarVolume(window_length=30) > 10e6
)
return pipeline
In the initialize
function (required in all Zipline strategies), we attach the pipeline to the algorithm, and we schedule a custom function called rebalance
that will run every market day 30 minutes before the close:
def initialize(context):
"""
Called once at the start of a backtest, and once per day at
the start of live trading.
"""
# Attach the pipeline to the algo
algo.attach_pipeline(make_pipeline(), 'pipeline')
# Rebalance every day, 30 minutes before market close.
algo.schedule_function(
rebalance,
algo.date_rules.every_day(),
algo.time_rules.market_close(minutes=30),
)
In before_trading_start
, another built-in function which Zipline calls once per day before the market opens, we gather the pipeline output for that day and select our winners (copying code from an earlier notebook):
def before_trading_start(context, data):
"""
Called every day before market open.
"""
factors = algo.pipeline_output('pipeline')
# Get the top and bottom 3 stocks by 1-year return
returns = factors["1y_returns"].sort_values(ascending=False)
context.winners = returns.index[:3]
Finally, in the custom rebalance
function which we scheduled to run before the close, we calculate the intraday returns (again copying code from an earlier notebook) and add logic for the entering and exiting of positions:
def rebalance(context, data):
# calculate intraday returns for our winners
current_prices = data.current(context.winners, "price")
prior_closes = data.history(context.winners, "close", 2, "1d").iloc[0]
intraday_returns = (current_prices - prior_closes) / prior_closes
positions = context.portfolio.positions
# Exit positions we no longer want to hold
for asset, position in positions.items():
...