Back to Openbb

**Sector Rotation Strategy Analysis with OpenBB**

examples/sectorRotationStrategy.ipynb

4.7.04.2 KB
Original Source

Sector Rotation Strategy Analysis with OpenBB

Sector rotation involves shifting investments across different sectors in the stock market, based on economic cycles or market performance expectations. This strategy seeks to maximize returns by focusing on sectors that are expected to perform better in the current market environment while reducing exposure to underperforming sectors.

Author:

Sanchit Mahajan

python
!pip install openbb -q
python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from openbb import obb
python
sector_etfs = ['XLF', 'XLE', 'XLK', 'XLY', 'XLI', 'XLU', 'XLV']

start_date = '2015-01-01'
etf_dataframes = []

for etf in sector_etfs:
    try:
        data = obb.etf.historical(
            symbol=etf,
            start_date=start_date,
            provider="yfinance"
        ).to_df()
        data['Symbol'] = etf
        etf_dataframes.append(data)
    except Exception as e:
        print(f"Failed to fetch data for {etf}: {str(e)}")

combined_etf_data = pd.concat(etf_dataframes)
combined_etf_data = combined_etf_data.reset_index()

combined_etf_data.head()
python
combined_etf_data['date'] = pd.to_datetime(combined_etf_data['date'])
combined_etf_data = combined_etf_data[['date', 'close', 'Symbol']]

pivoted_data = combined_etf_data.pivot_table(index='date', columns='Symbol', values='close')

pivoted_data.ffill()

pivoted_data.head()
python
def sector_rotation_strategy(etf_data, lookback_period=3, top_n=3):
    """
    Implements a simple sector rotation strategy that invests in the top 'n' sector ETFs based on
    past performance over a lookback period.

    Parameters:
    etf_data (DataFrame): ETF performance data
    lookback_period (int): Number of months to look back for performance evaluation
    top_n (int): Number of top sector ETFs to invest in

    Returns:
    DataFrame: Portfolio returns based on the sector rotation strategy
    """
    monthly_returns = etf_data.resample('ME').last().pct_change()

    portfolio_returns = pd.DataFrame(index=monthly_returns.index, columns=['Portfolio Return'])

    for date in monthly_returns.index[lookback_period:]:
        past_returns = monthly_returns.loc[date - pd.DateOffset(months=lookback_period):date].mean()
        top_etfs = past_returns.nlargest(top_n).index

        next_month_date = date + pd.DateOffset(months=1)

        if next_month_date in monthly_returns.index:
            next_month_return = monthly_returns.loc[next_month_date, top_etfs].mean()
            portfolio_returns.loc[next_month_date, 'Portfolio Return'] = next_month_return

    return portfolio_returns

portfolio_returns = sector_rotation_strategy(pivoted_data, lookback_period=3, top_n=3)
portfolio_returns.dropna(inplace=True)

portfolio_returns.head()
python
portfolio_returns['Cumulative Return'] = (1 + portfolio_returns['Portfolio Return']).cumprod()

pivoted_data['Market Average'] = pivoted_data.mean(axis=1)
market_returns = pivoted_data['Market Average'].resample('ME').last().pct_change()
market_cumulative_return = (1 + market_returns).cumprod()

plt.figure(figsize=(12, 7))
plt.plot(portfolio_returns.index, portfolio_returns['Cumulative Return'], label='Sector Rotation Strategy', color='green')
plt.plot(market_cumulative_return.index, market_cumulative_return, label='Market Average', color='blue')

plt.title('Sector Rotation Strategy vs Market Average', fontsize=16, fontweight='bold')
plt.xlabel('Date', fontsize=12)
plt.ylabel('Cumulative Return', fontsize=12)
plt.legend()
plt.grid(True)
plt.show()
python
final_strategy_return = portfolio_returns['Cumulative Return'].iloc[-1]

final_market_return = market_cumulative_return.iloc[-1]

print(f"Final cumulative return of sector rotation strategy: {final_strategy_return:.2f}")
print(f"Final cumulative return of market average: {final_market_return:.2f}")

strategy_daily_returns = portfolio_returns['Portfolio Return'].dropna()
sharpe_ratio = (strategy_daily_returns.mean() / strategy_daily_returns.std()) * np.sqrt(12)
print(f"Sharpe Ratio of the sector rotation strategy: {sharpe_ratio:.2f}")