Part 1

Number 1

# tickers and timeframe
tickers <- c("SPY", "QQQ", "EEM", "IWM", "EFA", "TLT", "IYR", "GLD")
start_date <- "2010-01-01"
end_date   <- "2025-12-31"
# daily data
getSymbols(tickers, src = "yahoo", from = start_date, to = end_date)
## [1] "SPY" "QQQ" "EEM" "IWM" "EFA" "TLT" "IYR" "GLD"
prices_list <- lapply(tickers, function(x) Ad(get(x)))
etf_prices  <- do.call(merge, prices_list)

colnames(etf_prices) <- tickers

etf_prices <- na.locf(etf_prices)
head(etf_prices)
##                 SPY      QQQ      EEM      IWM      EFA      TLT      IYR
## 2010-01-04 84.79637 40.29079 30.35151 51.36657 35.12844 56.13517 26.76811
## 2010-01-05 85.02083 40.29079 30.57180 51.18993 35.15940 56.49766 26.83239
## 2010-01-06 85.08071 40.04776 30.63576 51.14177 35.30801 55.74141 26.82070
## 2010-01-07 85.43986 40.07380 30.45810 51.51911 35.17179 55.83518 27.06027
## 2010-01-08 85.72420 40.40363 30.69973 51.80011 35.45044 55.81018 26.87914
## 2010-01-11 85.84389 40.23870 30.63576 51.59138 35.74147 55.50392 27.00768
##               GLD
## 2010-01-04 109.80
## 2010-01-05 109.70
## 2010-01-06 111.51
## 2010-01-07 110.82
## 2010-01-08 111.37
## 2010-01-11 112.85

Number 2: Calculating Monthly Discrete Returns

To calculate monthly returns, we first need to extract the closing prices on the last trading day of each month. Then, we apply the Rate of Change calculation across our dataset to find the discrete (simple) returns.

month_ends <- endpoints(etf_prices, on = "months")

monthly_prices <- etf_prices[month_ends, ]

monthly_returns <- ROC(monthly_prices, type = "discrete")

monthly_returns <- na.omit(monthly_returns)
head(monthly_returns)
##                    SPY         QQQ          EEM         IWM          EFA
## 2010-02-26  0.03119470  0.04603857  0.017764127  0.04475145  0.002667738
## 2010-03-31  0.06087975  0.07710947  0.081108773  0.08230654  0.063854321
## 2010-04-30  0.01546981  0.02242508 -0.001661748  0.05678449 -0.028046102
## 2010-05-28 -0.07945415 -0.07392400 -0.093935922 -0.07536592 -0.111927633
## 2010-06-30 -0.05174090 -0.05975660 -0.013986709 -0.07743442 -0.020619284
## 2010-07-30  0.06830005  0.07258292  0.109325297  0.06730967  0.116104021
##                     TLT         IYR          GLD
## 2010-02-26 -0.003424235  0.05457094  0.032748219
## 2010-03-31 -0.020573681  0.09748433 -0.004386396
## 2010-04-30  0.033217884  0.06388103  0.058834363
## 2010-05-28  0.051083857 -0.05683536  0.030513147
## 2010-06-30  0.057978316 -0.04670111  0.023553189
## 2010-07-30 -0.009463286  0.09404800 -0.050871157

Number 3: Download Fama-French 3 Factors

Using the frenchdata library to pull the “Fama/French 3 Factors” dataset. This file contains both monthly and annual data; we will extract the monthly subset.

ff_data_raw <- download_french_data("Fama/French 3 Factors")

ff_monthly <- ff_data_raw$subsets$data[[1]]

ff_factors <- ff_monthly %>%
  mutate(
    date = ym(date),
    across(c(`Mkt-RF`, SMB, HML, RF), ~ . / 100)
  ) %>%
  filter(date >= "2010-01-01" & date <= "2025-12-31")
head(ff_factors)
## # A tibble: 6 × 5
##   date       `Mkt-RF`     SMB     HML     RF
##   <date>        <dbl>   <dbl>   <dbl>  <dbl>
## 1 2010-01-01  -0.0335  0.0043  0.0033 0     
## 2 2010-02-01   0.0339  0.0118  0.0318 0     
## 3 2010-03-01   0.063   0.0146  0.0219 0.0001
## 4 2010-04-01   0.0199  0.0484  0.0296 0.0001
## 5 2010-05-01  -0.079   0.0013 -0.0248 0.0001
## 6 2010-06-01  -0.0556 -0.0179 -0.0473 0.0001

Number 4: Merging ETF Returns and Fama-French Factors

To perform regressions later, we need all variables in a single table. We will convert our ETF returns into a data frame, align the dates to the first of each month, and then join them with the Fama-French factors.

etf_df <- as.data.frame(monthly_returns)
etf_df$date <- index(monthly_returns)

etf_df <- etf_df %>%
  mutate(date = floor_date(date, "month"))

merged_data <- etf_df %>%
  left_join(ff_factors, by = "date") %>%
  relocate(date)

merged_data <- na.omit(merged_data)
head(merged_data)
##         date         SPY         QQQ          EEM         IWM          EFA
## 1 2010-02-01  0.03119470  0.04603857  0.017764127  0.04475145  0.002667738
## 2 2010-03-01  0.06087975  0.07710947  0.081108773  0.08230654  0.063854321
## 3 2010-04-01  0.01546981  0.02242508 -0.001661748  0.05678449 -0.028046102
## 4 2010-05-01 -0.07945415 -0.07392400 -0.093935922 -0.07536592 -0.111927633
## 5 2010-06-01 -0.05174090 -0.05975660 -0.013986709 -0.07743442 -0.020619284
## 6 2010-07-01  0.06830005  0.07258292  0.109325297  0.06730967  0.116104021
##            TLT         IYR          GLD  Mkt-RF     SMB     HML    RF
## 1 -0.003424235  0.05457094  0.032748219  0.0339  0.0118  0.0318 0e+00
## 2 -0.020573681  0.09748433 -0.004386396  0.0630  0.0146  0.0219 1e-04
## 3  0.033217884  0.06388103  0.058834363  0.0199  0.0484  0.0296 1e-04
## 4  0.051083857 -0.05683536  0.030513147 -0.0790  0.0013 -0.0248 1e-04
## 5  0.057978316 -0.04670111  0.023553189 -0.0556 -0.0179 -0.0473 1e-04
## 6 -0.009463286  0.09404800 -0.050871157  0.0692  0.0022 -0.0050 1e-04

