Skip to content

Relative Rotation Graph (RRG)

RS-Ratio (relative-strength trend) and RS-Momentum (its rate-of-change) of a style/sector ETF basket versus a benchmark, plotted in four quadrants — Leading, Weakening, Lagging, Improving — that rotate clockwise over time. RRG reads the rotation rhythm (which names lead vs are improving), not a price-direction forecast.

How to use

  1. Wire the style/sector ETF Price Factors as the basket (edge-first), or type symbols.
  2. Set benchmark (default SPY) — it is the 100,100 origin and is excluded from the basket.
  3. Read each symbol's quadrant + trail. Improving → Leading (RS-Ratio crossing 100 with positive momentum) is an early rotation-in signal; Leading → Weakening is fading excess momentum. Both are tentative, not deterministic.

Core formulas

RS          = 100 · price / benchmark            (aligned to shortest common length)
RS-Ratio    = 100 + rolling_z(RS, ratio_window)
RS-Momentum = 100 + rolling_z(ΔRS-Ratio, momentum_window)   (ΔRS-Ratio[0] := 0)

quadrant:  Leading   (ratio ≥ 100, mom ≥ 100)
           Weakening (ratio ≥ 100, mom < 100)
           Lagging   (ratio < 100, mom < 100)
           Improving (ratio < 100, mom ≥ 100)

rolling_z is an expanding-until-window, then trailing-window, population-std (ddof=0) z-score; the first point and any constant window contribute 0 (base 100, never NaN/inf).

Assumptions & applicability

Assumptions: a meaningful trail needs ≥ ratio_window + momentum_window of history; the benchmark is strictly positive and finite.

Applicability: equity / ETF / multi-asset baskets, daily data, ≥ 5 aligned observations.

Out of scope: price-direction forecasting, single-name analysis, the proprietary JdK normalization.

Known limitations

  1. Reads relative rotation rhythm, not direction — a Leading name can still fall in absolute terms if the whole benchmark falls.
  2. Factor/style regimes persist for long stretches; quadrant crossings are tentative, not deterministic.
  3. Short history (< ratio_window + momentum_window) flags short_history and the trail is unreliable.
  4. Sensitive to the window choice — short windows are noisier.

References

  • StockCharts / OpenBB public RRG description (RS-Ratio · RS-Momentum, four quadrants) — the reproducible method this operator implements.
  • Julius de Kempenaer (JdK), Relative Rotation Graphs — the originator (proprietary JdK normalization is not used here).

Golden Test

tests/golden/fixtures/tier2/rrg/ — 1e-3 absolute (absorbs the operator's 3-decimal rounding), independent pandas-rolling reference vs the operator's numpy per-window loop, 2026-05-25 passing. Locks the two-stage rolling-z stacking, ddof=0 population std, the expanding-until-window warmup, the ΔRS-Ratio[0]:=0 seam, and the quadrant thresholds.

Changelog

  • 1.0.0 (2026-05-25) — New operator (Stage 2 — Style Rotation). Backend handler + core, frontend registry + four-quadrant SVG renderer, style + sector demos, golden added.

Verifiable intelligence for the decisions that demand scrutiny.