Portfolio Manager

Sector Rotation Signal β€” Tech Lagging, Agent Says Move to Energy

+18% rotation alpha on rotated capital (60-day)Finance & Trading5 min read

Key Takeaway

Our AI agent detected tech underperformance across three timeframes, cross-referenced with late-cycle macro data, and recommended rotating 8% from tech to energy β€” three weeks before consensus caught on.

The Problem

Sector rotation is one of those strategies everyone talks about and almost nobody executes well. The reason is simple: by the time you read about it in a newsletter, it's already priced in.

The edge isn't knowing that sector rotation works. Every finance textbook covers it. The edge is detecting the rotation signal early enough to act on it. That means monitoring sector performance continuously, across multiple timeframes, and cross-referencing with macro regime data to distinguish noise from signal.

I was doing this manually. Sort of. I'd glance at sector ETFs weekly, notice tech was flat, think "hmm," and then forget about it because I had twelve other things to do. By the time I'd convinced myself to rotate, the energy rally was already 15% in.

The Solution

Alpha Vantage market data combined with our macro regime detector. The agent tracks eleven sector ETFs weekly, computes momentum scores across 1-week, 1-month, and 3-month windows, and cross-references with the current macro regime classification.

When all three timeframes agree that a sector is lagging β€” and the macro regime historically favors a different sector β€” the agent fires a rotation signal. Not a vague "consider rebalancing." A specific recommendation: "reduce tech by X%, add energy by X%, here's why."

The Process

Sector monitoring config:

yamlShow code
# sector-rotation config
schedule: "0 7 * * 5"  # Friday 7AM UTC
sectors:
  - { name: "Technology", etf: "XLK" }
  - { name: "Energy", etf: "XLE" }
  - { name: "Healthcare", etf: "XLV" }
  - { name: "Financials", etf: "XLF" }
  - { name: "Industrials", etf: "XLI" }
  - { name: "Consumer Disc.", etf: "XLY" }
  - { name: "Consumer Staples", etf: "XLP" }
  - { name: "Utilities", etf: "XLU" }
  - { name: "Real Estate", etf: "XLRE" }
  - { name: "Materials", etf: "XLB" }
  - { name: "Communication", etf: "XLC" }

momentum_windows:
  - 5    # 1 week (trading days)
  - 21   # 1 month
  - 63   # 3 months

regime_source: macro_dashboard  # cross-reference with Monday macro data

The momentum scoring pipeline:

pythonShow code
def compute_sector_momentum(sectors, windows):
    scores = {}
    for sector in sectors:
        prices = fetch_prices(sector.etf, days=max(windows) + 10)
        momentum = {}
        for w in windows:
            ret = (prices[-1] / prices[-w] - 1) * 100
            rank = rank_among_sectors(ret, sector.name, w)
            momentum[f"{w}d"] = {"return": ret, "rank": rank}

        # Composite: equal-weight across timeframes
        avg_rank = np.mean([m["rank"] for m in momentum.values()])
        scores[sector.name] = {
            "momentum": momentum,
            "composite_rank": avg_rank,
            "signal": classify_signal(avg_rank, len(sectors))
        }
    return scores

def classify_signal(rank, total):
    if rank <= total * 0.2:
        return "STRONG_LEAD"
    elif rank <= total * 0.4:
        return "LEADING"
    elif rank >= total * 0.8:
        return "STRONG_LAG"
    elif rank >= total * 0.6:
        return "LAGGING"
    return "NEUTRAL"

Regime cross-reference:

pythonShow code
REGIME_SECTOR_MAP = {
    "early_expansion":  ["Technology", "Consumer Disc.", "Industrials"],
    "mid_expansion":    ["Technology", "Industrials", "Materials"],
    "late_expansion":   ["Energy", "Financials", "Materials"],
    "contraction":      ["Healthcare", "Utilities", "Consumer Staples"],
    "recovery":         ["Financials", "Consumer Disc.", "Real Estate"]
}

def generate_rotation_signal(sector_scores, current_regime):
    favored = REGIME_SECTOR_MAP[current_regime]
    lagging = [s for s, d in sector_scores.items() if d["signal"] == "STRONG_LAG"]
    leading = [s for s, d in sector_scores.items() if d["signal"] == "STRONG_LEAD"]

    # Signal fires when: lagging sector is currently overweight AND
    # regime-favored sector is currently underweight
    recommendations = []
    for lag in lagging:
        if lag in portfolio.overweight_sectors:
            for fav in favored:
                if fav in leading or fav not in portfolio.sectors:
                    recommendations.append(Rotation(
                        reduce=lag, increase=fav,
                        reason=f"{lag} lagging 3 consecutive weeks, "
                               f"{current_regime} historically favors {fav}"
                    ))
    return recommendations

The alert Hari delivered:

View details
πŸ“Š SECTOR ROTATION SIGNAL β€” Week of March 6

Tech (XLK): -2.1% (1W) | -4.3% (1M) | +1.2% (3M) β†’ STRONG_LAG
Energy (XLE): +3.4% (1W) | +8.7% (1M) | +14.2% (3M) β†’ STRONG_LEAD

Regime: Late-cycle expansion (confirmed by Monday macro dashboard)
Historical precedent: Energy outperforms tech by avg 12% in
late-cycle periods (1990-2024, n=7 cycles)

Recommendation: Reduce tech allocation by 8% β†’ add to energy
Current tech: 28% of equity sleeve β†’ proposed 20%
Current energy: 0% β†’ proposed 8%

Timing: momentum still accelerating on XLE, not overbought (RSI 62)

The Results

~3 weeks

Signal lead time vs. consensus

-6.2%

Tech (XLK) subsequent 60-day return

+11.8%

Energy (XLE) subsequent 60-day return

+18.0% on rotated capital

Rotation alpha (60-day)

+1.44% total portfolio

Portfolio impact (8% rotation)

2 out of 9 (78% accuracy)

False signals (last 12 months)

Try It Yourself

Install the alpha-vantage skill on Mr.Chief. Sector ETF data is free. The regime classification uses your macro dashboard β€” so you need that running first. The rotation signal is a layer on top. Each layer makes the next one smarter.

Start by just monitoring β€” don't rotate immediately. Build confidence in the signal over 2-3 cycles. Then size your rotations appropriately.


The market tells you what's working. Most people aren't listening. An agent never stops.

sector-rotationmomentummacro-regimeETFalpha-vantage

Want results like these?

Start free with your own AI team. No credit card required.

Sector Rotation Signal β€” Tech Lagging, Agent Says Move to Energy β€” Mr.Chief