Number 5: Data Subsetting

First, we filter our merged dataset to the specified 60-month window: March 2020 through February 2025.

window_data <- merged_data %>%
  filter(date >= "2020-03-01" & date <= "2025-02-28")

mkt_excess <- window_data[["Mkt-RF"]]

betas <- numeric(length(tickers))
resid_vars <- numeric(length(tickers))

for (i in 1:length(tickers)) {
  ticker <- tickers[i]
  
  etf_excess <- window_data[[ticker]] - window_data[["RF"]]

  capm_fit <- lm(etf_excess ~ mkt_excess)

  betas[i] <- coef(capm_fit)[2]

  resid_vars[i] <- var(resid(capm_fit))
}

var_mkt <- var(mkt_excess)

beta_matrix <- matrix(betas, ncol = 1)

cov_matrix_capm <- (beta_matrix %*% t(beta_matrix)) * var_mkt + diag(resid_vars)

rownames(cov_matrix_capm) <- tickers
colnames(cov_matrix_capm) <- tickers
inv_cov <- solve(cov_matrix_capm)

ones <- rep(1, length(tickers))

num <- inv_cov %*% ones
den <- as.numeric(t(ones) %*% inv_cov %*% ones)
mvp_weights <- num / den

mvp_weights <- as.vector(mvp_weights)
names(mvp_weights) <- tickers

etf_returns_matrix <- as.matrix(window_data %>% select(all_of(tickers)))
mvp_monthly_returns <- etf_returns_matrix %*% mvp_weights

mvp_results <- data.frame(
  date = window_data$date,
  MVP_Return = as.numeric(mvp_monthly_returns)
)

print(round(mvp_weights, 4))
##     SPY     QQQ     EEM     IWM     EFA     TLT     IYR     GLD 
##  0.2744 -0.1429  0.1719 -0.1891  0.1748  0.3330 -0.0312  0.4092
head(mvp_results)
##         date   MVP_Return
## 1 2020-03-01 -0.008541199
## 2 2020-04-01  0.040925826
## 3 2020-05-01  0.009933717
## 4 2020-06-01  0.018435373
## 5 2020-07-01  0.075344956
## 6 2020-08-01 -0.011832689

Number 6: Estimating Fama-French 3-Factor Parameters

We will use the same window_data (March 2020 - Feb 2025) as the previous question. This time, we run a multiple regression for each ETF against the Market, SMB, and HML factors.

B_matrix <- matrix(NA, nrow = length(tickers), ncol = 3)
rownames(B_matrix) <- tickers
colnames(B_matrix) <- c("Mkt_Beta", "SMB_Beta", "HML_Beta")

resid_vars_ff3 <- numeric(length(tickers))

for (i in 1:length(tickers)) {
  ticker <- tickers[i]

  etf_excess <- window_data[[ticker]] - window_data[["RF"]]

  ff3_fit <- lm(etf_excess ~ window_data[["Mkt-RF"]] + window_data[["SMB"]] + window_data[["HML"]])

  B_matrix[i, ] <- coef(ff3_fit)[2:4]

  resid_vars_ff3[i] <- var(resid(ff3_fit))
}

round(head(B_matrix), 4)
##     Mkt_Beta SMB_Beta HML_Beta
## SPY   0.9853  -0.1487   0.0194
## QQQ   1.0813  -0.0890  -0.3994
## EEM   0.6794   0.0834   0.1476
## IWM   1.0058   0.8895   0.2660
## EFA   0.8477  -0.1152   0.2169
## TLT   0.3443  -0.0658  -0.2622

Next, we calculate the covariance matrix of the factors themselves, and apply the Multi-Index formula to generate our ETF covariance matrix.

factor_data <- window_data[, c("Mkt-RF", "SMB", "HML")]
Sigma_F <- cov(factor_data)

cov_matrix_ff3 <- (B_matrix %*% Sigma_F %*% t(B_matrix)) + diag(resid_vars_ff3)

rownames(cov_matrix_ff3) <- tickers
colnames(cov_matrix_ff3) <- tickers

Finally, we use the same Minimum Variance Portfolio formula as before, but substitute our newly generated FF3 covariance matrix.

inv_cov_ff3 <- solve(cov_matrix_ff3)

ones <- rep(1, length(tickers))
num_ff3 <- inv_cov_ff3 %*% ones
den_ff3 <- as.numeric(t(ones) %*% inv_cov_ff3 %*% ones)
mvp_weights_ff3 <- as.vector(num_ff3 / den_ff3)
names(mvp_weights_ff3) <- tickers

etf_returns_matrix <- as.matrix(window_data[, tickers])
mvp_monthly_returns_ff3 <- etf_returns_matrix %*% mvp_weights_ff3

mvp_results_ff3 <- data.frame(
  date = window_data$date,
  MVP_FF3_Return = as.numeric(mvp_monthly_returns_ff3)
)

print("FF3 Estimated MVP Weights:")
## [1] "FF3 Estimated MVP Weights:"
print(round(mvp_weights_ff3, 4))
##     SPY     QQQ     EEM     IWM     EFA     TLT     IYR     GLD 
##  0.1399 -0.2280  0.1988 -0.0563  0.1810  0.3777 -0.0138  0.4007

