# Methodology — TradingView Market-Movers ingest, forward + backward loops

**Lane:** THv2-61
**As of:** 2026-04-29
**Owner:** NEXUS COMMAND
**Status:** READ-ONLY scaffold; activation gated behind `FF_TV_MOVERS=1`.

## Sources

Per the user mandate, eleven canonical TradingView pages are crawled twice
daily (morning ≈ 8 AM ET, evening ≈ 4:30 PM ET):

| page_kind          | URL |
| ------------------ | --- |
| gainers            | https://www.tradingview.com/markets/stocks-usa/market-movers-gainers/ |
| losers             | https://www.tradingview.com/markets/stocks-usa/market-movers-losers/ |
| active             | https://www.tradingview.com/markets/stocks-usa/market-movers-active/ |
| volatile           | https://www.tradingview.com/markets/stocks-usa/market-movers-most-volatile/ |
| large_cap          | https://www.tradingview.com/markets/stocks-usa/market-movers-large-cap/ |
| 52wk_high          | https://www.tradingview.com/markets/stocks-usa/market-movers-52wk-high/ |
| 52wk_low           | https://www.tradingview.com/markets/stocks-usa/market-movers-52wk-low/ |
| penny_volatile     | https://www.tradingview.com/markets/stocks-usa/market-movers-low-priced-most-volatile/ |
| crypto_all         | https://www.tradingview.com/markets/cryptocurrencies/prices-all/ |
| crypto_gainers     | https://www.tradingview.com/markets/cryptocurrencies/market-movers-gainers/ |
| crypto_losers      | https://www.tradingview.com/markets/cryptocurrencies/market-movers-losers/ |

## License & ToS compliance

Per `feedback_nexus_license_compliance.md`:

- Personal-use research only. NOT redistributed.
- User-Agent is identifying: `THv2-research-mover-collector/1.0
  (kadeem.yearwood@gmail.com; personal-use)`.
- Rate-limited to 1 req/sec floor (`RATE_LIMIT_MS = 1000`).
- robots.txt should be respected at fetch time (cron handler concern).
- TradingView ToS prohibits automated scraping at scale; this is intentionally
  small-volume (≈22 requests / day = 11 pages × 2 windows). If TV begins to
  block, fallback chain takes over and a "movers data degraded" banner
  surfaces per `feedback_silent_failures.md` — never silent.
- Methodology footer on `/pages/movers.html` cites TradingView with link
  back. No paid TradingView API auto-purchased.

## Fallback chain

When TV returns ≠200 or yields no parsable rows, the runner attempts:

1. **Yahoo Finance trending** — `query1.finance.yahoo.com/v1/finance/trending/US`
   (free, no auth). Provides ticker + price + change_pct + volume.
2. **Finviz screener** — CSV export of top gainers
   (`finviz.com/screener.ashx?v=111&s=ta_topgainers&export=true`). Free.
3. **Stocktwits trending** — `api.stocktwits.com/api/2/trending/symbols.json`.
   Provides ticker + name only; price/change are null with `partial: true`
   so downstream consumers know to enrich from another source.

The fallback chain only fires for `gainers / losers / active` pages — others
have no parity in the fallback sources.

## Forward loop (recommender)

`engine/tv-movers-recommender.js` ingests a snapshot + injected context maps
(scoresByTicker / leadingIndicatorsByTicker / newsByTicker / ivRankByTicker /
sanityGuardsByTicker / universeSet) and emits four recommendation kinds:

- **CONTINUATION** (AWARENESS): top-gainer + StrongBuy/Buy + (leading-indicator
  agreement OR news catalyst ≥60). `forward_impact = 0.85` if both lead+news,
  `0.7` if either alone.
- **REVERSION** (OPPORTUNITY): top-gainer + StrongSell + IV-rank ≥80 + extended
  52wk pos (≥0.95 or page = 52wk_high). Surfaces `options_strategies =
  [short_call, bear_call_spread, long_put_high_iv]`.
- **AVOID_TRAP** (DEFENSIVE): top-loser (≤−10%) + (sanity-guard fired OR
  microcap+penny OR StrongSell). Surfaces "do not buy this dip" banner.
- **SURPRISE_PROMOTE** (AWARENESS): not-in-universe + extreme move + significant
  volume → analyst-immediate flag + `promote_to_watchlist = true`.

`composite = forward_impact × probability × time_criticality`, all clamped to
[0,1]. Per `feedback_actionable_first.md`, callers surface top-3 first.

## Backward loop (recall + calibration)

`engine/tv-movers-recall.js`:

- **classifyOutcome**: `{ hit | miss | false_positive | partial | unrelated }`
  for each top mover, joined to forecast-ledger claims by `ticker` within a
  5-day lookback window.
- **recallAnalysis**: full counts + `hit_rate ± 95% Wilson CI` per
  `feedback_scientific_rigor_portfolio_wide.md`.
- **top10 capture**: of today's top-10 gainers (or crypto_gainers), how many
  did THv2 have on a Buy/StrongBuy claim? Baseline = 5% (top decile by
  definition); lift = capture / 0.05.
- **toLedgerResolutions**: emits resolution objects for all pending EOD/1d
  claims that match a mover row → consumed by `/api/cron/resolve-forecasts`
  (lane 16) for the actual ledger writeback.

## Capture-rate baseline

Top-10 gainers represent the top 10% of the market on a given day. If THv2
recommendations were random, the expected capture rate of a random sample
is ≈10% × 10/N where N is the universe. We use the simpler 5% floor as
"random-baseline" because (a) THv2's universe is curated (not random) and
(b) the actual stat we care about is *lift over uncurated*. Future work:
replace 5% baseline with empirical "random-tier draw" from the ledger.

## Compounding metrics

`windowMetrics(history, windowName)` rolls daily recall results into:

- daily / weekly / monthly / quarterly / yearly
- each reports `hit_rate ± 95% CI` and `top10_capture_rate`.

Surfaced on `/pages/movers.html#mv-compound` and propagated to `/track-record`
(lane 28).

## Anti-silent-failure contracts

- Every fetch failure is recorded into `degraded[]` with `source_chain`.
- Empty snapshot → page surfaces "Movers data degraded" banner (never blank).
- Missing fields → `null` (never zero); recommender skips `null` change_pct
  rows entirely rather than counting them as "no move".

## Empirical references

Top-mover anomaly literature (informs forward-loop calibration):

- Lehmann (1990) "Fads, martingales, and market efficiency" — short-term
  reversal in losers.
- Jegadeesh & Titman (1993) "Returns to buying winners and selling losers" —
  3-12 month momentum continuation.
- Da, Engelberg, Gao (2011) "In Search of Attention" — Google-search spikes
  + price moves.
- Tetlock (2007) — media pessimism IC ~0.04 daily.
- Engle, Hansen, Lunde (2012) — earnings surprise beats consensus by far.

These citations ground the rationale text on each recommendation; explicit
empirical IC numbers will be backfilled by lane 16 backtest harness once
≥30 days of live snapshots accumulate.
