AQAI QuantAI research lab for systematic strategies

Case study · Backtest

Sector Relative Strength Rotation (3/6/12m vs SPY)

SECTOR_MOMENTUM
sector-rotationmomentumetfrelative-strengthmonthly-rebalanceus

🗓 Backtest period: 2020-01-01..2026-11-01

Jan 2020Total 106.2%Oct 2026
Max DD -22.5%

Backtest metrics

Sharpe
0.96
Total Return
106.2%
Max Drawdown
-22.5%
CAGR
11.2%
Volatility
16.2%
Beta vs SPY
0.69
Trades
68

Strategy Card

Sector Relative Strength Rotation (3/6/12m vs SPY) — strategy card

Spec ID: spec-sector-momentum-rotation-etf-top50-1767027941_v27 · Generated: 2026-11-05 10:44 UTC

Cluster: Momentum · Sub Cluster: Multi-Horizon Sector Relative Strength Rotation

One-line description

Ranks eligible sector ETFs by composite 63-, 126-, and 252-day relative strength versus SPY and targets the top three at equal weights, rebalanced monthly. The intended portfolio is long-only with 1.0× gross exposure, subject to position and sector caps.

Why this trade exists

Sector leadership can persist as investors gradually incorporate changes in earnings prospects, economic conditions, and capital flows. Ranking relative strength across several horizons seeks to capture persistent leadership rather than a single short-lived price move.

The strategy expresses this hypothesis through liquid ETFs, reducing individual-stock exposure. Relative ranking does not provide an absolute defensive signal: selected sectors can still fall together, and leadership reversals can produce whipsaw losses. This rationale is a hypothesis, not a causal conclusion established by the supplied backtest.

Algorithm

Specification-level logic; the truncated source does not establish the full implemented selection and order-generation path.

[code omitted from public view]

The specification requests a one-day signal lag and next-open trading; the applied execution convention is daily-bar MOC at the official closing auction print. These are distinct settings and the actual timing requires blotter reconciliation. The minimum-three-position setting, disabled cash fallback, and caps do not fully specify a feasible allocation when too few eligible sectors exist. The return-ratio definition also requires verification of whether total_return means a gross return factor or a signed cumulative return.

Parameters

Param Value Notes
Strategy / rule Sector Relative Strength Rotation (3/6/12m vs SPY) / SECTOR_MOMENTUM Specification-level description
Universe ETF; top_n = 50; sort_by = capitalization Supplied 50-symbol snapshot; visible code describes annual refreshes
Universe symbols AGG, BIL, BIV, BND, BNDX, BSV, DIA, EFA, GLD, IEFA, IEMG, IJR, ITOT, IVE, IVV, IWD, IWF, IWM, IXUS, JEPI, LQD, MBB, MUB, QQQ, QUAL, RSP, SCHD, SCHF, SPY, VB, VCIT, VCSH, VEA, VGIT, VGT, VIG, VNQ, VO, VOO, VT, VTEB, VTI, VTIP, VTV, VUG, VWO, VXUS, VYM, XLK, XLV All supplied keys have suffix &US&ETF; not all are eligible sector ETFs
Sector filter sector_etfs_only; use_provider_metadata_or_name_match; GICS_11 Keywords: Select Sector, Sector, SPDR, XL; fallback category: Sector Equity
Benchmark SPY&US&ETF Relative-strength denominator
Lookbacks 63, 126, 252 trading days Approximately 3, 6, 12 months
Relative strength total_return(etf,LB)/total_return(benchmark,LB) Return-factor versus signed-return semantics require verification
Composite mean_zscore_across_lookbacks Mean cross-sectional standardized relative strength
History / missing data require_full_price_history_days = 252; drop_if_missing_any_lookback = true Exclude incomplete candidates
Liquidity volume_lookback_days = 63; min_avg_daily_volume_shares = 250000 Rule-level filter; plan-level liquidity_filter = null
Rebalance monthly; first_trading_day Monthly ranking and portfolio reset
Selection / sizing selection_count = 3; position_sizing = equal_weight; gross_leverage = 1.0 Intended three-position, long-only allocation
Risk overrides min_positions = 3; max_weight_per_position = 0.4; cash_if_fewer_candidates = false Insufficient-candidate behavior is not established
Sector cap max_sector_allocation = 0.4 Aggregate sector constraint can bind across overlapping ETFs
Other risk controls stop_loss_pct = null; volatility_targeting = false No configured stop or volatility target
Requested execution trade_on = next_open; signal_lag_days = 1; skip_if_turnover_below = 0.0 Differs from recorded applied convention
Applied execution daily bars, MOC (market-on-close) by default From costs_applied.execution
Commissions $0.0040 per share, minimum $1.00 per order, capped at 1.00% of trade value Charged per fill by the results module; all metrics are net of them
Slippage 0 bps — not applied Not an omission — MOC (market-on-close) fills at the auction print the backtest uses
Costs not modelled short borrow fees / rebate, margin financing on leverage, market impact, exchange/regulatory/clearing pass-through fees, taxes Excluded deliberately, not unknown
Backtest window / bars 2020-01-01..2026-11-01; 1d Requested interval; actual end of evaluated returns is not established
Supplied data period 2018-01-01..2023-01-01 Does not cover the full requested interval
Annualized measurement start 2020-01-03 Reported annualized_metrics_measured_from
Evaluation settings performance_metrics = annualized_return, sharpe, max_drawdown, turnover; wfa = null; position_limits = null Plan-level settings; rule-level caps remain specified
Initial sizing capital 1000000.0 fallback Visible code accepts configuration/environment overrides; actual run capital is not confirmed