Number 7: Out-of-Sample Testing: Realized Returns for March 2025

To find the realized returns, we isolate the actual ETF returns for March 2025 and multiply them by the respective optimal weights we calculated in the previous steps.

march_data <- merged_data %>%
  filter(date == "2025-03-01")

march_returns <- as.numeric(march_data[ , tickers])
names(march_returns) <- tickers

realized_return_capm <- sum(march_returns * mvp_weights)

realized_return_ff3 <- sum(march_returns * mvp_weights_ff3)

results_comparison <- data.frame(
  Model = c("CAPM (Single-Index) MVP", "FF3 (Multi-Index) MVP"),
  Realized_Return_March_2025 = c(realized_return_capm, realized_return_ff3)
)

print(results_comparison)
##                     Model Realized_Return_March_2025
## 1 CAPM (Single-Index) MVP                 0.04615948
## 2   FF3 (Multi-Index) MVP                 0.04957562

Number 8: Rolling Window: Estimating New Weights for April 2025

We shift our 60-month window forward by one month (April 2020 through March 2025) to re-estimate our covariance matrices and update our portfolio weights before April begins.

window_data_apr <- merged_data %>%
  filter(date >= "2020-04-01" & date <= "2025-03-31")

mkt_excess_apr <- window_data_apr[["Mkt-RF"]]

betas_apr <- numeric(length(tickers))
resid_vars_apr <- numeric(length(tickers))

for (i in 1:length(tickers)) {
  ticker <- tickers[i]
  etf_excess <- window_data_apr[[ticker]] - window_data_apr[["RF"]]
  
  capm_fit <- lm(etf_excess ~ mkt_excess_apr)
  betas_apr[i] <- coef(capm_fit)[2]
  resid_vars_apr[i] <- var(resid(capm_fit))
}

var_mkt_apr <- var(mkt_excess_apr)
beta_matrix_apr <- matrix(betas_apr, ncol = 1)
cov_capm_apr <- (beta_matrix_apr %*% t(beta_matrix_apr)) * var_mkt_apr + diag(resid_vars_apr)

inv_cov_capm_apr <- solve(cov_capm_apr)
ones <- rep(1, length(tickers))
mvp_weights_capm_apr <- as.vector((inv_cov_capm_apr %*% ones) / as.numeric(t(ones) %*% inv_cov_capm_apr %*% ones))


B_matrix_apr <- matrix(NA, nrow = length(tickers), ncol = 3)
resid_vars_ff3_apr <- numeric(length(tickers))

for (i in 1:length(tickers)) {
  ticker <- tickers[i]
  etf_excess <- window_data_apr[[ticker]] - window_data_apr[["RF"]]
  
  ff3_fit <- lm(etf_excess ~ window_data_apr[["Mkt-RF"]] + window_data_apr[["SMB"]] + window_data_apr[["HML"]])
  B_matrix_apr[i, ] <- coef(ff3_fit)[2:4]
  resid_vars_ff3_apr[i] <- var(resid(ff3_fit))
}

Sigma_F_apr <- cov(window_data_apr[, c("Mkt-RF", "SMB", "HML")])
cov_ff3_apr <- (B_matrix_apr %*% Sigma_F_apr %*% t(B_matrix_apr)) + diag(resid_vars_ff3_apr)

inv_cov_ff3_apr <- solve(cov_ff3_apr)
mvp_weights_ff3_apr <- as.vector((inv_cov_ff3_apr %*% ones) / as.numeric(t(ones) %*% inv_cov_ff3_apr %*% ones))

Now that we have our newly rebalanced portfolio weights based strictly on data prior to April, we can apply them to the actual April 2025 market returns.

april_data <- merged_data %>%
  filter(date == "2025-04-01")

april_returns <- as.numeric(april_data[ , tickers])
names(april_returns) <- tickers

realized_return_capm_apr <- sum(april_returns * mvp_weights_capm_apr)
realized_return_ff3_apr <- sum(april_returns * mvp_weights_ff3_apr)

results_april <- data.frame(
  Model = c("CAPM (Single-Index) MVP", "FF3 (Multi-Index) MVP"),
  Realized_Return_April_2025 = c(realized_return_capm_apr, realized_return_ff3_apr)
)

print(results_april)
##                     Model Realized_Return_April_2025
## 1 CAPM (Single-Index) MVP                 0.02052597
## 2   FF3 (Multi-Index) MVP                 0.01846650

Part 2

Chapter 5: Problem Set 12

Visit Professor Kenneth French’s data library Web site: http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html and download the monthly returns of “6 portfolios formed on size and book-to-market (2 × 3).” Choose the value-weighted series for the period from January 1930–December 2018. Split the sample in half and compute the average, SD, skew, and kurtosis for each of the six portfolios for the two halves. Do the six split-halves statistics suggest to you that returns come from the same distribution over the entire period?

ff_portfolios <- download_french_data("6 Portfolios Formed on Size and Book-to-Market (2 x 3)")

vw_returns <- ff_portfolios$subsets$data[[1]]

clean_data <- vw_returns %>%
  mutate(
    date = ym(date),
    across(-date, ~ . / 100)
  ) %>%
  filter(date >= "1930-01-01" & date <= "2018-12-31")

split_data <- clean_data %>%
  mutate(
    Period = if_else(date <= "1974-06-01", 
                     "1st Half (1930-1974)", 
                     "2nd Half (1974-2018)")
  )

summary_stats <- split_data %>%
  pivot_longer(cols = -c(date, Period), names_to = "Portfolio", values_to = "Return") %>%
  group_by(Period, Portfolio) %>%
  summarise(
    Average  = mean(Return),
    SD       = sd(Return),
    Skewness = skewness(Return),
    Kurtosis = kurtosis(Return),
    .groups  = 'drop'
  )

