Skip to content

Momentum

An internal research tool that screens the market once per trading day for stocks in a confirmed, accelerating uptrend — what Chinese technical traders call a 主升浪 ("main rising wave"). This page documents the exact algorithm: every signal, every formula, and every weight.

Descriptive screening, not advice

The screener is an operator-only lab feature — it is not part of the regular StockClaw app. Candidate selection is a pure, deterministic algorithm over daily OHLCV data; the LLM only writes descriptive commentary afterwards and can never add, remove, or rank a stock. Output is an algorithmic screening result for information only. It is not investment advice.

Architecture: three strictly separated layers

Layer What it does What it can NOT do
1. Quant screen Deterministic signal math over daily bars. Same input → same output, always. No LLM anywhere in this layer.
2. LLM read-out Writes 2–4 descriptive sentences (中文 + English) per candidate the quant layer already picked. Cannot pick, drop, re-rank, or invent tickers; cannot change any number. Output mentioning any other stock or advisory wording ("recommend", "买点"…) is rejected and falls back to metrics-only.
3. Snapshot Caches the daily result; pushes a Top-5 summary to the operator's Telegram.

Universe

The core production universe is S&P 500 ∪ Nasdaq 100 (deduplicated, roughly 518 tickers), plus a hand-maintained watchlist for anything outside those indices. Membership is bootstrapped from static CSVs and refreshed periodically from the index provider lists. Momentum Discovery is broader: it reads the grouped-daily DuckDB bars table, keeps symbols with enough history, minimum price, common-stock-like symbol shape, and minimum dollar liquidity, then reports its own expanded universe size.

Daily bars come from one bulk grouped-daily request per trading day (whole US market in a single API call), stored in DuckDB. The screener evaluates the last 120 trading sessions per symbol; a symbol needs at least 65 sessions of history to be screenable.

Two keyless public sources add context (they never enter the score): FINRA's daily Reg SHO files provide per-symbol off-exchange (TRF) and short volume — shown as off_exchange_share_20d and short_vol_ratio_20d (published evenings ET, so always one session behind) — and CBOE's VIX history feeds the market-summary layer.

