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
- Wire the style/sector ETF Price Factors (edge-first), or type
symbols. - Set the
benchmark(default SPY). - Read the ranking + stance; feed
style_rotation_v1to 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) / neutralAssumptions & 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
- Relative ranking only — a top-ranked name can still fall in absolute terms if the benchmark falls.
- Cross-sectional z-scores need ≥ 2 names to mean anything.
- 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.