print(summary_stats, n = 12)
## # A tibble: 12 × 6
##    Period               Portfolio  Average     SD Skewness Kurtosis
##    <chr>                <chr>        <dbl>  <dbl>    <dbl>    <dbl>
##  1 1st Half (1930-1974) BIG HiBM   0.0119  0.0891    1.76     14.4 
##  2 1st Half (1930-1974) BIG LoBM   0.00765 0.0571    0.178     6.86
##  3 1st Half (1930-1974) ME1 BM2    0.0117  0.0842    1.58     12.7 
##  4 1st Half (1930-1974) ME2 BM2    0.00812 0.0673    1.71     17.5 
##  5 1st Half (1930-1974) SMALL HiBM 0.0148  0.102     2.28     17.0 
##  6 1st Half (1930-1974) SMALL LoBM 0.00971 0.0823    1.18      9.03
##  7 2nd Half (1974-2018) BIG HiBM   0.0114  0.0489   -0.516     2.78
##  8 2nd Half (1974-2018) BIG LoBM   0.00978 0.0470   -0.333     1.97
##  9 2nd Half (1974-2018) ME1 BM2    0.0135  0.0528   -0.531     3.40
## 10 2nd Half (1974-2018) ME2 BM2    0.0106  0.0434   -0.472     2.63
## 11 2nd Half (1974-2018) SMALL HiBM 0.0142  0.0550   -0.463     4.28
## 12 2nd Half (1974-2018) SMALL LoBM 0.00996 0.0669   -0.407     2.14

No, the split-halves statistics strongly suggest that the returns do NOT come from the same distribution over the entire period.

While the expected return (mean) remained somewhat consistent, the shape of the risk changed entirely. The shift from high-volatility, right-skewed, extreme fat-tailed returns (1930-1974) to lower-volatility, left-skewed, more normally distributed returns (1974-2018) proves these are two distinct statistical regimes.

Chapter 6: Problem Set 21

Consider the following information about a risky portfolio that you manage and a risk-free asset: \(E(r_{P}) = 11%\), \(σ_{P} = 15%\), \(r_{f} = 5%\).

  1. Your client wants to invest a proportion of her total investment budget in your risky fund to provide an expected rate of return on her overall or complete portfolio equal to 8%. What proportion should she invest in the risky portfolio, \(P\), and what proportion in the risk-free asset?
  2. What will be the standard deviation of the rate of return on her portfolio?
  3. Another client wants the highest return possible subject to the constraint that you limit his standard deviation to be no more than 12%. Which client is more risk averse?
E_rp <- 0.11     # Expected return of the risky portfolio (11%)
sigma_p <- 0.15  # Standard deviation of the risky portfolio (15%)
r_f <- 0.05      # Risk-free rate (5%)

Answer for question A

The expected return of a complete portfolio (\(C\)) is the weighted average of the risky asset and the risk-free asset: \[E(r_C) = y \cdot E(r_P) + (1 - y) \cdot r_f\] We can rearrange this formula to solve for the weight of the risky portfolio (\(y\)): \[y = \frac{E(r_C) - r_f}{E(r_P) - r_f}\]

E_rc_target <- 0.08 

y_client1 <- (E_rc_target - r_f) / (E_rp - r_f)

w_rf_client1 <- 1 - y_client1

cat("Proportion in Risky Portfolio (y):", y_client1, "\n")
## Proportion in Risky Portfolio (y): 0.5
cat("Proportion in Risk-Free Asset (1-y):", w_rf_client1, "\n")
## Proportion in Risk-Free Asset (1-y): 0.5

Answer: The client should invest 50% of her budget in the risky portfolio and 50% in the risk-free asset.

Answer for question B

Since the risk-free asset has a standard deviation of zero, the standard deviation of the complete portfolio is simply the proportion invested in the risky asset multiplied by its standard deviation: \[\sigma_C = y \cdot \sigma_P\]

sigma_c_client1 <- y_client1 * sigma_p

cat("Standard Deviation of Complete Portfolio:", sigma_c_client1, "\n")
## Standard Deviation of Complete Portfolio: 0.075

Answer: The standard deviation of the rate of return on her portfolio will be 7.5% (\(0.075\)).

Answer for question C

To maximize return, the second client will push their risk allocation to the absolute maximum limit of 12%. Let’s calculate what proportion (\(y\)) that requires.

sigma_c_target <- 0.12

y_client2 <- sigma_c_target / sigma_p

cat("Client 2 Proportion in Risky Portfolio:", y_client2, "\n")
## Client 2 Proportion in Risky Portfolio: 0.8

Answer: The first client is more risk-averse. The first client is only comfortable taking on 7.5% volatility (allocating 50% to the risky asset), whereas the second client is willing to endure 12% volatility (allocating 80% to the risky asset) in pursuit of higher returns.

Chapter 6: Problem Set 22

Investment Management Inc. (IMI) uses the capital market line to make asset allocation recommendations. IMI derives the following forecasts:

  • Expected return on the market portfolio: 12%
  • Standard deviation on the market portfolio: 20%
  • Risk-free rate: 5%

Samuel Johnson seeks IMI’s advice for a portfolio asset allocation. Johnson informs IMI that he wants the standard deviation of the portfolio to equal half of the standard deviation for the market portfolio. Using the capital market line, what expected return can IMI provide subject to Johnson’s risk constraint?

E_rm <- 0.12      # Expected return of the market (12%)
sigma_m <- 0.20   # Standard deviation of the market (20%)
r_f <- 0.05       # Risk-free rate (5%)

sigma_p <- 0.5 * sigma_m

The Capital Market Line formula is used to calculate the highest possible expected return for a given level of risk, assuming the risky asset is the broad market portfolio.The formula is: \(E(r_P) = r_f + \frac{E(r_M) - r_f}{\sigma_M} \times \sigma_P\)

sharpe_market <- (E_rm - r_f) / sigma_m

