Docs
Open Studio

US examples

Long-short hedge

On this page4

Go long cheap value stocks and short SPY (the S&P 500 ETF) to hedge against broad market declines. It suits investors who worry about a market drop but want to keep their value stocks rather than sell them.

Strategy logic

  1. Long leg (70% of capital): buy the stocks in the lowest 20% by price-to-book ratio, the cheapest value stocks in the market. quantile_row computes the cross-sectional percentile on each date, and the qualifying stocks are equally weighted.
  2. Short leg (30% of capital): short SPY as a market hedge. SPY is an ETF, so it is backtested in the us_fund market.
  3. Combine: Portfolio joins the two backtests at 70% and 30%. Both legs rebalance quarterly.

Net exposure is 40% (70% − 30%), much less market risk than a long-only book.

Code

strategy.py
from finlab import data
from finlab import backtest
from finlab.portfolio import Portfolio

# Long leg: lowest 20% by price-to-book ratio
data.set_market('us')
market_value = data.get('etl:us_market_value')
equity = data.get('us_balance_sheet:total_stockholders_equity')
pb = market_value / equity
pb = pb[pb > 0]  # Negative equity is distress, not value

long_position = pb < pb.quantile_row(0.2)
long_report = backtest.sim(long_position, resample='Q')

# Hedge leg: short SPY (ETFs trade in the us_fund market)
data.set_market('us_fund')
spy = data.get('price:adj_close')[['SPY']]
short_position = -spy.notna().astype(float)
short_report = backtest.sim(short_position, resample='Q')

# 70% long value stocks, 30% short SPY
portfolio = Portfolio(
    {
        'long value': (long_report, 0.7),
        'short SPY': (short_report, 0.3),
    }
)
portfolio.display()

How to adjust it

  • market_value / equity: price-to-book from daily market value and quarterly stockholders' equity (aligned to each SEC filing date). Non-positive values are dropped.
  • pb < pb.quantile_row(0.2): stocks whose price-to-book is in the bottom 20th percentile across all stocks on each date, the classic "deep value" screen. sim() equal-weights the selected stocks. Change 0.2 to make the value bucket wider or narrower.
  • -spy.notna().astype(float): a −100% SPY position for the hedge leg. SPY is used because it is the most liquid US equity ETF and closely tracks the broad market.
  • Portfolio({...: (report, weight)}): gives 70% of capital to the long leg and 30% to the short-SPY leg, a fixed −30% SPY hedge. Net exposure is the long weight minus the short weight.
  • resample='Q': rebalances quarterly to keep turnover and transaction costs low.
↑↓ Move Enter Open Esc Close