Skip to content
All library documents

Monthly Long-Only Stock Selection with a Borrow Fee Filter

Article Strategy library · Author: QuantRocket

Summary

This example builds a monthly rebalanced U.S. common-stock portfolio. Its pipeline screens for stocks in the middle portion of a 90-day average dollar-volume ranking and, when the fee limit is enabled, excludes names whose recorded borrow fee exceeds the configured ceiling. At rebalance, it exits holdings that leave the selected universe and allocates an equal fraction of portfolio value to each remaining stock using market orders.

The code illustrates how to combine liquidity and borrow-cost data in a pipeline universe, then translate that universe into portfolio orders. It supplies no backtest results or evidence that the filters improve returns. The portfolio is long-only despite using borrow-fee data, and the example does not describe transaction-cost, slippage, concentration, or failed-order handling; market availability and the borrow-fee feed may also constrain real use.

Key ideas

  • A pipeline limits candidates to common stocks and a specified average dollar-volume percentile range.
  • An optional maximum borrow-fee condition removes stocks with fees above the configured threshold.
  • The strategy rebalances at the start of each month and exits holdings outside the current selection.
  • Selected stocks receive equal target portfolio weights through market orders.

Tags

Full text
# avoid-high-borrow


# avoid-high-borrow









## Source (Apache-2.0)

```python
# Copyright 2024 QuantRocket LLC - All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

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.
    """
    # Attach the pipeline to the algo
    algo.attach_pipeline(make_pipeline(), 'pipeline')

    # Rebalance monthly
    algo.schedule_function(
        rebalance,
        algo.date_rules.month_start(),
    )

def make_pipeline():
    """
    Create a pipeline that filters by dollar volume and borrow fee.
    """
    # limit initial universe to common stocks
    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

    # Exit positions we no longer want to hold
    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())

    # Enter long positions
    for asset in desired_stocks:

        # allocate 1/Nth of capital per asset
        algo.order_target_percent(asset, 1/len(desired_stocks), style=MarketOrder())
        
```

Shown in full with attribution under the source's licence. Licence: Apache-2.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.