E_rp <- r_f + (sharpe_market * sigma_p)

cat("Target Portfolio Standard Deviation:", sigma_p, "\n")
## Target Portfolio Standard Deviation: 0.1
cat("Market Sharpe Ratio (Slope):", sharpe_market, "\n")
## Market Sharpe Ratio (Slope): 0.35
cat("Expected Portfolio Return:", E_rp, "\n")
## Expected Portfolio Return: 0.085

By allocating his assets to achieve a standard deviation of 10% (half of the market’s 20%), Samuel Johnson can expect a portfolio return of 8.5%. This is achieved by investing exactly 50% of his capital in the Market Portfolio and 50% in Risk-Free assets.

Chapter 6: CFA Problem 4, 5, 8

Question 4

Which indifference curve represents the greatest level of utility that can be achieved by the investor?

In portfolio theory, indifference curves that are further to the “Northwest” (meaning higher expected return for the same or less risk) represent higher levels of utility.

While Curves 3 and 4 represent higher utility overall, they are physically unattainable because they lie completely above the Capital Allocation Line (CAL). Indifference Curve 2 is the highest curve the investor can actually reach, as it touches the CAL at exactly one point (Point F).

Answer: Indifference Curve 2

Question 5

Which point designates the optimal portfolio of risky assets?

The Capital Allocation Line (CAL) is visually constructed by drawing a straight line from the risk-free asset (the starting dot on the y-axis) through the optimal portfolio of risky assets. In this standard textbook graph, Point E represents that specific 100% risky portfolio.

Answer: Point E

Question 8

You manage an equity fund with an expected risk premium of 10% and an expected standard deviation of 14%. The rate on Treasury bills is 6%. Your client chooses to invest $60,000 of her portfolio in your equity fund and $40,000 in a T-bill money market fund. What are the expected return and standard deviation of return on your client’s portfolio?

risk_premium <- 0.10  # Expected risk premium of equity fund (10%)
sigma_p <- 0.14       # Standard deviation of equity fund (14%)
r_f <- 0.06           # Risk-free rate (6%)

# Investment amounts
invest_equity <- 60000
invest_tbill <- 40000
total_budget <- invest_equity + invest_tbill

First, we determine the weights of the assets in the portfolio. Then, we apply the portfolio expected return and standard deviation formulas.

y <- invest_equity / total_budget

expected_return_c <- r_f + y * risk_premium

sigma_c <- y * sigma_p

cat("Weight in Risky Fund (y):", y, "\n")
## Weight in Risky Fund (y): 0.6
cat("Expected Portfolio Return:", expected_return_c, "\n")
## Expected Portfolio Return: 0.12
cat("Portfolio Standard Deviation:", sigma_c, "\n")
## Portfolio Standard Deviation: 0.084

By investing $60,000 in the equity fund and $40,000 in T-bills, the client’s complete portfolio will have an expected return of 12% and a standard deviation of 8.4%.

Chapter 7: Problem Set 11

Stocks offer an expected rate of return of 18% with a standard deviation of 22%. Gold offers an expected return of 10% with a standard deviation of 30%.

  1. In light of the apparent inferiority of gold with respect to both mean return and volatility, would anyone hold gold? If so, demonstrate graphically why one would do so.
  2. Given the data above, reanswer (a) with the additional assumption that the correlation
    coefficient between gold and stocks equals 1. Draw a graph illustrating why one would or would not hold gold in one’s portfolio.
  3. Could the set of assumptions in part (b) for expected returns, standard deviations, and
    correlation represent an equilibrium for the security market?

Answer for question A

Yes, an investor might still hold gold despite its lower expected return and higher volatility. This is due to the diversification benefits gold can offer.If the correlation coefficient (\(\rho\)) between the returns of stocks and gold is less than 1 (especially if it is low or negative), combining the two assets can reduce the overall risk (standard deviation) of the portfolio to a level lower than holding stocks alone. The portfolio variance formula demonstrates this: \[\sigma_p^2=w_s^2\sigma_s^2+w_g^2\sigma_g^2+2w_sw_g\sigma_s\sigma_g\rho\]

When \(\rho\) is sufficiently low, the covariance term pulls the total portfolio variance down, creating an “efficient frontier” that bows to the left.

library(ggplot2)

# Asset Data
er_s <- 0.18
sd_s <- 0.22
er_g <- 0.10
sd_g <- 0.30
rho <- 0 # Assuming 0 correlation for part A

# Portfolio weights for Gold from 0 to 1
w_g <- seq(0, 1, by = 0.01)
w_s <- 1 - w_g

# Expected Return and Standard Deviation
er_p <- w_s * er_s + w_g * er_g
sd_p <- sqrt((w_s * sd_s)^2 + (w_g * sd_g)^2 + 2 * w_s * w_g * sd_s * sd_g * rho)

df_a <- data.frame(Expected_Return = er_p, Standard_Deviation = sd_p, Weight_Gold = w_g)

# Plot
ggplot(df_a, aes(x = Standard_Deviation, y = Expected_Return)) +
  geom_path(color = "blue", size = 1) +
  geom_point(aes(x = sd_s, y = er_s), color = "black", size = 3) +
  geom_point(aes(x = sd_g, y = er_g), color = "gold3", size = 3) +
  annotate("text", x = sd_s, y = er_s + 0.005, label = "Stocks") +
  annotate("text", x = sd_g, y = er_g + 0.005, label = "Gold") +
  labs(title = "Investment Opportunity Set (Correlation = 0)",
       x = "Portfolio Standard Deviation",
       y = "Portfolio Expected Return") +
  theme_minimal()

Answer for question B

If the correlation between gold and stocks is exactly \(1\), no rational, risk-averse investor would hold a long position in gold.When \(\rho=1\), there are absolutely no diversification benefits. The portfolio standard deviation becomes a simple weighted average of the individual standard deviations: \[\sigma_p=w_s\sigma_s+w_g\sigma_g\]

