momentum-scanner
Short-term momentum on NSE/BSE stocks across a whole universe: momentum-burst days (a 4%+ up-close out of a quiet base on rising volume, near the high, above a rising 50 DMA, not already extended), ep
SKILL.mdskills/momentum-scanner/SKILL.md
GitHubMomentum Scanner (NSE/BSE)
Find what is moving now: a burst out of a quiet base, a news gap the market re-prices, or a leader
whose RS line makes a new high before its price. This skill finds candidates; breakout-planner
reads the base and builds the order.
Commands
python3 scripts/momentum.py burst --csv-dir data/ --days 5 --show-rejects
python3 scripts/momentum.py pivot --csv-dir data/ --catalyst DIXON=results --catalyst KAYNES=order-win
python3 scripts/momentum.py rs --csv-dir data/ --benchmark-csv data/nifty.csv --top 20
python3 scripts/momentum.py scan --csv-dir data/ --benchmark-csv nifty.csv --bands bands.csv --regime confirmed
python3 scripts/momentum.py scan --symbols DIXON,KAYNES,TRENT,POLYCAB --benchmark NIFTY # yfinance
The universe flags match breakout.py scan: --csv-dir + --pattern (file name = symbol),
--csv FILE (repeatable) or --symbols. Also --as-of YYYY-MM-DD (replay a date),
--min-turnover-cr (5), --bands FILE (SYMBOL,band with 2/5/10/20, or 0 for F&O names with
no fixed band) and --json. Use 260+ daily bars (64 is the minimum for RS). Blank or zero candles
are skipped. Bad input exits 2 with a one-line error:.
Reading burst (last 5 sessions, --days)
| Test | Default (flag) |
|---|---|
| Move | Close ≥ +4% vs the previous close (--min-move-pct) |
| Volume | Above the previous session and above the 50-day average (the 50 sessions before) |
| Close | In the top 70% of the day's range (--min-close-pos) |
| Quiet base | 3+ sessions right before it inside an 8% high-low band (--min-base-days, --max-base-pct), with daily ranges no wider than the 20 sessions before (--max-range-ratio 1.0) |
| Not extended | Up no more than 6% in the 3 sessions before (--max-run-pct) |
| Trend | Close above a 50 DMA that is higher than 10 sessions ago |
| Liquidity | ≥ ₹5 crore average traded value over the 20 sessions before the burst, so a one-day spike can't pass an illiquid stock |
Score /100: move 25, volume 20, close 15, base length 10, range contraction 15, 50 DMA above 200
DMA 10, delivery at or above average 5, minus flag penalties. Plan reference: buy above the
burst-day high, stop at its low. A burst is a 3-5 day trade: book partials fast, exit if the low
breaks. --show-rejects lists near-misses and why (extended, illiquid, no base).
Reading pivot (last 10 sessions)
Open ≥ 5% above the previous close (--min-gap-pct) on ≥ 3× the 50-day volume (--min-vol-mult),
with no close below the gap-day low since. Day 1: strong if it closed above the open near the
high, weak if sellers took it back to the low. Day 2: follow-through, holding, tested the low,
or failed. A gap that gets filled, or a stock already up 40%+ in the 60 sessions before, scores
lower. The open comes from NSE's pre-open call auction (orders 09:00-09:08, trading from 09:15),
so don't chase the first minutes. Buy above the gap-day high or the opening-range high, stop under
the gap-day low.
Catalyst checklist. Pass what you have verified: --catalyst SYM=results|order-win|block-deal|approval|rating-upgrade|other
(a bare --catalyst results applies to every name). Results beats with margin expansion and order
wins large against revenue carry the most weight. For a block deal, check who sold. A gap with no
catalyst is a burst, not a pivot, and in small caps it can be operator-driven.
Reading rs
Weighted return = 0.4 × 3-month + 0.2 × 6-month + 0.2 × 9-month + 0.2 × 12-month (63/126/189/252
sessions, cumulative). The latest quarter sits inside all four, so recent strength counts most. The
rating is the percentile rank inside your universe, from 1 to 99. Rank NIFTY 500 or a full
watchlist, because ten names give coarse ratings. Stocks with less history are re-weighted over the
horizons they have and marked partial. With a benchmark, the RS line (stock ÷ NIFTY) is checked for
a new 52-week high in the last 5 sessions (--rs-high-days). New high ahead of price is the
leader's tell. A price high without an RS-line high is a laggard riding the index. The output also
shows where the benchmark itself would rate (use NIFTY Midcap 150 for midcaps).
scan: the watchlist
Bursts, pivots and liquid RS leaders (RS ≥ 85 --leader-rs, within 10% of the high, above the 50
DMA, RS line at a high) go into one list ranked by signal strength (60%), RS rating (30%) and RS-line and high bonuses, minus
circuit and band penalties. Each name gets a one-line reason. The top tradable names (no circuit or
band flag) get a ready breakout.py check command (see ../breakout-planner/scripts/breakout.py)
to find the base, pivot, stop and order. --regime takes the market-regime label and prints the
gate: Correction means no new momentum trades.
India specifics
- Results season (mid-Jan, Apr-May, Jul-Aug, Oct-Nov) is when most real pivots happen. Gaps around the result date are the signal. A burst just before results is a coin toss.
- Upper circuit. A close at the high on a band-sized move (2/5/10/20%) is flagged
UC?(inferred) orUC(band from--bands). Buyers queued unfilled, so the close isn't a price you could pay, and the next open usually gaps.--exclude-lockeddrops these closes. - 2%/5% bands (flag
band2/band5, inferred when the tape keeps closing exactly ±2/5%) mean surveillance (ASM/GSM), trade-for-trade (BE/T2T) or SME. These names have no intraday or BTST, need 100% upfront margin and often have no MTF, and their exits can lock at the lower circuit. Operator and SME pumps live here: vertical moves, circuit after circuit, low delivery, no news. Skip them. - Delivery %. If the CSV has an NSE delivery column (
DELIV_PER,% Dly Qt to Traded Qty, or delivery quantity), a burst on below-average delivery is flagged as intraday churn.--min-delivery-pctmakes it a filter. - Expiry-week noise. Bursts in the week of the last-Tuesday F&O monthly expiry are tagged
expiry-wk. Rollover and short covering in F&O names, and NIFTY's weekly Tuesday expiry, can fake one-day strength. Wait for a second day.
Workflow
- Run
../market-regime/scripts/regime.py status(market-regime). Trade bursts only when the regime allows new longs, and stay inside its position count. - Run
scanon the universe, read the reasons, and drop flagged names. - Hand the top names to
breakout-planner(check, thenplan) for the stop, trigger and GTT. - Size with
position-sizing(../position-sizing/scripts/risk.py). Bursts are short trades, so check the round trip withtrading-costs. - Run the
trading-disciplinegate (../trading-discipline/scripts/discipline.py) before any order. After entry,trailing-stopstakes over.
Output
# Symbol Close RS vs 52wH Score Signals [flags] + "Why:" one reason per name
Next: python3 .../breakout.py check --csv SYMBOL.csv --benchmark-csv nifty.csv
Limits: daily bars only, so there's no intraday pre-open data or live circuit status. Bands are
inferred unless you pass --bands, and an F&O stock up exactly 10% at its high can be a false
UC?. Catalysts are whatever you supply. RS ranks only the universe you give it.
Educational analysis, not investment advice.