import zipline.api as algo
from zipline.pipeline import Pipeline, ibkr, master
from zipline.pipeline.factors import AverageDollarVolume
from zipline.finance.execution import MarketOrder
BUNDLE = "usstock-1d-bundle"
MAX_BORROW_FEE = 0.3
def initialize(context: algo.Context):
"""
Called once at the start of a backtest, and once per day in
live trading.
"""
algo.attach_pipeline(make_pipeline(), 'pipeline')
algo.schedule_function(
rebalance,
algo.date_rules.month_start(),
)
def make_pipeline():
"""
Create a pipeline that filters by dollar volume and borrow fee.
"""
universe = master.SecuritiesMaster.usstock_SecurityType2.latest.eq("Common Stock")
screen = AverageDollarVolume(window_length=90).percentile_between(50, 75)
if MAX_BORROW_FEE:
screen &= (ibkr.BorrowFees.FeeRate.latest <= MAX_BORROW_FEE)
pipeline = Pipeline(
initial_universe=universe,
screen=screen
)
return pipeline
def rebalance(context: algo.Context, data: algo.BarData):
"""
Execute orders according to our schedule_function() timing.
"""
desired_stocks = algo.pipeline_output('pipeline').index
positions = context.portfolio.positions
for asset, position in positions.items():
if asset not in desired_stocks and data.can_trade(asset):
algo.order_target_value(asset, 0, style=MarketOrder())
for asset in desired_stocks:
algo.order_target_percent(asset, 1/len(desired_stocks), style=MarketOrder())