Because stocks strictly dominate gold (they offer a higher return for less risk), combining them with a perfect positive correlation simply creates a straight line connecting the two assets on the risk-return graph. Moving any funds from stocks to gold will simultaneously decrease expected return and increase risk.

rho_b <- 1

sd_p_b <- sqrt((w_s * sd_s)^2 + (w_g * sd_g)^2 + 2 * w_s * w_g * sd_s * sd_g * rho_b)

df_b <- data.frame(Expected_Return = er_p, Standard_Deviation = sd_p_b)

# Plot
ggplot(df_b, aes(x = Standard_Deviation, y = Expected_Return)) +
  geom_path(color = "red", size = 1) +
  geom_point(aes(x = sd_s, y = er_s), color = "black", size = 3) +
  geom_point(aes(x = sd_g, y = er_g), color = "gold3", size = 3) +
  annotate("text", x = sd_s, y = er_s + 0.005, label = "Stocks") +
  annotate("text", x = sd_g, y = er_g + 0.005, label = "Gold") +
  labs(title = "Investment Opportunity Set (Correlation = 1)",
       x = "Portfolio Standard Deviation",
       y = "Portfolio Expected Return") +
  theme_minimal()

Answer for question C

No, this set of assumptions cannot represent a stable equilibrium for the security market.In a perfectly functioning market, if two assets are perfectly correlated (\(\rho=1\)) and one strictly dominates the other (Stocks have higher return and lower risk), an arbitrage or extreme substitution opportunity exists. Every rational investor would want to sell (or short) gold and buy stocks.

This massive selling pressure on gold would drive its current price down, which mathematically forces its expected future return to rise. Conversely, the high demand for stocks would drive their current price up, lowering their expected return. This price adjustment process would continue until gold is no longer strictly dominated by stocks, thereby restoring market equilibrium.

Chapter 7: Problem Set 12

Suppose that there are many stocks in the security market and that the characteristics of stocks A and B are given as follows:

Stock Expected Return Standard Deviation
A 10% 5%
B 15 10

Correlation = \(-1\)

Suppose that it is possible to borrow at the risk-free rate, \(r_{f}\). What must be the value of the risk free rate? (Hint: Think about constructing a risk-free portfolio from stocks \(A\) and \(B\).)

Answer

er_a <- 0.10
sd_a <- 0.05
er_b <- 0.15
sd_b <- 0.10

# To achieve zero variance with a correlation of -1:
# w_a * sd_a = w_b * sd_b
# w_a * sd_a = (1 - w_a) * sd_b
# w_a * (sd_a + sd_b) = sd_b

w_a <- sd_b / (sd_a + sd_b)
w_b <- 1 - w_a

rf <- (w_a * er_a) + (w_b * er_b)

cat("Weight of Stock A for zero risk:", round(w_a * 100, 2), "%\n")
## Weight of Stock A for zero risk: 66.67 %
cat("Weight of Stock B for zero risk:", round(w_b * 100, 2), "%\n")
## Weight of Stock B for zero risk: 33.33 %
cat("Implied Risk-Free Rate (rf):", round(rf * 100, 2), "%\n")
## Implied Risk-Free Rate (rf): 11.67 %

The risk-free rate \(r_f\) must be 11.67%.

Chapter 7: CFA Problem 12

Abigail Grace has a $900,000 fully diversified portfolio. She subsequently inherits ABC Company common stock worth $100,000. Her financial adviser provided her with the following estimates:

Risk and Return Characteristics

Portfolio/Company Expected Monthly Returns Standard Deviation of Monthly Returns
Original Portfolio 0.67% 2.37%
ABC Company 1.25 2.95

The correlation coefficient of ABC stock returns with the original portfolio returns is .40.

  1. The inheritance changes Grace’s overall portfolio, and she is deciding whether to keep the ABC stock. Assuming Grace keeps the ABC stock, calculate the:
  1. Expected return of her new portfolio, which includes the ABC stock.
  2. Covariance of ABC stock returns with the original portfolio returns.
  3. Standard deviation of her new portfolio, which includes the ABC stock.
  1. If Grace sells the ABC stock, she will invest the proceeds in risk-free government securities yielding .42% monthly. Assuming Grace sells the ABC stock and replaces it with the government securities, calculate the
  1. Expected return of her new portfolio, which includes the government securities.
  2. Covariance of the government security returns with the original portfolio returns.
  3. Standard deviation of her new portfolio, which includes the government securities.
  1. Determine whether the systematic risk of her new portfolio, which includes the government securities, will be higher or lower than that of her original portfolio.

  2. On the basis of conversations with her husband, Grace is considering selling the $100,000 of ABC stock and acquiring $100,000 of XYZ Company common stock instead. XYZ stock has the same expected return and standard deviation as ABC stock. Her husband comments, “It doesn’t matter whether you keep all of the ABC stock or replace it with $100,000 of XYZ stock.” State whether her husband’s comment is correct or incorrect. Justify your response.

  3. In a recent discussion with her financial adviser, Grace commented, “If I just don’t lose money in my portfolio, I will be satisfied.” She went on to say, “I am more afraid of losing money than I am concerned about achieving high returns.”

  1. Describe one weakness of using standard deviation of returns as a risk measure for Grace.
  2. Identify an alternate risk measure that is more appropriate under the circumstances.

Answers

Question A

