Exercise - Unconstrained Optimization#

Data#

All the analysis below applies to the data set,

  • data/spx_weekly_returns.xlsx

  • The file has weekly returns.

  • For annualization, use 52 periods per year.

Consider only the following 10 stocks…

TICKS =  ['AAPL','NVDA','MSFT','GOOGL','AMZN','META','TSLA','AVGO','BRK/B','LLY']

As well as the ETF,

TICK_ETF = 'SPY'

Data Processing#

import pandas as pd
INFILE = '../data/spx_returns_weekly.xlsx'
SHEET_INFO = 's&p500 names'
SHEET_RETURNS = 's&p500 rets'
SHEET_BENCH = 'benchmark rets'

FREQ = 52
info = pd.read_excel(INFILE,sheet_name=SHEET_INFO)
info.set_index('ticker',inplace=True)
info.loc[TICKS]
name mkt cap
ticker
AAPL Apple Inc 3.008822e+12
NVDA NVIDIA Corp 3.480172e+12
MSFT Microsoft Corp 3.513735e+12
GOOGL Alphabet Inc 2.145918e+12
AMZN Amazon.com Inc 2.303536e+12
META Meta Platforms Inc 1.745094e+12
TSLA Tesla Inc 9.939227e+11
AVGO Broadcom Inc 1.148592e+12
BRK/B Berkshire Hathaway Inc 1.064240e+12
LLY Eli Lilly & Co 7.332726e+11
rets = pd.read_excel(INFILE,sheet_name=SHEET_RETURNS)
rets.set_index('date',inplace=True)
rets = rets[TICKS]
bench = pd.read_excel(INFILE,sheet_name=SHEET_BENCH)
bench.set_index('date',inplace=True)
rets[TICK_ETF] = bench[TICK_ETF]

1. Risk Statistics#

1.1.#

Display a table with the following metrics for each of the return series.

  • mean (annualized)

  • volatility (annualized)

  • Sharpe ratio (annualized)

  • skewness

  • kurtosis

  • maximum drawdown

Note#

We have total returns, and Sharpe ratio is technically defined for excess returns. Don’t worry about the difference. (Or subtract SHV if you prefer.)

1.2.#

As a standalone investment, which is most attractive? And least? Justify your answer.

1.3.#

For each investment, estimate a regression against SPY. Report the

  • alpha (annualized as a mean)

  • beta

  • info ratio

  • r-squared

Based on this table, which investment seems most attractive relative to holding SPY?


2. Portfolio Allocation#

2.1.#

Display the correlation matrix of the returns.

  • Based on this information, which investment do you anticipate will get extra weight in the portfolio, beyond what it would merit for its mean return?

  • Report the maximally correlated assets and the minimally correlated assets.

2.2.#

Calculate the weights of the mean-variance optimized portfolio, also called the tangency portfolio.

  • Display a table indexed by each investment, with the optimal weights in one column and the Sharpe ratios in another column.

  • Do the investments with the best Sharpe ratios tend to get the biggest weights?

Note:#

To estimate the optimal weights, consider using the provided function below.

def optimized_weights(returns,dropna=True,scale_cov=1):
    if dropna:
        returns = returns.dropna()

    covmat_full = returns.cov()
    covmat_diag = np.diag(np.diag(covmat_full))
    covmat = scale_cov * covmat_full + (1-scale_cov) * covmat_diag

    weights = np.linalg.solve(covmat,returns.mean())
    weights = weights / weights.sum()

    if returns.mean() @ weights < 0:
        weights = -weights

    return pd.DataFrame(weights, index=returns.columns)

2.3.#

Report the following performance statistics of the portfolio achieved with the optimized weights calculated above.

  • mean

  • volatility

  • Sharpe

(Annualize all three statistics.)

2.4.#

Try dropping the asset which had the biggest short position from the investment set. Re-run the optimization. What do you think of these new weights compared to the original optimized weights?

What is going on?