1 Problem 10: Portfolio Return and Variance

1.1 Given Parameters

rf    <- 0.05   # Risk-free rate (T-bill)
rm    <- 0.13   # Expected return on S&P 500 (5% + 8% excess)
sig_m <- 0.20   # Standard deviation of S&P 500

1.2 Calculations

For a portfolio with weight \(w_m\) in the S&P 500 and \(w_f = 1 - w_m\) in T-bills:

\[E(r_p) = w_f \cdot r_f + w_m \cdot r_m \qquad \sigma_p^2 = (w_m \cdot \sigma_m)^2\]

weights <- c(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)

E_rp  <- (1 - weights) * rf + weights * rm
Var_p <- (weights * sig_m)^2
Sig_p <- sqrt(Var_p)

p10 <- data.frame(
  `Weight in S&P 500` = weights,
  `Expected Return`   = paste0(round(E_rp * 100, 1), "%"),
  `Variance`          = round(Var_p, 4),
  `Std Deviation`     = paste0(round(Sig_p * 100, 1), "%"),
  check.names = FALSE
)
kable(p10, align = "c", caption = "Table 1: Portfolio Return and Risk")
Table 1: Portfolio Return and Risk
Weight in S&P 500 Expected Return Variance Std Deviation
0.0 5% 0.0000 0%
0.2 6.6% 0.0016 4%
0.4 8.2% 0.0064 8%
0.6 9.8% 0.0144 12%
0.8 11.4% 0.0256 16%
1.0 13% 0.0400 20%

1.3 Capital Allocation Line (CAL)

w_seq   <- seq(0, 1, by = 0.01)
er_seq  <- (1 - w_seq) * rf + w_seq * rm
sig_seq <- w_seq * sig_m

ggplot(data.frame(sigma = sig_seq, er = er_seq), aes(x = sigma, y = er)) +
  geom_line(color = "#2c7bb6", linewidth = 1.2) +
  geom_point(data = data.frame(sigma = Sig_p, er = E_rp),
             color = "red", size = 3) +
  geom_text(data = data.frame(sigma = Sig_p, er = E_rp,
                               label = paste0("w=", weights)),
            aes(label = label), vjust = -0.9, size = 3.2) +
  scale_x_continuous(labels = scales::percent_format()) +
  scale_y_continuous(labels = scales::percent_format()) +
  labs(title = "Capital Allocation Line (CAL)",
       x = "Portfolio Standard Deviation (σ)",
       y = "Expected Return E(r)") +
  theme_minimal(base_size = 13)


2 Problem 11: Optimal Portfolio — A = 2

2.1 Utility Formula

\[U = E(r_p) - A \cdot \sigma_p^2\]

A2 <- 2
U2 <- E_rp - A2 * Var_p

p11 <- data.frame(
  `Weight in S&P 500` = weights,
  `E(r)`              = round(E_rp, 4),
  `Variance`          = round(Var_p, 4),
  `Utility (A=2)`     = round(U2, 4),
  check.names = FALSE
)
kable(p11, align = "c", caption = "Table 2: Utility Scores with A = 2")
Table 2: Utility Scores with A = 2
Weight in S&P 500 E(r) Variance Utility (A=2)
0.0 0.050 0.0000 0.0500
0.2 0.066 0.0016 0.0628
0.4 0.082 0.0064 0.0692
0.6 0.098 0.0144 0.0692
0.8 0.114 0.0256 0.0628
1.0 0.130 0.0400 0.0500
best11 <- weights[which.max(U2)]
cat("Best Weight in S&P 500:", best11, " | Max Utility:", round(max(U2), 4))
## Best Weight in S&P 500: 0.6  | Max Utility: 0.0692

2.2 Analytical Optimal Weight

\[w^* = \frac{E(r_m) - r_f}{A \cdot \sigma_m^2}\]

w_star_A2 <- (rm - rf) / (A2 * sig_m^2)
cat("Analytical w* (A=2):", round(w_star_A2, 4), "=", round(w_star_A2*100, 1), "%")
## Analytical w* (A=2): 1 = 100 %

2.3 Utility Plot (A = 2)

ggplot(data.frame(w = weights, U = U2), aes(x = w, y = U)) +
  geom_line(color = "#1a9641", linewidth = 1.2) +
  geom_point(size = 3, color = "#1a9641") +
  geom_point(data = data.frame(w = best11, U = max(U2)),
             color = "red", size = 5, shape = 18) +
  scale_x_continuous(labels = scales::percent_format()) +
  labs(title = "Utility Function: A = 2",
       subtitle = "Red diamond = maximum utility",
       x = "Weight in S&P 500", y = "Utility") +
  theme_minimal(base_size = 13)

Conclusion: With A = 2, the analytical optimum is 100% in S&P 500.
Moderate risk aversion leads to a balanced allocation.


3 Problem 12: Optimal Portfolio — A = 3

A3 <- 3
U3 <- E_rp - A3 * Var_p