Before calculating, we need to establish the portfolio weights. The total portfolio value is $1,000,000 ($900,000 original + $100,000 ABC).

  • Weight of Original Portfolio (\(w_o\)): 900,000 / 1,000,000 = 0.90 (or 90%)
  • Weight of ABC Stock (\(w_{abc}\)): 100,000 / 1,000,000 = 0.10 (or 10%)
  1. Expected Return of the New Portfolio: The expected return is the weighted average of the individual expected returns: \[E(R_p) = w_oE(R_o) + w_{abc}E(R_{abc})\] \[E(R_p) = (0.90 \times 0.67\%) + (0.10 \times 1.25\%) = 0.603\% + 0.125\% = 0.728\%\]

  2. Covariance of ABC Stock Returns with Original Portfolio:Covariance is calculated using the correlation coefficient (\(\rho\)) and the standard deviations (\(\sigma\)) of the two assets: \[Cov(o, abc) = \rho \times \sigma_o \times \sigma_{abc}\] \[Cov(o, abc) = 0.40 \times 0.0237 \times 0.0295 = 0.00027966\]

  3. Standard Deviation of the New Portfolio:Using the two-asset portfolio variance formula: \[\sigma_p = \sqrt{w_o^2\sigma_o^2 + w_{abc}^2\sigma_{abc}^2 + 2w_ow_{abc}Cov(o, abc)}\] \[\sigma_p = \sqrt{(0.90^2 \times 2.37^2) + (0.10^2 \times 2.95^2) + (2 \times 0.90 \times 0.10 \times 2.7966)}\] \[\sigma_p = \sqrt{4.5497 + 0.0870 + 0.5034} = \sqrt{5.1401} = 2.267\%\]

Question B

The weights remain the same (90% original, 10% government securities). Risk-free assets have a standard deviation of 0%.

  1. Expected Return of the New Portfolio: \[E(R_p) = (0.90 \times 0.67\%) + (0.10 \times 0.42\%) = 0.603\% + 0.042\% = 0.645\%\]

  2. Covariance of Government Security Returns with Original Portfolio: The covariance is 0. By definition, a risk-free asset has no volatility (variance = 0). Since it doesn’t move at all, it cannot move in tandem with another asset. Therefore, its correlation and covariance with any risky asset are mathematically zero.

  3. Standard Deviation of the New Portfolio: Because the standard deviation and covariance of the risk-free asset are zero, the portfolio variance formula simplifies dramatically: \[\sigma_p = \sqrt{w_o^2\sigma_o^2 + 0 + 0} = w_o \times \sigma_o\] \[\sigma_p = 0.90 \times 2.37\% = 2.133\%\]

Question C

The systematic risk of the new portfolio (with government securities) will be lower than that of her original portfolio. Systematic risk is measured by Beta. The original portfolio has a Beta of \(1.0\) relative to itself. A risk-free asset has a Beta of \(0\). By shifting 10% of her wealth into an asset with zero systematic risk, the overall systematic risk of her portfolio decreases to 90% of what it previously was.

Question D

Her husband’s comment is incorrect.

Even if XYZ stock has the exact same expected return and standard deviation as ABC stock, he is completely ignoring the correlation of XYZ stock with the original portfolio. If XYZ stock has a lower correlation with the original portfolio than ABC stock does (less than 0.40), it will provide better diversification benefits, resulting in a lower overall portfolio risk (standard deviation) without sacrificing any return.

Question E

  1. Weakness of using Standard Deviation: Standard deviation is a symmetrical risk measure—it measures the dispersion of returns both above and below the mean. For an investor like Grace, who states she just doesn’t want to lose money, standard deviation is flawed because it penalizes unexpected massive gains (upside volatility) exactly the same way it penalizes massive losses (downside volatility).

  2. Alternate Risk Measure: A more appropriate measure would be Semi-variance (or Downside Deviation), which only measures the volatility of returns below a specific target (in her case, below 0%). Alternatively, Value at Risk (VaR) or Expected Shortfall (Conditional VaR) would be excellent choices, as they specifically quantify the maximum expected loss over a given timeframe at a certain confidence level.

Chapter 8: Problem Set 17

A portfolio manager summarizes the input from the macro and micro forecasters in the following table:

Micro Forecasts

Asset Expected Return (%) Beta Residual Standard Deviation (%)
Stock A 20% 1.3 58%
Stock B 18% 1.8 71%
Stock C 17% 0.7 60%
Stock D 12% 1.0 55%

Macro Forecasts

Asset Expected Return (%) Standard Deviation (%)
T-bills 8% 0%
Passive equity portfolio 16% 23%
  1. Calculate expected excess returns, alpha values, and residual variances for these stocks.
  2. Construct the optimal risky portfolio.
  3. What is the Sharpe ratio for the optimal portfolio?
  4. By how much did the position in the active portfolio improve the Sharpe ratio compared to a purely passive index strategy?
  5. What should be the exact makeup of the complete portfolio (including the risk-free asset) for an investor with a coefficient of risk aversion of 2.8?

Answers

# --- Given Macro Data ---
rf <- 0.08
er_m <- 0.16
sd_m <- 0.23
var_m <- sd_m^2
rm_excess <- er_m - rf
A <- 2.8

# --- Given Micro Data ---
stocks <- c("Stock A", "Stock B", "Stock C", "Stock D")
er_i <- c(0.20, 0.18, 0.17, 0.12)
beta_i <- c(1.3, 1.8, 0.7, 1.0)
sd_e_i <- c(0.58, 0.71, 0.60, 0.55)

# ---------------------------------------------------------
# Part A: Excess Returns, Alphas, and Residual Variances
# ---------------------------------------------------------
r_i_excess <- er_i - rf
alpha_i <- r_i_excess - (beta_i * rm_excess)
var_e_i <- sd_e_i^2

part_a_results <- data.frame(
  Stock = stocks,
  Excess_Return = r_i_excess,
  Alpha = alpha_i,
  Residual_Var = var_e_i
)

