Assume SPY, the S&P 500 index-tracking ETF, produces realized annual returns as described below. The objective is to apply four different investment strategies over this historical return period and evaluate the performance of a $10,000 investment.
setfour <- new.env()
Years <- c(2001,2002,2003,2004,2005,2006,2007,2008,2009,2010)
Returns <- c(-0.0710, -0.1676, 0.2532, 0.0315, -0.0061, 0.1629, 0.0643, -0.3384, 0.1471, 0.1812)
frame <- as.data.frame(cbind(Years, Returns))
setfour$frame <- frame
print(frame)
## Years Returns
## 1 2001 -0.0710
## 2 2002 -0.1676
## 3 2003 0.2532
## 4 2004 0.0315
## 5 2005 -0.0061
## 6 2006 0.1629
## 7 2007 0.0643
## 8 2008 -0.3384
## 9 2009 0.1471
## 10 2010 0.1812
Capital Flows are held fixed at the start of the investment period. An initial investment of $10,000 is invested in SPY at the start of year 2001. No withdrawals are take taken out during the 10-year period.
Capital Investments are variable and a funtion of prior realized SPY annual returns. If prior year returns are positive, all capital is invested in the index. Otherwise, only 80% of capital is invested in the index and the remaining 20% is invested in a 3% annual interest crediting fixed income ETF. Transaction costs are not factored into realized returns.
Rather than having 100% of a client’s capital exposed, $1,000 is invested each year into the index.
This strategy is similar to strategy C, except that the remaining capital is invested in the above-mentioned interest crediting fixed income ETF. Every year, the capital invested in the ETF grows by $1,000, while the capital invested in the 3% risk-free account declines proportionately.
The code below implements each strategy and the investment results are stored in the frame object.
# Strategy A: Buy & Hold
frame$Buy_Hold <- rep(0, nrow(frame))
frame$Buy_Hold[1] <- 10000*(1+frame$Returns[1])
for (i in 2:nrow(frame)) {
frame$Buy_Hold[i] <- frame$Buy_Hold[i-1]*(1+frame$Returns[i])
}
# Strategy B: Market Chasing
rf_bond <- .03
frame$Chasing <- rep(0, nrow(frame))
frame$Chasing[1] <- (8000*(1+frame$Returns[1])) + (2000 * (1+rf_bond))
for (i in 2:nrow(frame)) {
if(frame$Returns[i-1] > 0) {
frame$Chasing[i] <- (frame$Chasing[i-1]*(1+frame$Returns[i]))
} else {
frame$Chasing[i] <- ((0.8*frame$Chasing[i-1])*(1+frame$Returns[i])) +
((0.2*frame$Chasing[i-1])*(1+rf_bond))
}
}
# Strategy C: Dollar Cost Averaging
frame$DCA <- rep(0, nrow(frame))
deposit <- 1000
frame$DCA[1] <- deposit*(1+frame$Returns[1])
for (i in 2:nrow(frame)) {
frame$DCA[i] <- (frame$DCA[i-1] + deposit)*(1+frame$Returns[i])
}
# Strategy D: Mixed
# Create vectors of capital flows for investment strategy
init_capital <- 10000
x <- rep(0, nrow(frame))
y <- rep(0, nrow(frame))
x[1] <- init_capital - deposit
y[1] <- deposit
for (i in 2:nrow(frame)) {
x[i] <- x[i-1] - deposit
y[i] <- y[i-1] + deposit
}
frame$Mix <- rep(0, nrow(frame))
frame$Mix[1] <- (y[1]*(1+frame$Returns[1])) + ((x[1])*(1+rf_bond))
for (i in 2:nrow(frame)) {
frame$Mix[i] <- (y[i]*(1+frame$Returns[i])) + (x[i]*(1+rf_bond))
}
print(frame)
## Years Returns Buy_Hold Chasing DCA Mix
## 1 2001 -0.0710 9290.000 9492.000 929.000 10199.0
## 2 2002 -0.1676 7732.996 8276.265 1605.700 9904.8
## 3 2003 0.2532 9690.991 10002.362 3265.463 10969.6
## 4 2004 0.0315 9996.257 10317.437 4399.825 10306.0
## 5 2005 -0.0061 9935.280 10254.500 5366.886 10119.5
## 6 2006 0.1629 11553.737 11652.394 7404.052 11097.4
## 7 2007 0.0643 12296.642 12401.643 8944.432 10540.1
## 8 2008 -0.3384 8135.458 8204.927 6579.236 7352.8
## 9 2009 0.1471 9332.184 9219.712 8694.142 11353.9
## 10 2010 0.1812 11023.176 10890.324 11450.720 11812.0
The mixed and dollar cost averaging strategies yield the largest returns with a gain of 1,812 and 1,450.72, respectively. Refer to the table below for more details. It appears that a DCA capital investment strategy is superior to a traditional buy and hold strategy, as well as the market chasing momentum strategy described in this example. This is significant because it emphasizes the benefits of reducsing exposure to downside volatility by investing capital on a reoccuring, proportional basis.
results_matrix <- matrix(0, nrow = 3, ncol = 4)
colnames(results_matrix) <- colnames(frame[,3:6])
rownames(results_matrix) <- c('Realized Gain', 'Holding Period Return', 'Annualized Return')
for (i in 1:ncol(results_matrix)) {
data <- frame[,3:6]
results_matrix[1,i] <- data[10,i] - 10000
results_matrix[2,i] <- ((data[10,i] - 10000) / 10000) * 100
results_matrix[3,i] <- (((1+((data[10,i] - 10000)/10000))^(1/10)) - 1) * 100
}
print(results_matrix)
## Buy_Hold Chasing DCA Mix
## Realized Gain 1023.176009 890.3241553 1450.720463 1812.000000
## Holding Period Return 10.231760 8.9032416 14.507205 18.120000
## Annualized Return 0.978909 0.8565436 1.363893 1.679252
Suppose an analyst identifies four stocks that may in fact be underpriced; that is, a claim to each of the respective firm’s future cash flows is offered at a bargain price on the market. Given this hypothesis, the analyst also estimates the current market risk premium, market volatility (sigma), and risk-free rate to be 8%, 20%, and 4%, respectively.
Refer to the stock estimates below.
You can also embed plots, for example:
## Average Return (%) Standard Deviation (%) Beta
## Stock I 9 15 0.5
## Stock II 8 16 0.4
## Stock III 15 30 1.2
## Stock IV 12 20 0.8
With this information, the expected returns of each stock under the assumptions of the CAPM can be derived. Under market equilibrium, no stock should yield a positive / negative alpha, i.e. no stock will produce a return in excess of that which is assumed by the market. As we see, all alpha estimates of excess returns are zerio.
rf_rate <- 4
Exp_Ret_Matrix <- matrix(0, nrow = 2, ncol = 4)
rownames(Exp_Ret_Matrix) <- c('Expected Return', 'Alpha')
colnames(Exp_Ret_Matrix) <- c('Stock I', 'Stock II', "Stock III", "Stock IV")
for (i in 1:ncol(Exp_Ret_Matrix)) {
Exp_Ret_Matrix[1,i] <- rf_rate + stock_matrix[i,3]*8
}
for (i in 1:ncol(Exp_Ret_Matrix)) {
Exp_Ret_Matrix[2,i] <- Exp_Ret_Matrix[1,i] - rf_rate - stock_matrix[i,3] * 8
}
print(Exp_Ret_Matrix)
## Stock I Stock II Stock III Stock IV
## Expected Return 8 7.2 13.6 10.4
## Alpha 0 0.0 0.0 0.0
However, the average return for each of the stocks are different from the CAPM estimates. Therefore, assume that each stock’s estimated alphas are not equal to zero. Stock I produces an alpha of 1%; Stock II produces an alpha of 0.8%; Stock III produces an alpha of 1.4%; Stock IV produces an alpha of 1.6%.
Idiosyncratic volatility is the firm-specific (intrinsic) risk that a firm carries and is not rewarded by the market. In other words, it is risk that is not factored into the CAPM model. The expected return for a risky asset is a linear combination of broad market risk and the stock’s correlation with the market. Such correlated risk is reflected in the beta estimate. Idiosyncratic risk is not correlated with the broad market and is thus not rewarded. This risk can be diversified (risk-sharing) away by holding several positions in a portfolio.
Idiosyncratic risk can be calculated as total asset volatility less the product of the asset’s beta and the market volatility. The calculations are left to the reader. The idiosyncratic volatility for stock 1,2,3, and 4 is 5%, 8%, 6%, and 4%, respectively.
The Treynor-Black Model is an active portfolio management strategy which seeks to maximize risk premium per unit of volatility by allocating capital to assets in proportion (weights) to their respective alpha divided by idiosyncratic volatility. Likewise, assets that produce higher alphas receive a higher share of aggregate capital.
This model is implemented in the code below, and the portfolio’s alpha, beta, and residual variance / volatility are computed as well.
alpha_vector <- as.vector(c(.01, .008, .014, .016))
idio_sigma_vector <- as.vector(idio_sigma^2)
TB <- rbind(alpha_vector, idio_sigma_vector)
sum_weights <- sum(TB[1,]/TB[2,])
weight_TB_1 <- (TB[1,1] / TB[2,1]) / sum_weights
weight_TB_2 <- (TB[1,2] / TB[2,2]) / sum_weights
weight_TB_3 <- (TB[1,3] / TB[2,3]) / sum_weights
weight_TB_4 <- (TB[1,4] / TB[2,4]) / sum_weights
TB_weights <- c(weight_TB_1, weight_TB_2, weight_TB_3, weight_TB_4)
show(TB_weights)
## alpha_vector alpha_vector alpha_vector alpha_vector
## 0.20899855 0.06531205 0.20319303 0.52249637
Assuming a fixed-allocaiton strategy, an investor would allocate approximately 21% to stock I, 7% to stock II, 20% to stock III, and 52% to stock IV. This is consistent with a strategy of chasing alpha while mitigating concentration risk.
The alpha of the overall portfolio is a linear combination of each stock’s alpha and the proportion of capital allocated to the stock. Following, the portfolio’s alpha is approximately 1.4%.
# Portfolio Alpha
alpha_active <- sum(TB_weights*TB[1,1:4])
# Portfolio Beta
beta_active <- sum(stock_matrix[,3]*TB_weights)
# Portfolio Residual Variance
idio_var_active <- sum(TB[2,]*TB_weights)
idio_sigma_active <- sqrt(sum(TB[2,]*TB_weights))
The portfolio’s beta is calculated similarly as a linear function of each stock’s beta and its weight in the overall portfolio. Likewise, the active portfolio’s beta estimate is approximately 0.8. Lastly, the residual variance of the active portfolio is, similarly, a linear function of each stock’s squared idiosyncratic volatility and its proportion (weight) in the portfolio. The active portfolio’s residual variance (the risk that is not factored into CAPM expected returns estimates) is 0.0025. The residual volatility is 5%.
The strategy above still leaves a client exposed to idiosyncratic (residual) volatility. By allocating a proportion of capital to the market portfolio, this risk can be eliminated. Let the weight in the active (Treynor-Black) portfolio and the market portfolio equal:
\(w_A = [\alpha_A/\sigma^2_{IA}]/[(E(R_M)-R_f)/\sigma^2_M) + (1-\beta_A) *(\alpha_A / \sigma^2_{IA})]\)
\(w_M = 1-w_A\)
The respective weights are derived below. It looks like in order to eliminate all of the idiosyncratic exposure, we need to (borrow) short the market portfolio and invest the proceeds in the active portfolio
#D: TB Model plus Market Portfolio
# Compute weights
weight_A <- (alpha_active / idio_var_active) / ((0.08/(.20^2)) +
((1 - beta_active)*(alpha_active/idio_var_active)))
weight_M <- 1 - weight_A
show(weight_A); show(weight_M)
## [1] 1.752626
## [1] -0.752626
Having the optimal weights, the portfolio mixed with the active and market portfolioh has a expected return, beta, volatility, and Sharpe ratio of 0.64, 11.51%, 15.46%, and 0.49, respectively. Since the market Sharpe ratio is 0.4, the portfolio of portfolios outperforms the market portfolio.
# Portfolio Characteristics
mix_beta <- weight_M + (weight_A*beta_active)
mix_expret <- .04 + (mix_beta*.08) + (weight_A * alpha_active)
mix_var <- (mix_beta*.20)^2 + (weight_A*idio_sigma_active)^2
mix_sigma <- sqrt(mix_var)
mix_sharpe <- (mix_expret - .04) / mix_sigma
show(cbind(mix_beta, mix_expret, mix_sigma, mix_sharpe))
## mix_beta mix_expret mix_sigma mix_sharpe
## [1,] 0.6362474 0.115116 0.1545839 0.485924
This exercise involves performance evaluation of a hypothetical fund manager against a hypothetical benchmark.
# Fund Manager Return
manager_ret <- (0.75*2) + (0.20*1) + (.05*.5)
# Benchmark Return
benchmark_ret <- (0.65*2.5) + (0.25*1.2) + (.10*0.5)
The fund manager’s return of 1.73% underperformed the benchmark’s 1.98% return over the month. In assessing relative performance, we can identify the contribution of asset allocation and secuity selection. Let the impact of security selection on performance be a function of manager asset allocation multiplied by differences in returns. Similarly, let the impact of asset allocation on performance be a function of differences in asset allocation multiplied by average asset returns.
# Security Selection?
security_select <- 0.75*(2-2.5) + 0.20*(1-1.2) + 0.5*(0.0)
show(security_select)
## [1] -0.415
# Asset Allocation?
asset_allo <- 2*(0.75-0.65) + 1*(.20-.25) + 0.5*(.05-.10)
show(asset_allo)
## [1] 0.125
It appears that the fund’s security selection negatively impacted relative perofrmance to the benchmark by -0.415, whereas the manager’s asset allocation positively impacted the manager’s performance relative to the benchmark by 0.125.
The respective Sharpe ratios for funds A, B, C, D, and the market are computed below, listed in the respective order. Fund B has the highest excess return per unit of volatility at 2.25, followed by Fund A, D, C, and the market. In order for fund A to overtake fund B, fund A would have to produce an average return (%) of 14%.
# Sharpe Ratio
Sharpe_Matrix <- as.matrix(rep(0, 6))
colnames(Sharpe_Matrix) <- 'Sharpe Ratio'
rownames(Sharpe_Matrix) <- c('A', 'B', 'C', 'D', 'Market', 'Risk-Free')
Average_Ret <- c(14,12,10,20,16,3)
Std_Dev <- c(6,4,6,10,8,0)
Beta <- c(1.5,0.5,0.5,2.0,1.0,0)
for (i in 1:nrow(Sharpe_Matrix)) {
Sharpe_Matrix[i] <- (Average_Ret[i] - 3) / Std_Dev[i]
}
show(Sharpe_Matrix)
## Sharpe Ratio
## A 1.833333
## B 2.250000
## C 1.166667
## D 1.700000
## Market 1.625000
## Risk-Free NaN
The Treynor Ratio is similar to the Sharpe ratio with the exception that instead of dividing the fund’s risk premium by the fund’s total risk / standard deviation, the risk premium is divided by the fund’s beta. The siginficane of this measure is that covariance risk with the market is significant, i.e. idiosyncratic risk is diversified away and is not an accurate reflection of risk in mutual fund investments.
# Treynor Ratio
Treynor_Matrix <- as.matrix(rep(0,6))
colnames(Treynor_Matrix) <- 'Treynor Ratio'
rownames(Treynor_Matrix) <- c('A', 'B', 'C', 'D', 'Market', 'Risk-Free')
for (i in 1:nrow(Treynor_Matrix)) {
Treynor_Matrix[i] <- (Average_Ret[i] - 3) / Beta[i]
}
show(Treynor_Matrix)
## Treynor Ratio
## A 7.333333
## B 18.000000
## C 14.000000
## D 8.500000
## Market 13.000000
## Risk-Free NaN
From this output, Fund B produces the highest market-risk adjusted excess return at 18%, followed by fund C and the market at 14% and 13%, respectively. Another important performance metric is Jensen’s alpha, which is the actual fund’s excess return less the CAPM expected excess return as determined by the fund’s beta.
# Jensen's Alpha
Jensen_Alpha_Matrix <- as.matrix(rep(0,6))
colnames(Jensen_Alpha_Matrix) <- 'Jensens Alpha'
rownames(Jensen_Alpha_Matrix) <- c('A', 'B', 'C', 'D', 'Market', 'Risk-Free')
for (i in 1:nrow(Jensen_Alpha_Matrix)) {
Jensen_Alpha_Matrix[i] <- Average_Ret[i] - 3 - (Beta[i]*(13))
}
show(Jensen_Alpha_Matrix)
## Jensens Alpha
## A -8.5
## B 2.5
## C 0.5
## D -9.0
## Market 0.0
## Risk-Free 0.0
Fund B clearly outperforms the other funds with an alpha estimate of 2.5, whereas fund A and C perform poorly against the market index. In the event that an investor has limited choices in mutual funds (capital requirements, suitability restrictions, etc.), the Sharpe ratio and alpha estimate should be factored into investment recommendations. However, if an investor has enough capital to invest in a UMA account under multiple fund managers (strategists), the Treynor ratio is much more informative. It factors in covariance and beta risk, as oppossed to standard deviation (total risk) as the significant and accurate reflection of investment risk. By adding additional funds to a portfolio, diversification eliminates the severity of risk outside of systematic, market factors. Therefore, evaluating the risk-adjusted excess returns of multiple funds is better reflected under the Treynor measure.