US examples
52-week high momentum
On this page4
Buy US stocks that close at a new 200-day high and let the trend run. It builds on the tendency of stocks making new highs to keep rising, a well-documented anomaly in academic finance, and suits investors who want a simple trend-following strategy.
Strategy logic
- Buy stocks whose closing price is at a new 200-day high. 200 trading days is roughly one calendar year (52 weeks), so this is close to a 52-week high breakout.
- Rebalance every two weeks.
- Put at most 20% of the portfolio in any one stock.
- Sell a stock automatically if it falls 20% from its entry price.
Code
strategy.py
from finlab import data
from finlab.backtest import sim
from finlab.markets.us import USMarket
data.set_market('us')
close = data.get('price:adj_close')
close = close[close.index.dayofweek < 5] # remove weekends
# Stock price at 200-day high
position = close == close.rolling(200).max()
# Biweekly rebalancing, 20% max position per stock, 20% stop-loss
report = sim(
position,
resample='2W',
position_limit=0.2,
stop_loss=0.2,
market=USMarket(),
fee_ratio=0.001,
tax_ratio=0,
)
report.display()How to adjust it
rolling(200).max(): the 200-day rolling maximum price. A stock equals it only when it is at a new high. Change 200 to look for a shorter or longer high.resample='2W': rebalances every two weeks. A longer holding period gives breakout trades time to develop while keeping turnover manageable.position_limit=0.2: caps each stock at 20% of the portfolio, so no single name dominates.stop_loss=0.2: sells a position that drops 20% from its entry price, to limit downside risk.
Keep only highs that hold
The second strategy, "sustained new high", replaces the position line and keeps everything else the same:
# At least 3 of the last 5 days at a 200-day high
position = (close == close.rolling(200).max()).sustain(5, 3)sustain(5, 3) requires the stock to have hit a 200-day high on at least 3 of the last 5 trading days. It removes stocks that only briefly touched a new high before pulling back and keeps those that stay strong near the top of their range. This variant is more selective: it tends to hold fewer but higher-conviction positions.
Related pages
- Quickstart A first backtest built on the same new-high idea.
- Add a market switch Go to cash when market breadth turns bearish.
- Write better rules
sustain,is_largestand other FinlabDataFrame tools. - Tune the backtest Rebalance frequency, stops and position limits in
sim().
Was this page helpful?