cat("--- Part A: Stock Metrics ---\n")
## --- Part A: Stock Metrics ---
print(part_a_results, digits = 4)
##     Stock Excess_Return  Alpha Residual_Var
## 1 Stock A          0.12  0.016       0.3364
## 2 Stock B          0.10 -0.044       0.5041
## 3 Stock C          0.09  0.034       0.3600
## 4 Stock D          0.04 -0.040       0.3025
cat("\n")
# ---------------------------------------------------------
# Part B: Construct Optimal Risky Portfolio
# ---------------------------------------------------------
active_ratios <- alpha_i / var_e_i
w_active_initial <- active_ratios / sum(active_ratios)

alpha_A <- sum(w_active_initial * alpha_i)
beta_A <- sum(w_active_initial * beta_i)
var_e_A <- sum((w_active_initial^2) * var_e_i)

w0 <- (alpha_A / var_e_A) / (rm_excess / var_m)
wA_star <- w0 / (1 + (1 - beta_A) * w0)
wM_star <- 1 - wA_star

final_stock_weights <- wA_star * w_active_initial

cat("--- Part B: Optimal Risky Portfolio Weights ---\n")
## --- Part B: Optimal Risky Portfolio Weights ---
cat("Passive Market Index:", round(wM_star * 100, 2), "%\n")
## Passive Market Index: 104.86 %
cat("Active Portfolio Total:", round(wA_star * 100, 2), "%\n")
## Active Portfolio Total: -4.86 %
for(i in 1:4){
  cat("  ->", stocks[i], ":", round(final_stock_weights[i] * 100, 2), "%\n")
}
##   -> Stock A : 2.98 %
##   -> Stock B : -5.47 %
##   -> Stock C : 5.92 %
##   -> Stock D : -8.28 %
cat("\n")
# ---------------------------------------------------------
# Part C & D: Sharpe Ratios
# ---------------------------------------------------------
sr_m <- rm_excess / sd_m
ir_sq <- sum((alpha_i / sd_e_i)^2)
sr_p <- sqrt(sr_m^2 + ir_sq)

cat("--- Part C & D: Sharpe Ratios ---\n")
## --- Part C & D: Sharpe Ratios ---
cat("Market Sharpe Ratio:", round(sr_m, 4), "\n")
## Market Sharpe Ratio: 0.3478
cat("Optimal Portfolio Sharpe Ratio (Part C):", round(sr_p, 4), "\n")
## Optimal Portfolio Sharpe Ratio (Part C): 0.3662
cat("Sharpe Ratio Improvement (Part D):", round(sr_p - sr_m, 4), "\n\n")
## Sharpe Ratio Improvement (Part D): 0.0183
# ---------------------------------------------------------
# Part E: Complete Portfolio Allocation (A = 2.8)
# ---------------------------------------------------------
er_p_excess <- (wM_star * rm_excess) + (wA_star * (alpha_A + beta_A * rm_excess))
beta_p <- (wM_star * 1) + (wA_star * beta_A)
var_p <- (beta_p^2 * var_m) + ((wA_star^2) * var_e_A)

y <- er_p_excess / (A * var_p)
weight_rf <- 1 - y

cat("--- Part E: Complete Portfolio Allocation (A = 2.8) ---\n")
## --- Part E: Complete Portfolio Allocation (A = 2.8) ---
cat("Risk-Free Asset (T-bills):", round(weight_rf * 100, 2), "%\n")
## Risk-Free Asset (T-bills): 42.99 %
cat("Optimal Risky Portfolio:", round(y * 100, 2), "%\n")
## Optimal Risky Portfolio: 57.01 %
cat("  -> Passive Market Index:", round(y * wM_star * 100, 2), "%\n")
##   -> Passive Market Index: 59.77 %
for(i in 1:4){
  cat("  ->", stocks[i], ":", round(y * final_stock_weights[i] * 100, 2), "%\n")
}
##   -> Stock A : 1.7 %
##   -> Stock B : -3.12 %
##   -> Stock C : 3.37 %
##   -> Stock D : -4.72 %

Chapter 8: CFA Problem 1

When the annualized monthly percentage excess rates of return for a stock market index were regressed against the excess returns for ABC and XYZ stocks over the most recent 5-year period, using an ordinary least squares regression, the following results were obtained:

Statistic ABC XYZ
Alpha −3.20% 7.30%
Beta 0.60 0.97
0.35 0.17
Residual Standard Deviation 13.02% 21.45%

Explain what these regression results tell the analyst about risk–return relationships for each stock over the sample period. Comment on their implications for future risk–return relationships, assuming both stocks were included in a diversified common stock portfolio, especially in view of the following additional data obtained from two brokerage houses, which are based on the most recent two years of weekly returns.

Brokerage House Beta of ABC Beta of XYZ
A 0.62 1.45
B 0.71 1.25

Answer

Historical Risk-Return (5-Year Regression)

  • Stock ABC: Underperformed the market (Alpha = -3.20%) but was defensive, moving less than the broader market (Beta = 0.60). It had low firm-specific risk.
  • Stock XYZ: Significantly outperformed expectations (Alpha = 7.30%) but had very high firm-specific risk (Residual Std Dev = 21.45%, low R²). Its historical systematic risk matched the market (Beta = 0.97).

Implications for a Diversified Portfolio

  • In a fully diversified portfolio, firm-specific (unsystematic) risk is completely diversified away.
  • Therefore, Residual Standard Deviation and R² become irrelevant.
  • Beta becomes the only meaningful measure of risk that these stocks contribute to the overall portfolio. (Also, historical alphas rarely persist, so the 7.30% alpha shouldn’t be counted on).

Impact of New Brokerage Data

  • ABC is Stable: The recent broker estimates (0.62 and 0.71) are close to the 5-year beta (0.60). ABC’s risk profile is stable over time.
  • XYZ is Riskier Now: The recent broker estimates (1.25 and 1.45) are significantly higher than the 5-year beta (0.97).
  • Conclusion: Beta changes over time. The analyst must not rely on XYZ’s 5-year historical beta. The company has clearly taken on more systematic risk recently, so the newer, higher beta estimates should be used for future forecasting.