These study notes are based on Chapter 6 the Exam 9 syllabus reading Investments by Bodie, Kane, and Marcus. This chapter illustrates how to determine the optimal allocation between risk-free and risky assets, given an investor’s level of risk tolerance. This chapter corresponds to learning objective A1 on the syllabus.
The reading considers a complete portfolio that consists of two investments:
A risky portfolio \(P\) that has an expected rate of return of \(r_P\) with a standard deviation of \(\sigma_P\). This asset constitutes a fraction \(y\) of the complete portfolio. The risky portfolio is typically a mixture of various risky assets, and future readings address the topic of its composition.
A risk-free asset \(F\) that has a certain rate of return of \(r_f\). This asset constitutes \(1-y\) of the complete portfolio. The typical risk-free asset is a T-bill, or more generally, a money market fund.
The rate of return of the complete portfolio is \[ r_C = y r_P + (1-y)r_f = r_f + y(r_P - r_f) \] Note that the second expression for \(r_C\) expresses \(r_C\) as having a risk premium that is some fraction, \(y\) of the risk premium of \(P\). The standard deviation of the complete portfolio is \[ \sigma_C = y \sigma_P \]
easypackages::packages("dplyr", "ggplot2")
The approach assumes that investors assign a utility score to various portfolios, and select the portfolio with the highest score. This is also called a certainty equivalent rate of return. An example of a utility function is \[ U = E(r) - \frac12 A \sigma^2, \] where \(A\) is a parameter reflecting the investor’s risk appetite:
When \(A > 0\), the investor is risk averse. These investors reject portfolios that are fair games or worse. Higher values indicate greater levels of risk aversion. These investors will not accept investments with an expected rate of return less than or equal to the risk free rate — they expect a risk premium in exchange for assuming the risk. These investors are engaging in speculation.
When \(A = 0\), the investor is risk-neutral. These investors make decisions entirely based on the expected rate of return.
When \(A < 0\), the investor is a risk lover. This corresponds to gambling, since the utility is adjusted upward to account for the fun associated with the uncertainty. These investors will accept investments without a risk premium.
The parameter \(A\) is a subjective view on the part of the investor. Ways of determining an appropriate value for \(A\) include:
Using a survey of risk attitudes; questions are scored and the total score is translated into a value for \(A\)
Calculating the value of \(A\) implied by previous investment decisions that have been made by the investor.
The following example illustrates how different investors would make decisions depending on their level of risk aversion:
bkm.utility.example = read.csv("./Data/BKM_6.csv")
## Warning in read.table(file = file, header = header, sep = sep, quote
## = quote, : incomplete final line found by readTableHeader on './Data/
## BKM_6.csv'
bkm.utility.example
## portfolio risk_premium standard_deviation
## 1 L 0.02 0.05
## 2 M 0.04 0.10
## 3 H 0.08 0.20
First, calcutate the expected return by adding the risk-free rate, assumed to be 5% in this example.
risk.free.rate = 0.05
bkm.utility.example = bkm.utility.example %>% mutate(expected_return = risk_premium + risk.free.rate)
bkm.utility.example
## portfolio risk_premium standard_deviation expected_return
## 1 L 0.02 0.05 0.07
## 2 M 0.04 0.10 0.09
## 3 H 0.08 0.20 0.13
Next, calculate utility for three different values of \(A\):
A.values = c(2, 3.5, 5)
A.df = data.frame(A_value = A.values)
bkm.utility.comparison = merge(bkm.utility.example, A.df)
bkm.utility.comparison = bkm.utility.comparison %>% mutate(utility = expected_return - 0.5 * A_value * standard_deviation^2)
bkm.utility.comparison
## portfolio risk_premium standard_deviation expected_return A_value
## 1 L 0.02 0.05 0.07 2.0
## 2 M 0.04 0.10 0.09 2.0
## 3 H 0.08 0.20 0.13 2.0
## 4 L 0.02 0.05 0.07 3.5
## 5 M 0.04 0.10 0.09 3.5
## 6 H 0.08 0.20 0.13 3.5
## 7 L 0.02 0.05 0.07 5.0
## 8 M 0.04 0.10 0.09 5.0
## 9 H 0.08 0.20 0.13 5.0
## utility
## 1 0.067500
## 2 0.080000
## 3 0.090000
## 4 0.065625
## 5 0.072500
## 6 0.060000
## 7 0.063750
## 8 0.065000
## 9 0.030000
The investor with \(A = 2\) would select portfolio \(H\), while the other two investors would both select portfolio \(M\).
Portfolios can be compared graphically by plotting them such that standard deviation is on the \(y\)-axis, and expected return is on the \(x\)-axis:
ggplot(data = bkm.utility.example, aes(x = standard_deviation, y = expected_return, col = portfolio)) + geom_point(size = 4)
The mean-variance criterion states that, for a risk adverse investor, portfolio \(A\) is preferred to portfolio \(B\) if portfolio \(A\) has both a higher expected return and a lower standard deviation. (Only one of the inequalities needs to be strict.) Geometrically, this corresponds to portfolio \(A\) appearing northwest of portfolio \(B\). When this occurs, portfolio \(A\) is unambiguously preferred to portfolio \(B\). None of the portfolios in this example dominates another, so the utility function must be used to distinguish them.
For a given investor, the indifference curve for a given certainty-equivalent rate corresponds to all portfolios that have the same certainty-equivalent rate. It can be plotted, as above, by expressing the expected return as a function of standard deviation: \[ E(r) = U + \frac12 A\sigma^2 \] The following calculates indifference curves for each of the three investors at a utility value of 0.09 and 0.06:
indifference.curve = function(A, sd, U) {
return(U + 0.5 * A * sd^2)
}
indifference.curve.data = merge(A.df, data.frame(sd = 0:25 / 100))
indifference.curve.data$utility_09 = apply(indifference.curve.data, 1, function(y){ indifference.curve(A = y['A_value'], sd = y['sd'], U = 0.09)})
indifference.curve.data$utility_06 = apply(indifference.curve.data, 1, function(y){ indifference.curve(A = y['A_value'], sd = y['sd'], U = 0.06)})
Plot the curves along with the three portfolios:
ggplot(data = indifference.curve.data, aes(x = sd, y = utility_09, col = as.factor(A_value))) + geom_line() + geom_line(aes(y = utility_06)) + expand_limits(y = 0) + geom_point(data = bkm.utility.example, aes(x = standard_deviation, y = expected_return, col = portfolio), size = 4) + labs(x = "Standard Deviation", y = "Expected Return")
The lower three curves correspond to a certainty-equivalent rate of 6%, while the upper 3 curves correspond to a certainty equivalent rate of 9%. This is the intercept of the indifference curve. For a fixed portfolio, the indifference curve for that portfolio will have a higher y-intercept if the investor is less risk averse.
For a fixed portfolio, the indifference curves for two different investors will intersect at the point corresponding to that portfolio’s standard deviation and expected return. This is because, by definition, the portfolio itself will always lie on the indifference curve for its utility value. In the above graph, 6% is the certainty-equivalent rate for the investor with \(A = 3.5\) for portfolio \(H\), and 9% is the certainty-equivalent rate for the same portfolio, but for the investor with \(A=2\). Therefore, these indifference curves will intersect at the point corresponding to portfolio \(H\).
For the investor with \(A=2\), portfolio \(H\) lies on the 9% curve, and the other two portfolios lie below it; this is the geometric interpretation of the earlier result that this investor would prefer portfolio \(H\) to the other two. In contrast, for the investor with \(A = 3.5\), portfolio \(H\) lies on the 6% curve, and the other two portfolios lie above it, indicating that this investor would prefer either \(L\) or \(M\) to portfolio \(H\).
*Note that higher degrees of risk aversion correspond to steeper slopes, since a more risk adverse investor will demand higher returns at large standard deviations than a less risk averse investor would.
The Capital Allocation Line (CAL) is a plot of the expected return of the complete portfolio against standard deviation. In order to plot this, note that for the complete portfolio \[ y = \frac{\sigma_C}{\sigma_P} \] so that \[ E[r_C] = r_f + \frac{\sigma_C}{\sigma_P}(E[r_P] - r_f) \]
Consider the following three portfolios:
bkm.utility.example.2 = read.csv("./Data/BKM_6_v2.csv")
## Warning in read.table(file = file, header = header, sep = sep, quote
## = quote, : incomplete final line found by readTableHeader on './Data/
## BKM_6_v2.csv'
bkm.utility.example.2 = bkm.utility.example.2 %>% mutate(expected_return = risk.free.rate + risk_premium)
bkm.utility.example.2
## portfolio risk_premium standard_deviation expected_return
## 1 A 0.04 0.1 0.09
## 2 B 0.04 0.2 0.09
## 3 C 0.06 0.2 0.11
Impose the restriction that \(y \leq 1\) since we cannot allocate more than 100% of the portfolio to the risky asset.
CAL.data = merge(bkm.utility.example.2, data.frame(sd = 0:25 / 100)) %>% filter(sd <= standard_deviation)
expected.return = function(risk.free.rate, sigma.C, sigma.P, expected.return.P) {
return(risk.free.rate + sigma.C / sigma.P * (expected.return.P - risk.free.rate))
}
CAL.data$CAL = apply(CAL.data %>% select(-portfolio), 1, function(y) {expected.return(risk.free.rate = risk.free.rate, sigma.C = y['sd'], sigma.P = y['standard_deviation'], expected.return.P = y['expected_return'])})
ggplot(data = CAL.data, aes(x = sd, y = CAL, col = portfolio)) + geom_line()
This graph plots the investment opportunity set of all feasible portfolios with \(0 \leq y \leq 1\). The slope of the Capital Allocation Line is the Sharpe Ratio, the ratio of the risk premium to standard deviation: \[ S = \frac{E(r_P) - r_f}{\sigma_P} \] Note that the Sharpe ratio increases if either the standard deviation decreases, or the expected return increases; therefore, higher values of the Sharpe ratio correspond to better risky portfolios.
It is possible to extend the Capital Allocation Line for \(y \geq 1\), but this assumes that the investor borrows money to make leveraged investments in the risky portfolio. However, the investor must typically borrow at a rate \(r_B > r_f\), so the expected return now becomes \[ E[r_C] = y r_P + (1 - y) r_B = r_B + \frac{\sigma_C}{\sigma_P}(r_P - r_B) \] The slope, and therefore the Sharpe ratio, become \[ \frac{E(r_P) - r_B}{\sigma_P} \] when \(y \geq 1\). This can be visualized as follows:
CAL.data.v2 = merge(bkm.utility.example.2, data.frame(sd = 0:25 / 100))
expected.return.v2 = function(risk.free.rate, borrowing.rate, sigma.C, sigma.P, expected.return.P) {
return(ifelse(sigma.C <= sigma.P, risk.free.rate + sigma.C / sigma.P * (expected.return.P - risk.free.rate), borrowing.rate + sigma.C / sigma.P * (expected.return.P - borrowing.rate)))
}
CAL.data.v2$CAL = apply(CAL.data.v2 %>% select(-portfolio), 1, function(y) {expected.return.v2(risk.free.rate = risk.free.rate, borrowing.rate = 0.08, sigma.C = y['sd'], sigma.P = y['standard_deviation'], expected.return.P = y['expected_return'])})
ggplot(data = CAL.data.v2, aes(x = sd, y = CAL, col = portfolio)) + geom_line() + geom_point(data = bkm.utility.example.2, aes(x = standard_deviation, y = expected_return, col = portfolio), size = 4)
The points correspond to \(y=1\), i.e. situations in which the complete portfolio consists only of the risky portfolio \(P\).
The optimal amount of investment, \(y^*\), in the risky portfolio, is the value of \(y\) which maximizes the investor’s utility function. To determine this value, first express utility as a function of \(y\): \[ U(y) = r_f + y(r_P - r_f) - \frac12 A \sigma_P^2 y^2 \] The derivative with respect to \(y\) is \[ U'(y) = r_P - r_f - A \sigma_P^2y \] Setting \(U'(y^*) = 0\) and solving for \(y\), we obtain \[ y^* = \frac{r_P - r_f}{A\sigma_P^2} \] Rearranging the formula, we can also deduce the investor’s risk aversion based on their degree of investment in the risky portfolio: \[ A = \frac{r_P - r_f}{y^* \sigma_P^2} \]
For the three investors considered earlier, we can calculate the optimum value of \(y\) for each of the three risk portfolios described above. If this results in a value of \(y\geq 1\), then the borrowing rate is used instead subject to the additional constraint that \(y\geq 1\).
optimum.example = merge(bkm.utility.example.2, A.df)
optimum.y = function(risk.free.rate, expected.return, A, standard.deviation, borrowing.rate) {
no.borrow.optimum = (expected.return - risk.free.rate) / (A * standard.deviation^2)
borrowing.optimum = (expected.return - borrowing.rate) / (A * standard.deviation^2)
return(ifelse(no.borrow.optimum <= 1, no.borrow.optimum, pmax(borrowing.optimum, 1)))
}
optimum.example$optimum_y = apply(optimum.example %>% select(-portfolio), 1, function(y) {optimum.y(risk.free.rate = risk.free.rate, expected.return = y['expected_return'], A = y['A_value'], standard.deviation = y['standard_deviation'], borrowing.rate = 0.08)})
optimum.example
## portfolio risk_premium standard_deviation expected_return A_value
## 1 A 0.04 0.1 0.09 2.0
## 2 B 0.04 0.2 0.09 2.0
## 3 C 0.06 0.2 0.11 2.0
## 4 A 0.04 0.1 0.09 3.5
## 5 B 0.04 0.2 0.09 3.5
## 6 C 0.06 0.2 0.11 3.5
## 7 A 0.04 0.1 0.09 5.0
## 8 B 0.04 0.2 0.09 5.0
## 9 C 0.06 0.2 0.11 5.0
## optimum_y
## 1 1.0000000
## 2 0.5000000
## 3 0.7500000
## 4 1.0000000
## 5 0.2857143
## 6 0.4285714
## 7 0.8000000
## 8 0.2000000
## 9 0.3000000
Once the optimum \(y\) has been found, we can determine the expected rate of return for the complete portfolio at this value, and the associated utility value.
expected.return.complete = function(risk.free.rate, expected.return, optimum.y) {
return(risk.free.rate + optimum.y *(expected.return - risk.free.rate))
}
utility.complete = function(risk.free.rate, expected.return, optimum.y, standard.deviation, A) {
return(expected.return.complete(risk.free.rate, expected.return, optimum.y) - 0.5 * A * standard.deviation^2 * optimum.y^2)
}
optimum.example$CP_expected_return = apply(optimum.example %>% select(-portfolio), 1, function(y) {expected.return.complete(risk.free.rate, y['expected_return'], y['optimum_y'])})
optimum.example$CP_utility= apply(optimum.example %>% select(-portfolio), 1, function(y) {utility.complete(risk.free.rate, y['expected_return'], y['optimum_y'], y['standard_deviation'], y['A_value'])})
optimum.example = optimum.example %>% mutate(CP_sd = standard_deviation * optimum_y)
optimum.example
## portfolio risk_premium standard_deviation expected_return A_value
## 1 A 0.04 0.1 0.09 2.0
## 2 B 0.04 0.2 0.09 2.0
## 3 C 0.06 0.2 0.11 2.0
## 4 A 0.04 0.1 0.09 3.5
## 5 B 0.04 0.2 0.09 3.5
## 6 C 0.06 0.2 0.11 3.5
## 7 A 0.04 0.1 0.09 5.0
## 8 B 0.04 0.2 0.09 5.0
## 9 C 0.06 0.2 0.11 5.0
## optimum_y CP_expected_return CP_utility CP_sd
## 1 1.0000000 0.09000000 0.08000000 0.10000000
## 2 0.5000000 0.07000000 0.06000000 0.10000000
## 3 0.7500000 0.09500000 0.07250000 0.15000000
## 4 1.0000000 0.09000000 0.07250000 0.10000000
## 5 0.2857143 0.06142857 0.05571429 0.05714286
## 6 0.4285714 0.07571429 0.06285714 0.08571429
## 7 0.8000000 0.08200000 0.06600000 0.08000000
## 8 0.2000000 0.05800000 0.05400000 0.04000000
## 9 0.3000000 0.06800000 0.05900000 0.06000000
Focussing on the investor with \(A = 2\), look at the indifference curves corresponding to the optimum \(y\) value for each of the portfolios \(A\), \(B\), and \(C\). Plot these along with the capital allocation lines for each portfolio.
indifference.curve.data.2 = merge(data.frame(optimum_utility = c(0.08, 0.06, 0.0725)), data.frame(sd = 0:25 / 100))
indifference.curve.data.2$utility = apply(indifference.curve.data.2, 1, function(y){ indifference.curve(A = 2, sd = y['sd'], U = y['optimum_utility'])})
ggplot(data = indifference.curve.data.2, aes(x = sd, y = utility, col = as.factor(optimum_utility))) + geom_line() + geom_line(data = CAL.data.v2, aes(x = sd, y = CAL, col = portfolio)) + geom_point(data = optimum.example %>% filter(A_value == 2.0), aes(x = CP_sd, y = CP_expected_return, col = portfolio), size = 4) + labs(x = "Standard Deviation", y = "Expected Return")
In each case, the optimum complete portfolio is the one where the highest indifference curve lies tangent to the capital allocation line. Note that the higher the Sharpe ratio of the portfolio, the higher the optimum utility is.
To view the results from another perspective, focus on portfolio \(A\) and see how the results change as risk tolerance changes:
indifference.curve.data.3 = merge(optimum.example %>% filter(as.character(portfolio) == "A") %>% select(CP_utility, A_value), data.frame(sd = 0:25 / 100))
indifference.curve.data.3$utility = apply(indifference.curve.data.3, 1, function(y){ indifference.curve(A = y['A_value'], sd = y['sd'], U = y['CP_utility'])})
ggplot(data = indifference.curve.data.3, aes(x = sd, y = utility, col = as.factor(A_value))) + geom_line() + geom_line(data = CAL.data.v2 %>% filter(as.character(portfolio) == "A"), aes(x = sd, y = CAL, col = portfolio)) + geom_point(data = optimum.example %>% filter(as.character(portfolio) == "A"), aes(x = CP_sd, y = CP_expected_return, col = portfolio), size = 4) + xlim(0, 0.15) + ylim(0, 0.13)
## Warning: Removed 30 rows containing missing values (geom_path).
## Warning: Removed 10 rows containing missing values (geom_path).
For the investors with \(A = 2\) and \(A = 3.5\), the indifference curves are both tangent when \(y=1\). However, for the steeper indifference curve when \(A=5\), the point of tangency occurs for a smaller value of \(y = 0.80\). This corresponds to both a lower standard deviation and a lower return.
When determining the risky portfolio \(P\), a passive market strategy is one that avoids any security analysis, such as a portfolio consisting of a wide range of corporate stocks in proportion to their market value.
An example is the S&P 500 composite index.
The Capital Allocation Line associated with such an index, along with 1-month T-bills as the risk-free asset, is the Capital Market Line.
A key advantage of this approach is that it avoids the cost of actively managing a portfolio.
The free rider benefit results from many active market participants bidding up prices on undervalued assets, and driving down prices of overvalued assets, resulting in a fair price for passive market participants; in essence, a passive strategy is similar to that of the average active investor.