Skip to content

Style / Sector Score

Cross-sectional ranking of a style/sector ETF basket vs a benchmark. Each name's score blends its RRG quadrant with the cross-sectional z-score of its interval return and Sharpe, minus a volatility penalty — yielding a rank and an overweight / neutral / underweight stance. A relative ranking of who is leading the rotation now, not a price forecast.

How to use

  1. Wire the style/sector ETF Price Factors (edge-first), or type symbols.
  2. Set the benchmark (default SPY).
  3. Read the ranking + stance; feed style_rotation_v1 to turn it into target weights + a backtest.

Core formula

score = quadrant_bonus + 0.5·z(interval_return) + 0.5·z(interval_sharpe) − 0.25·z(vol)
quadrant_bonus = Leading +1.0 / Improving +0.5 / Weakening −0.5 / Lagging −1.0
z = cross-sectional z-score within the basket
stance = overweight (score > 0.25) / underweight (< −0.25) / neutral

Assumptions & applicability

Assumptions: a basket vs one benchmark; enough history for the RRG windows + the interval lookback.

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

Out of scope: price-direction forecasting, single-name analysis.

Known limitations

  1. Relative ranking only — a top-ranked name can still fall in absolute terms if the benchmark falls.
  2. Cross-sectional z-scores need ≥ 2 names to mean anything.
  3. Inherits RRG's sensitivity to the ratio/momentum window choice.

References

RRG quadrants (StockCharts / OpenBB) + standard cross-sectional factor ranking (return / Sharpe / vol z-scores).

Golden Test

tests/golden/fixtures/tier2/style_score/ — 1e-3 absolute, independent pandas reimplementation of the quadrant + interval metrics + cross-sectional z-score, 2026-05-25 passing.

Changelog

  • 1.0.0 (2026-05-25) — New operator (Stage 2 — Style Rotation). Backend kernel + handler, frontend registry + ranked-table renderer, golden added.

Verifiable intelligence for the decisions that demand scrutiny.