p12 <- data.frame(
  `Weight in S&P 500` = weights,
  `E(r)`              = round(E_rp, 4),
  `Variance`          = round(Var_p, 4),
  `Utility (A=3)`     = round(U3, 4),
  check.names = FALSE
)
kable(p12, align = "c", caption = "Table 3: Utility Scores with A = 3")
Table 3: Utility Scores with A = 3
Weight in S&P 500 E(r) Variance Utility (A=3)
0.0 0.050 0.0000 0.0500
0.2 0.066 0.0016 0.0612
0.4 0.082 0.0064 0.0628
0.6 0.098 0.0144 0.0548
0.8 0.114 0.0256 0.0372
1.0 0.130 0.0400 0.0100
w_star_A3 <- (rm - rf) / (A3 * sig_m^2)
cat("Analytical w* (A=3):", round(w_star_A3, 4), "=", round(w_star_A3*100, 1), "%")
## Analytical w* (A=3): 0.6667 = 66.7 %

3.1 Comparison: A = 2 vs A = 3

df_compare <- data.frame(
  w = rep(weights, 2),
  U = c(U2, U3),
  A = rep(c("A = 2", "A = 3"), each = length(weights))
)

ggplot(df_compare, aes(x = w, y = U, color = A)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  scale_x_continuous(labels = scales::percent_format()) +
  scale_color_manual(values = c("A = 2" = "#1a9641", "A = 3" = "#d7191c")) +
  labs(title = "Utility Comparison: A = 2 vs A = 3",
       x = "Weight in S&P 500", y = "Utility", color = "Risk Aversion") +
  theme_minimal(base_size = 13)

Conclusion: Higher risk aversion (A = 3) shifts the optimal portfolio to 66.7% in S&P 500,
compared to 100% for A = 2. More risk-averse investors hold more T-bills.


4 CFA Problem 1: Best Investment (A = 4)

\[U = E(r) - 4\sigma^2\]

A_cfa <- 4

cfa1 <- data.frame(
  Investment = 1:4,
  `E(r)`     = c(0.12, 0.15, 0.21, 0.24),
  Variance   = c(0.0225, 0.1225, 0.0400, 0.0625),
  check.names = FALSE
)
cfa1 <- cfa1 %>%
  mutate(`Utility (A=4)` = round(`E(r)` - A_cfa * Variance, 4))

kable(cfa1, align = "c", caption = "Table 4: CFA Problem 1 — Investment Utilities")
Table 4: CFA Problem 1 — Investment Utilities
Investment E(r) Variance Utility (A=4)
1 0.12 0.0225 0.03
2 0.15 0.1225 -0.34
3 0.21 0.0400 0.05
4 0.24 0.0625 -0.01
best_cfa1 <- cfa1$Investment[which.max(cfa1$`Utility (A=4)`)]
cat("Best Investment: #", best_cfa1, "| Utility =", max(cfa1$`Utility (A=4)`))
## Best Investment: # 3 | Utility = 0.05

Answer: Investment 3 yields the highest utility of 0.05.


5 CFA Problem 2: Risk-Neutral Investor

A risk-neutral investor has A = 0, so \(U = E(r)\). They simply maximise expected return.

returns_cfa2 <- c(0.12, 0.15, 0.21, 0.24)
best_cfa2    <- which.max(returns_cfa2)

df_cfa2 <- data.frame(Investment = 1:4,
                       `E(r)` = paste0(returns_cfa2*100, "%"),
                       check.names = FALSE)
kable(df_cfa2, align = "c", caption = "Table 5: CFA Problem 2 — Returns")
Table 5: CFA Problem 2 — Returns
Investment E(r)
1 12%
2 15%
3 21%
4 24%
cat("Best Investment: #", best_cfa2, "| Return =", returns_cfa2[best_cfa2]*100, "%")
## Best Investment: # 4 | Return = 24 %

Answer: Investment 4 — the highest expected return, with no variance penalty.


6 CFA Problem 3: Meaning of Parameter A

The mean-variance utility function is:

\[U = E(r_p) - \frac{1}{2} A \sigma_p^2\]

Value of A Interpretation
A > 0 Risk-averse (prefers less risk)
A = 0 Risk-neutral (ignores variance)
A < 0 Risk-seeking (prefers more risk)

Answer: (b) Investor’s degree of risk aversion.
A larger A means the investor penalises variance more heavily and will accept a lower expected
return in exchange for a reduction in portfolio risk.


7 Summary of All Answers

summary_df <- data.frame(
  Problem  = c("10", "11 (A=2)", "12 (A=3)", "CFA 1 (A=4)", "CFA 2", "CFA 3"),
  Answer   = c(
    "See CAL table & plot above",
    paste0("w* = ", round(w_star_A2*100,1), "% in S&P 500"),
    paste0("w* = ", round(w_star_A3*100,1), "% in S&P 500"),
    paste0("Investment ", best_cfa1, " (U = ", max(cfa1[["Utility (A=4)"]]), ")"),
    paste0("Investment ", best_cfa2, " (highest return = 24%)"),
    "b. Investor's degree of risk aversion"
  )
)
kable(summary_df, align = "l", caption = "Final Summary")
Final Summary
Problem Answer
10 See CAL table & plot above
11 (A=2) w* = 100% in S&P 500
12 (A=3) w* = 66.7% in S&P 500
CFA 1 (A=4) Investment 3 (U = 0.05)
CFA 2 Investment 4 (highest return = 24%)
CFA 3 b. Investor’s degree of risk aversion