Look-ahead audit

# Concern Status
1 Point-in-time universe and sector classifications ⚠ Annual refresh is described, but historical capitalization ranks, membership, and metadata timestamps are not verified.
2 Signal and execution alignment ⚠ Applied convention is MOC at the closing auction print; reconcile with the requested one-day lag/next-open setting. Same-day open fills using that day's closing data would violate causality.
3 Return and volume inputs ⚠ Verify dividend-adjusted total returns, trailing-only liquidity windows, and complete benchmark/ETF history at every signal date.
4 Data coverage ⚠ Supplied data ends 2023-01-01 while the requested backtest ends 2026-11-01; actual evaluated end date requires confirmation.
5 Ranking and constraint implementation ⚠ Truncated code does not verify z-score handling, return-ratio semantics, insufficient-candidate behavior, or sector-cap enforcement.
6 Charged costs ✓ commissions $0.0040/share (min $1.00/order); slippage 0 bps — not applied

Caveats / known limitations

Results

The supplied net-of-charged-commissions results show a 106.15% total return, a 0.96 Sharpe ratio, and a -22.45% maximum drawdown across 68 reported trades. Reported volatility is 16.22%, with a 70.59% win rate and a 5.96 profit factor. These figures indicate positive historical performance with material downside, but do not establish outperformance versus SPY. The unresolved data-window, eligibility, and execution discrepancies limit confidence that these results describe the intended three-sector rotation strategy.

Run diagnostics

Recomputed here from the run's stored daily returns, because every annualized figure in the table above is derived from the LENGTH of that array from its first active row (years = n / 252, counted from the first trade). Only total return and max drawdown do not depend on the row count, so when the recomputed and stored values differ by a common factor, those two are the numbers to trust.

Check From the run's own returns Note
Daily-return rows 1,717 1.00x the 1,722 trading days in 2020-01-01..2026-11-01
Annualized from 2020-01-03 1 leading flat row(s) before the first trade are excluded from Sharpe, volatility and CAGR (1,716 rows count)
Distinct dates 1,717 one row per date
Date span 2020-01-02 .. 2026-10-30
Sum of daily returns 106.15% matches the reported total return
Sharpe from these rows 0.96 stored 0.96
Volatility from these rows 16.22% stored 16.22%
Max drawdown from these rows -22.45% stored -22.45%
Lowest the book stood -16.16% low-water mark, in units of starting capital
CAGR from these rows 11.21% stored 11.21%

Backtest metrics snapshot

Metric Value
Total Return 106.15%
Sharpe 0.96
Sortino 1.23
Calmar 0.50
Max Drawdown -22.45%
Volatility 16.22%
Beta vs SPY 0.69
Annualized from 2020-01-03
Win Rate 70.59%
Profit Factor 5.96
Total Trades 68
Symbols 50 (AGG, BIL, BIV, BND, BNDX, BSV, DIA, EFA, GLD, IEFA, +40 more)