Consider a portfolio consisting of 2 stocks, stock 1 and stock 2. The weights on each stock, \(w_1\) and \(w_2\), are the percentages invested in each.
\(w_1\): Portfolio weight on stock
1
\(w_2\): Portfolio weight on stock 2,
where
\(w_1 + w_2=1\).
The following variables describe the characteristics of the 2 stocks:
\(r_1\): Expected return on stock
1
\(r_2\): Expected return on stock 2
\(\sigma_1\): Standard deviation of
return for stock 1
\(\sigma_2\): Standard deviation of
return for stock 2
\(corr_{12}\): Correlation of returns between stock 1 and stock 2
Given these variables, the following 2 rules describe the expected return, variance, and standard deviation of the combined portfolio:
\[E(r_p)=w_1r_1+w_2r_2\]
\[Variance_p=(w_1\sigma_1)^2+(w_2\sigma_2)^2+2w_1w_2\sigma_1\sigma_2corr_{12}\] \[\sigma_p=\sqrt{Variance_p}\]
In this question, I am asking you to create functions for portfolio expected returns and standard deviation. Please fill in the Python code in the notebook cells below.
A. Use the tidyverse library
library(tidyverse)
── Attaching core tidyverse packages ── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.2 ✔ tibble 3.2.1
✔ lubridate 1.9.4 ✔ tidyr 1.3.1
✔ purrr 1.0.4
── Conflicts ──────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(ggplot2)
B. Create a function to calculate the expected return on the portfolio given 3 inputs: w1, r1, and r2. You will need to calculate w2 in the function itself.
portfolio_return <- function(w1, r1, r2) { w2 <- 1 - w1 return(w1 * r1 + w2 * r2) }
C. Create a functions to calculate the standard deviation of a portfolio given 4 inputs: w1, s1, s2, and corr12. You will need to calculate w2 in the function itself.
portfolio_sd <- function(w1, s1, s2, corr12) { w2 <- 1 - w1 variance <- (w1s1)^2 + (w2s2)^2 + 2w1w2s1s2*corr12 return(sqrt(variance)) }
D. For a test case, use the constants defined in the cell below. You will need to make sure you run the cell so the variables will be set in memory.
ret_apple=0.20
ret_walmart=0.10
sd_apple=0.25
sd_walmart=0.20
corr_aw=0.25
<!-- rnb-source-end -->
<!-- rnb-output-end -->
<!-- rnb-output-begin eyJkYXRhIjoiRXJyb3I6IGF0dGVtcHQgdG8gdXNlIHplcm8tbGVuZ3RoIHZhcmlhYmxlIG5hbWVcbiJ9 -->
Error: attempt to use zero-length variable name ```
E. Using the functions you created and the constants above, calculate and print the expected return and standard deviation of a portfolio with a 0.5 weight in apple and a 0.5 weight in walmart.
w_test <- 0.5 test_return <- portfolio_return(w_test, ret_apple, ret_walmart) test_sd <- portfolio_sd(w_test, sd_apple, sd_walmart, corr_aw)
cat(“50/50 Portfolio:”) cat(“Expected Return:”, test_return, “”) cat(“Standard Deviation:”, test_sd, “”)
F.Using seq(), create a range of weights on apple (stock 1) ranging from 0 to 1 in increments of 0.01.
weights <- seq(0, 1, by = 0.01)
G. Create two arrays, one with the portfolio standard deviations corresponding to the different weights, the other giving the portfolio expected returns based on the different weights.
returns <- sapply(weights, portfolio_return, r1 = ret_apple, r2 = ret_walmart) sds <- sapply(weights, portfolio_sd, s1 = sd_apple, s2 = sd_walmart, corr12 = corr_aw)
H. Create a plot with portfolio standard deviation on the x-axis and portfolio expected return on the y-axis.
plot_data <- data.frame(SD = sds, Return = returns) ggplot(plot_data, aes(x = SD, y = Return)) + geom_line(color = “blue”) + geom_point(data = plot_data[which.min(sds), ], color = “red”, size = 3) + labs(title = “Efficient Frontier”, x = “Portfolio Standard Deviation”, y = “Portfolio Expected Return”) + theme_minimal()
I. What is the minimum standard deviation of all the points you plotted on the curve?
min_sd <- min(sds) cat(“Minimum Standard Deviation:”, min_sd, “”)
#Minimum Standard Deviation = 0.1739
J. What are the weights corresponding to the portfolio with the minimum standard deviation?
min_sd_index <- which.min(sds) min_sd_weights <- c(weights[min_sd_index], 1 - weights[min_sd_index]) cat(“Optimal Weights (Apple, Walmart):”, min_sd_weights)
#Weights corresponding to the portfolio with the minimum standard deviation? # Apple = 0.35, Walmart = 0.65