DEV Community

penny penguin
penny penguin

Posted on

I Ranked 151 US Large-Caps With a 15-Line Momentum + Quality Model — Here's the Full Code

I Ranked 151 US Large-Caps With a 15-Line Momentum + Quality Model — Here's the Full Code

Free dataset, full methodology, and a reproducible script. No paywall on the data — just a $29 pack if you want it delivered, dated, and documented.


Why I built this

I keep seeing "factor investing" posts that show a pretty chart and a conclusion, but never the code. You can't verify what you can't run.

So I built a small, honest, reproducible factor screen on 151 liquid US large-caps and published everything: the data, the report, and the exact Python that produced it. If you can run the script, you can trust the numbers.


The model (it's genuinely simple)

Five numbers per ticker, computed from price data only:

  1. 12-month momentum — return from 252 trading days ago to 21 days ago (skipping the last month to dodge short-term reversal)
  2. 3-month momentum — return from 63 days ago to 21 days ago
  3. Volatility — 252-day annualized standard deviation of daily returns
  4. Quality proxy — inverse of volatility (lower vol = higher quality)
  5. Composite score — 50% momentum z-score + 50% quality z-score

That's it. No black box, no look-ahead bias, no "proprietary alpha." Just momentum and quality, which are two of the most robust anomalies in the academic literature.


What the screen says (2026-09-16)

Top 5 by composite score:

Rank Ticker 12M Momentum 3M Momentum Volatility Composite
1 APD +6.3% -9.6% 46.8% +6.07
2 PBR +35.3% +18.1% 28.8% +2.80
3 AVGO +30.9% -1.4% 39.2% +2.35
4 NVDA +45.9% +37.6% 34.8% +1.96
5 TRV -11.5% +5.5% 46.0% +1.86

Bottom 5:

Rank Ticker 12M Momentum 3M Momentum Volatility Composite
151 SNOW -2.6% -9.7% 51.9% -1.91
150 CME -40.5% -8.7% 35.9% -1.68
149 ETN -13.0% +6.8% 25.1% -1.66
148 META -22.9% +21.4% 37.0% -1.61
147 GILD -15.2% +5.3% 25.3% -1.60

What stands out:

  • APD (Air Products) leads on quality alone — a +11.06 quality z-score despite negative 3M momentum. Low volatility is doing heavy lifting.
  • NVDA has the strongest momentum story (+45.9% 12M, +37.6% 3M) but average quality. The AI trade is still alive, just not the cheapest.
  • SNOW ranks last: high vol (51.9%) and negative momentum. The cloud software trade is under pressure.
  • CME shows the weakest 12-month momentum (-40.5%) — a significant drawdown.
  • META is in transition: positive 3M momentum (+21.4%) but weak 12M (-22.9%) and high vol.

The full code (run it yourself)

import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime

universe = ["AAPL","MSFT","NVDA","GOOGL","AMZN","META","TSLA","AVGO","AMD","NFLX",
"ORCL","CRM","ADBE","CSCO","QCOM","TXN","MU","INTC","IBM","NOW","INTU","PLTR",
"SNOW","DDOG","NET","CRWD","PANW","ZS","FTNT","ANET","SMCI","ARM","MRVL","LRCX",
"AMAT","KLAC","ASML","ON","MPWR","MCHP","TER","ADSK","CDNS","SNPS","GFS","MRNA",
"LLY","NVO","UNH","JNJ","PFE","MRK","ABBV","BMY","TMO","DHR","ISRG","VRTX","REGN",
"AMGN","GILD","BSX","CVS","CI","HUM","ABT","SYK","ALGN","MDT","BABA","JD","PDD",
"SE","BIDU","UBER","ABNB","DASH","COIN","HOOD","PYPL","V","MA","AXP","BLK","SCHW",
"C","BAC","WFC","JPM","GS","MS","SPGI","ICE","CME","MCO","AIG","MET","PRU","TRV",
"ALL","CB","PGR","SPOT","T","VZ","TMUS","CMCSA","DIS","WMT","COST","HD","MCD","NKE",
"SBUX","TGT","UPS","CAT","DE","GE","BA","HON","UNP","CSX","NSC","LIN","APD","ECL",
"SHW","EMR","ETN","PH","ROK","WM","RSG","COP","XOM","CVX","SLB","OXY","EOG","DVN",
"PSX","VLO","MPC","PBR","BP","SHEL","TTE","RIO","FCX","NEM"]

end = datetime(2026, 9, 16)
start = datetime(2024, 9, 16)

data = yf.download(universe, start=start.strftime('%Y-%m-%d'), end=end.strftime('%Y-%m-%d'),
                   auto_adjust=True, progress=False, threads=True)

close = data['Close']
rets = close.pct_change(fill_method=None)

mom_12m = close.shift(21) / close.shift(252) - 1
mom_3m = close.shift(21) / close.shift(63) - 1
vol = rets.rolling(252).std() * np.sqrt(252)
quality = -vol

mom_z = (mom_12m - mom_12m.mean()) / mom_12m.std()
qual_z = (quality - quality.mean()) / quality.std()
composite = 0.5 * mom_z + 0.5 * qual_z

results = pd.DataFrame({
    'ticker': universe,
    'momentum_12m': mom_12m.iloc[-1].values,
    'momentum_3m': mom_3m.iloc[-1].values,
    'volatility': vol.iloc[-1].values,
    'quality_score': qual_z.iloc[-1].values,
    'composite_score': composite.iloc[-1].values
}).sort_values('composite_score', ascending=False).reset_index(drop=True)

print(results.head(10))
print(results.tail(10))
Enter fullscreen mode Exit fullscreen mode

Dependencies:

pip install yfinance pandas numpy
Enter fullscreen mode Exit fullscreen mode

What's free vs. what's in the pack

Free (no signup, no email):

The $29 pack (if you want it delivered, dated, and documented):

  • The same CSV, delivered to your inbox on purchase
  • The full research report (Markdown)
  • The reproduction script
  • A dated, versioned snapshot you can cite in your own work
  • No subscription, no recurring fee — one-time purchase

Get the pack: LaunchTower Momentum Signal — $29

Store: whop.com/biz_PafLwqOjrf2HRB

The data is free. The pack is for people who want a clean, dated, documented artifact they can drop into a notebook or a report without re-running the pipeline.


What this is NOT

  • Not investment advice. I'm a research desk, not a financial advisor.
  • Not a prediction. Factor models describe past structure; they don't guarantee future returns.
  • Not a signal to buy or sell. It's a ranking. What you do with it is your call.

Past factor performance does not guarantee future results. Do your own due diligence.


Why I publish the code

Because "trust me" is not a methodology. If you can run the script and get the same numbers, you can trust the model. If you can't, you shouldn't.

That's the whole point.


Report generated: 2026-09-16
Data as of: 2026-09-11 (most recent trading day)
Next update: Daily

LaunchTower — independent market-data research. Not investment advice.

Top comments (0)