On unlimited (paid) market-data plans two further unscored context columns appear: close_vs_vwap_pct (close relative to the session's volume-weighted average price, from the daily bar) and late_day_volume_share (share of regular-session volume traded in the final 30 minutes, from per-candidate 1-minute aggregates — institutions concentrate execution into the closing window). Throttled plans simply omit them.

FMP Premium and Unusual Whales are different: when configured, they can contribute a bounded paid-data confirmation overlay to the main leaderboard after the technical score has been computed. The overlay is volume-gated, capped, and visible in the expanded row, so users can see both the base technical score and the FMP/UW subscores that affected the final rank.

The six signals

All windows are trading sessions, all prices are split/dividend-adjusted closes. "MAₙ" is the trailing simple moving average over n sessions.

1. Moving-average alignment (均线多头排列) — boolean

close > MA20 > MA50   AND   MA20 > MA20[-5]   AND   MA50 > MA50[-5]

Price above a rising MA20, which is above a rising MA50 ("[-5]" = the value 5 sessions ago). Filters out dead-cat bounces inside downtrends.

2. Consolidation breakout to a new high (平台突破创新高) — boolean

True if any session d within the last 5 closed above every close of the 60 sessions before d — i.e. it cleared the consolidation ceiling and printed a fresh 60-day high. The first such session anchors the volume check below.

3. Volume confirmation (放量确认) — continuous ratio

vol_surge = mean(volume from breakout day onward)
          ÷ mean(volume of the 20 sessions before the breakout day)

Without a breakout, it degrades to latest volume ÷ prior 20-session average. A ratio ≥ 1.5× counts as confirmation. This is the screener's direct read on whether real money — including institutions — is participating in the move: conviction buying shows up as expanding on-exchange volume.

4. Slope acceleration (斜率加速) — continuous ratio

The core quantitative definition of an accelerating wave:

accel = OLS_slope(last 5 closes) ÷ OLS_slope(last 20 closes)
        (requires both slopes > 0, otherwise accel = 0)

Both slopes are ordinary least-squares linear regressions of close vs. session index. A ratio > 1.5 means the last week is climbing meaningfully faster than the last month — the move is steepening, not just continuing.

5. Relative strength vs. the market (相对强度) — continuous

RS = (close ÷ close[-20] − 1) − (SPY ÷ SPY[-20] − 1)

The stock's 20-session return minus SPY's. Positive RS means the stock is outrunning the index — leadership, not beta.

6. Institutional-accumulation proxy (机构吸筹足迹) — continuous, gated

No 13F or fund-flow feed exists at this tier, so the signal reads the footprint conviction buying leaves in the daily bars — two components that must agree:

up_vol_share = Σ volume on up days ÷ Σ volume            (last 20 sessions)
A/D gate:      OLS slope of the Accumulation/Distribution line
               (cumsum of (2C−H−L)/(H−L) × V) over 20 sessions must be > 0

accumulation = up_vol_share  if the A/D slope is positive, else 0

A reading of 0.5 means volume is symmetric between up and down days; sustained readings above it mean advances attract the volume — the classic quiet-accumulation pattern. The A/D gate rejects series where closes keep finishing near the daily lows.

From signals to a 0–100 score

Each signal maps to a subscore in [0, 1], then a weighted sum produces the composite:

Signal Subscore mapping Weight
MA alignment 1 if true, else 0 18
Breakout new high 1 if true, else 0 22
Volume surge clip((ratio − 1) / (3 − 1), 0, 1) — zero credit at ≤1× average, full credit at 3× 18
Slope acceleration clip(ratio / 1.5, 0, 1) if both slopes > 0, else 0 — full credit at the 1.5 threshold 18
Relative strength clip(RS / 0.10, 0, 1) if RS > 0, else 0 — full credit at +10 pp over SPY 14
Accumulation clip((share − 0.50) / (0.65 − 0.50), 0, 1) — zero at a symmetric share, full at 0.65 10
technical_score = 18·s_MA + 22·s_BO + 18·s_VOL + 18·s_ACC + 14·s_RS + 10·s_INST   ∈ [0, 100]

The technical score is the auditable base score. The main page then ranks technically plausible candidates by final score, which may include a capped FMP/UW confirmation bonus and a volume penalty for fresh-high breakouts that lack volume confirmation.

Worked example — MRNA, 2026-07-06 close (real snapshot data)

Signal Measured Subscore × Weight
MA alignment close 81.80 > MA20 60.16 > MA50 53.18, both rising 1.0 18.00
Breakout new 60-day high (distance to high = 0.0%) 1.0 22.00
Volume surge 1.455× (1.455−1)/2 = 0.2275 4.10
Slope acceleration 5d slope 3.39 vs 20d slope 1.75 → 1.935× 1.935/1.5 → capped 1.0 18.00
Relative strength +59.3 pp vs SPY over 20 sessions 0.593/0.10 → capped 1.0 14.00
Accumulation up-volume share 0.810, A/D slope positive (0.810−0.50)/0.15 → capped 1.0 10.00
Total 86.09

"Why isn't {hot stock} on the list?"

Two possible reasons, and it's almost always the second:

  1. Not in the universe. Only S&P 500 ∪ Nasdaq 100 ∪ watchlist are screened. Anything else needs a watchlist entry.
  2. It isn't in a 主升浪 right now. Media buzz and technical structure are different things. Real example from the 2026-07-08 snapshot: LITE (Lumentum) — a heavily-discussed optical/AI name that is in the universe — scored 0.0 that day: close 731 sat below MA20 (851) and MA50 (895), 30.6% under its 60-day high, 20-day return −22.6%, volume at 0.66× average, and −21.9 pp vs SPY. Every one of the five signals failed. A popular stock in a sharp pullback is precisely what this screener is built to exclude; if it bases and breaks out again, it re-enters the list on its own.

What the screener deliberately does NOT consider

  • Unconstrained fundamentals — earnings, valuation, guidance, and analyst context cannot replace a weak technical setup.
  • Raw news and sentiment — generic headlines and social buzz do not pick stocks. Only normalized catalyst fields can contribute context.
  • Standalone institutional-flow picking — FMP and Unusual Whales can confirm technically plausible candidates, but the leaderboard remains price/volume first. Paid data is capped, volume-gated, and shown as explainable subscores; it is not a separate stock picker.
  • Intraday action — daily closes only, one snapshot per trading day after the US close.

Thresholds are engineering defaults, not validated optima

Every constant above (60-day breakout window, 1.5× volume multiple, 1.5 acceleration threshold, the weights…) is a single-sourced config value chosen as a reasonable starting point. They have not been optimised by backtest yet — treat the ranking as a candidate short-list to verify on a chart, never as a verdict.

Catalyst, resonance, volume quality

The production screener is intentionally price/volume first. The v3 confirmation layer keeps that discipline: the deterministic technical_score remains the first eligibility gate and validation baseline, while confirmation fields explain whether a technical leader is also supported by fresh catalysts, peer participation, improving volume quality, FMP data, or Unusual Whales flow.

The layer adds five optional fields:

Field Meaning Boundary
catalyst_context Fresh news or event context: catalyst type, recency, source count, confidence, and a short evidence summary. A headline cannot force a technically broken stock into the Top 20.
sector_resonance Whether peers in the same theme or industry are moving together: peer breadth, leaders, relative strength, and Top-20 confirmation. This refines sector rotation; it does not replace per-stock signals.
volume_quality Whether participation is improving: 1-day volume vs 5-day/20-day baselines, up-volume trend, breakout participation, and optional late-day confirmation. Missing intraday data is shown as missing context, not as a negative score.
trade_character Descriptive setup type: mega-cap institutional, high-beta growth, or standard momentum, plus flags such as not early, near high, elevated valuation, lower/higher volatility, and extended move. This explains trading character; it is not a recommendation or separate eligibility gate.
paid_confirmation FMP and Unusual Whales confirmation, including fmp_confirmation, flow_confirmation, capped bonus, volume_factor, and volume_penalty. Paid context can affect final rank only after the technical gate and volume gate.
report_score A display blend of technical score, typed catalyst, resonance, volume improvement, and trade-character setup quality, reweighted when optional context is missing. The technical score remains visible for audit and replay.

Catalysts reuse StockClaw's existing ingestion and signal data where possible. They are normalized into typed events such as earnings/guidance, analyst, product, policy/regulatory, M&A, AI-capex/supply-chain, sector-macro, and other. Generic routine_news/other items are shown as news heat, not catalysts, and do not add the catalyst component to report_score. Sector resonance also prefers fine themes over broad sectors, so technology names should surface as cybersecurity, AI networking/optical, semi equipment, and similar buckets when the peer evidence exists. Trade character separates stable mega-cap institutional trends such as AAPL/MSFT from high-beta growth moves such as LITE/ALAB/FTNT, so the report can describe a name as institutional, near highs, not early, lower torque, or valuation-sensitive without changing the primary score. The LLM may summarize only these normalized facts; it still cannot pick tickers, change numbers, mention tickers outside the supplied payload, or use advisory wording.

The daily research note

Since 2026-07 the screener publishes a full daily note, built facts-first:

  1. Deterministic aggregates (no LLM anywhere): market context (SPY/QQQ/DIA from our own bars, VIX from CBOE, advance/decline breadth across the whole stored market), Top-20 sector composition from the index-membership files, list-level statistics (fresh-high count, volume-confirmed breakout share, median volume ratio, average acceleration, extension and ATR readings), a momentum-regime label, six insight cards, and per-candidate report fields (grade, extension, trend profile, leader flags) — every one a fixed rule table in screener_config.py.
  2. Historical validation — real replay, not a promise. The production screen is re-run as of each of the last 30 sessions (quant layer only) and measured against what actually happened: per-pick 5-session forward returns (win rate, average, alpha vs SPY), and a daily-rebalanced Top-5 basket (cumulative return, max drawdown). Convention: equal weight, close-to-close, no costs. Alongside win rate the section reports the payoff structure and the benchmark's own up-rate. The replay also breaks out 1/3/5/10-day statistics for Early Setup, Breakout Watch, and lifecycle groups such as confirmed and extended momentum, including alpha versus SPY/QQQ when available. These statistics describe the screen's past behaviour and are never a forecast.
  3. Language layer: the LLM writes the market summary, per-candidate read-outs (answering why today / what changed / what's unique, using the aggregates and yesterday-list comparison as context), and a daily conclusion — all under the same machine-validated contract (no advisory wording, no tickers beyond the screened set; violations fall back to deterministic templates).
  4. Momentum lifecycle staging: every candidate is classified into early_breakout / confirmed_momentum / extended_momentum / exhaustion_risk by a priority rule cascade (thresholds in screener_config.py: exhaustion first — late AND a fading confirmation such as weak volume or flat acceleration; then early — fresh high, <12% 20-day gain, <6% above MA20, no more than three days in the Top20, and volume confirmation when available; then extended; confirmed is the default middle). setup_stage values such as breakout_confirmed or post_breakout_follow_through can support early classification when the move is not overextended. History-aware inputs (consecutive days on the list, day-over-day score/rank change, newly-entered flags) come from the immutable report_history table.
  5. Early momentum screens: early_setup and breakout_watch run across the full evaluated universe, not only the Top 20. Early Setup emphasizes 5d/10d acceleration, proximity to 60-day highs, volume improvement, compression-to-expansion, RS improvement, and fine-theme resonance. Breakout Watch requires a name to sit within -3% to 0% of its 60-day high, hold MA20/MA50 alignment, show improving 5-day volume, and have theme peers already moving. News only appears here when normalized into a specific catalyst event; routine news is not promoted to catalyst. The full report stays at /momentum; the focused Early Momentum Radar has its own page at /momentum/early and is linked from the dashboard for admins. With MOMENTUM_FUNDAMENTALS_PROVIDER=fmp and FMP_API_KEY, the early model also calls FMP Premium for a capped technical shortlist: stock news / press releases, earnings calendar, analyst grades, price-target consensus, insider-trading statistics, institutional ownership / 13F position summaries, and financial-growth data. These become FMP confirmation subscores that can lift near-threshold Early Setup / Breakout Watch candidates; without FMP the screen falls back to quant-only behaviour. The /momentum/early row display exposes the full FMP breakdown: fmp_confirmation, news_event_score, earnings_event_score, analyst_revision_score, price_target_score, insider_score, institutional_flow_score, and fundamental_quality_score; rows without FMP data still show the same fields as placeholders with an unavailable reason when available. With UNUSUAL_WHALES_API_KEY, the early model also adds a flow confirmation layer from recent option flow, dark-pool trades, lit-flow trades, and options pulse. These normalize into flow_confirmation, options_flow_quality, darkpool_accumulation, lit_flow_quality, dealer_pressure, and flow_resonance. This is stock early-momentum context, not an options-trading recommendation layer. FMP and Unusual Whales are endpoint-level best effort: partial endpoint failures show partial_query_failed while successful sibling endpoints still contribute subscores; only a full provider failure shows query_failed.
  6. Momentum Discovery: /momentum/discovery reads discovery_screens from the same snapshot and separates liquid breakouts, early base breakouts, high FMP/UW confirmation, and filtered low-quality rows. It uses an expanded bars universe while the main Top 20 stays on the curated core universe. FMP/UW are re-read only for a capped technical Discovery shortlist, not for every backfilled symbol.
  7. Scan shelves: four adjacent screens from the same evaluated universe (emerging momentum, approaching breakout, pullback within trend, RS leaders without breakout) — threshold variants, fully deterministic.

Every early row also carries an entry_timing_profile so the product does not confuse a completed move with a future setup. The profile can be early_setup, catalyst_repricing, confirmed_breakout, extended_chase_risk, or pullback_preferred, based on 20-day run-up, distance to the 60-day high, MA20 stretch, volume spike, mega-cap/institutional character, and explicit catalysts. Inclusion and display order both use the timing-adjusted score: raw setup score minus timing/profile penalties. Post-catalyst repricing or chase-risk rows can fail the Early Setup threshold outright; if they still qualify, they rank behind true early setups. UI and Telegram show only the timing-adjusted score.

The radar also emits a finer setup_stage: base-building, volatility contraction, breakout ready, breakout attempt, breakout confirmed, post-breakout follow-through, failed breakout, extended, or no setup. Breakout confirmation is no longer inferred from being near a 60-day high; it requires a defined base pivot, breakout buffer, close confirmation, volume confirmation, and close-location evidence. Each row can show the pivot, distance to pivot, breakout volume ratio, trend score, catalyst score, breakout quality, data completeness, structured positive/negative reason codes, and invalidation condition. FMP or Unusual Whales partial_query_failed is represented in the data-quality object; failed components are unavailable/null rather than real zero scores.

Telegram sends the full Momentum daily intelligence note first and then, when early rows exist, a separate Early Momentum Radar message. The early message expands the /momentum/early rows with radar score, technical score, FMP confirmation, Unusual Whales flow confirmation, partial-data reasons, and replay context when available; the main note keeps only a compact early summary.

The LLM layer's hard contract

The read-out model receives only the screened candidates with their measured numbers, and must return one Chinese + one English description per candidate. Its output is machine-validated:

  • Any ticker mentioned that is not in the candidate list → rejected.
  • Any advisory phrase (推荐 / 建议买入 / 买点 / 必涨 / recommend / buy signal / price target / …) → rejected.
  • A volume adjective that contradicts the measured number (e.g. "surging volume" on a 0.99× ratio) → rejected (numeric-characterization consistency, rules in VOLUME_CLAIM_RULES).
  • Rejected or unparseable output gets one retry; if it fails again, that candidate is displayed with quantitative metrics only.

Numbers shown in the UI always come from the quant layer, never from the LLM.


本内容为基于公开行情数据的算法筛选结果与描述性说明,仅供信息参考,不构成任何投资建议。This content is an algorithmic screening result with descriptive commentary based on public market data, for informational purposes only. It does not constitute investment advice.