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 conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
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.
# function to calculate expected portfolio return
expected_return <- function(w1, r1, r2) {
# Calculate w2 as 1 - w1
w2 <- 1 - w1
# Calculate the expected return of the portfolio using Portfolio Rule 1
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.
# Function to calculate portfolio standard deviation
portfolio_sd <- function(w1, sigma1, sigma2, corr12) {
# Calculate w2 as 1 - w1
w2 <- 1 - w1
# Calculate the portfolio variance using the given formula
variance_p <- (w1 * sigma1)^2 + (w2 * sigma2)^2 + 2 * w1 * w2 * sigma1 * sigma2 * corr12
# Calculate the portfolio standard deviation (square root of variance)
sigma_p <- sqrt(variance_p)
return(sigma_p)
}
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.
# Definition of Constants
ret_apple=0.20
ret_walmart=0.10
sd_apple=0.25
sd_walmart=0.20
corr_aw=0.25
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.
# Define portfolio weight for Apple
w1 <- 0.5 # 50% invested in Apple
# Calculate the expected return of the portfolio
portfolio_return <- expected_return(w1, ret_apple, ret_walmart)
# Calculate the portfolio standard deviation
portfolio_sd_value <- portfolio_sd(w1, sd_apple, sd_walmart, corr_aw)
# Print the results
cat("Expected Return of the Portfolio:", portfolio_return, "\n")
## Expected Return of the Portfolio: 0.15
cat("Standard Deviation of the Portfolio:", portfolio_sd_value, "\n")
## Standard Deviation of the Portfolio: 0.1785357
F.Using seq(), create a range of weights on apple (stock 1) ranging from 0 to 1 in increments of 0.01.
# Create a sequence of weights for Apple from 0 to 1 in increments of 0.01
weights_apple <- seq(0, 1, by = 0.01)
# Print the sequence of weights
weights_apple
## [1] 0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14
## [16] 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29
## [31] 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41 0.42 0.43 0.44
## [46] 0.45 0.46 0.47 0.48 0.49 0.50 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59
## [61] 0.60 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.70 0.71 0.72 0.73 0.74
## [76] 0.75 0.76 0.77 0.78 0.79 0.80 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89
## [91] 0.90 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.00
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.
# Create a sequence of weights for Apple from 0 to 1 in increments of 0.01
weights_apple <- seq(0, 1, by = 0.01)
# Initialize empty arrays to store portfolio standard deviations and expected returns
portfolio_returns <- numeric(length(weights_apple))
portfolio_sds <- numeric(length(weights_apple))
# Loop through each weight and calculate the expected return and standard deviation
for (i in 1:length(weights_apple)) {
# Get the current weight for Apple
w1 <- weights_apple[i]
# Calculate the expected return of the portfolio
portfolio_returns[i] <- expected_return(w1, ret_apple, ret_walmart)
# Calculate the portfolio standard deviation
portfolio_sds[i] <- portfolio_sd(w1, sd_apple, sd_walmart, corr_aw)
}
# Print the portfolio returns and standard deviations
portfolio_returns
## [1] 0.100 0.101 0.102 0.103 0.104 0.105 0.106 0.107 0.108 0.109 0.110 0.111
## [13] 0.112 0.113 0.114 0.115 0.116 0.117 0.118 0.119 0.120 0.121 0.122 0.123
## [25] 0.124 0.125 0.126 0.127 0.128 0.129 0.130 0.131 0.132 0.133 0.134 0.135
## [37] 0.136 0.137 0.138 0.139 0.140 0.141 0.142 0.143 0.144 0.145 0.146 0.147
## [49] 0.148 0.149 0.150 0.151 0.152 0.153 0.154 0.155 0.156 0.157 0.158 0.159
## [61] 0.160 0.161 0.162 0.163 0.164 0.165 0.166 0.167 0.168 0.169 0.170 0.171
## [73] 0.172 0.173 0.174 0.175 0.176 0.177 0.178 0.179 0.180 0.181 0.182 0.183
## [85] 0.184 0.185 0.186 0.187 0.188 0.189 0.190 0.191 0.192 0.193 0.194 0.195
## [97] 0.196 0.197 0.198 0.199 0.200
portfolio_sds
## [1] 0.2000000 0.1986397 0.1973094 0.1960096 0.1947409 0.1935039 0.1922992
## [8] 0.1911276 0.1899895 0.1888855 0.1878164 0.1867826 0.1857848 0.1848236
## [15] 0.1838994 0.1830130 0.1821648 0.1813553 0.1805852 0.1798548 0.1791647
## [22] 0.1785154 0.1779073 0.1773408 0.1768163 0.1763342 0.1758949 0.1754986
## [29] 0.1751457 0.1748364 0.1745709 0.1743495 0.1741723 0.1740395 0.1739511
## [36] 0.1739073 0.1739080 0.1739533 0.1740431 0.1741774 0.1743560 0.1745788
## [43] 0.1748456 0.1751564 0.1755107 0.1759084 0.1763491 0.1768325 0.1773584
## [50] 0.1779262 0.1785357 0.1791864 0.1798777 0.1806094 0.1813808 0.1821915
## [57] 0.1830410 0.1839287 0.1848540 0.1858164 0.1868154 0.1878503 0.1889206
## [64] 0.1900257 0.1911649 0.1923376 0.1935433 0.1947813 0.1960510 0.1973518
## [71] 0.1986832 0.2000444 0.2014349 0.2028540 0.2043012 0.2057760 0.2072776
## [78] 0.2088055 0.2103592 0.2119381 0.2135416 0.2151691 0.2168202 0.2184943
## [85] 0.2201908 0.2219093 0.2236493 0.2254102 0.2271915 0.2289929 0.2308138
## [92] 0.2326537 0.2345123 0.2363890 0.2382834 0.2401952 0.2421239 0.2440692
## [99] 0.2460305 0.2480076 0.2500000
# Plot portfolio returns vs. portfolio standard deviations
plot(portfolio_sds, portfolio_returns, type = "l", col = "blue",
xlab = "Portfolio Standard Deviation", ylab = "Portfolio Expected Return",
main = "Portfolio Efficient Frontier")
H. Create a plot with portfolio standard deviation on the x-axis and portfolio expected return on the y-axis.
# Plot portfolio returns vs. portfolio standard deviations
plot(portfolio_sds, portfolio_returns, type = "l", col = "blue",
xlab = "Portfolio Standard Deviation", ylab = "Portfolio Expected Return",
main = "Portfolio Efficient Frontier")
I. What is the minimum standard deviation of all the points you plotted on the curve?
# Find the minimum standard deviation
min_sd <- min(portfolio_sds)
# Find the index of the minimum standard deviation
min_sd_index <- which.min(portfolio_sds)
# Get the corresponding weight for this minimum standard deviation
min_sd_weight <- weights_apple[min_sd_index]
# Print the results
cat("Minimum Standard Deviation:", min_sd, "\n")
## Minimum Standard Deviation: 0.1739073
cat("Weight on Apple for Minimum Standard Deviation:", min_sd_weight, "\n")
## Weight on Apple for Minimum Standard Deviation: 0.35
J. What are the weights corresponding to the portfolio with the minimum standard deviation?
# Find the index of the minimum standard deviation
min_sd_index <- which.min(portfolio_sds)
# Get the weight on Apple corresponding to the minimum standard deviation
min_sd_weight_apple <- weights_apple[min_sd_index]
# Calculate the weight on Walmart
min_sd_weight_walmart <- 1 - min_sd_weight_apple
# Print the results
cat("Weight on Apple for Minimum Standard Deviation:", min_sd_weight_apple, "\n")
## Weight on Apple for Minimum Standard Deviation: 0.35
cat("Weight on Walmart for Minimum Standard Deviation:", min_sd_weight_walmart, "\n")
## Weight on Walmart for Minimum Standard Deviation: 0.65