Introduction
How much more expected return is required to justify the turnover and the taxes that must be paid immediately? That’s the question we will continue to explore. In Part 1 we began with a simple example and built the tools to better address the question. In Part 2 we explored how the answered varies with the capital gain and time horizon. In this part, we consider the case of an investor who is “financially immortal” by which we mean the investor does not need to sell the current investment before he or she passes and that its basis can be stepped up at death thereby avoiding capital gains.
In this case, we will compare the terminal value of the current portfolio with the value of a portfolio assuming the current one is immediately liquidated and capital gains are paid. We use the same assumptions as Part 2.
The previoius posts contained some functions we will use here. To streamline the post we have put that code into a separate file and source it below. All the code is available in this GitHub repository.
source("TaxAlphaUtilities.r") # load the code (functions)
marketAssumptions <- rbind(c(0.024,0.019,0.005),c(0.068,0.031,0.037),c(0.079,0.024,0.054))
rownames(marketAssumptions)<-c("US Large Stocks","EAFE","Emerging Markets")
colnames(marketAssumptions)<-c("ExpectedReturns","Dividend Yield","Appreciation")
Every month Research Affiliates publishes 10 year return forecasts for a variety of asset classes. As of February 28, 2018, they assumed the following nominal annualized expected returns:
kable(marketAssumptions*100,digits = 1, align="c", caption="Market Assumptions (%)")
ExpectedReturns | Dividend Yield | Appreciation | |
---|---|---|---|
US Large Stocks | 2.4 | 1.9 | 0.5 |
EAFE | 6.8 | 3.1 | 3.7 |
Emerging Markets | 7.9 | 2.4 | 5.4 |
So Research Affiliates expects stocks in international developed (EAFE) and emerging markets to outperform. The margin seems like enough, but is it? To add to the realism, consider the following chart of SPY, an ETF that tracks the S&P 500. Its price has more than tripled which is a gain of over 200% since the beginning of 2009. Should an investor bite the bullet and pay the capital gains taxes for the expected higher returns in other markets?
As an example, we compare two scenarios using the assumptions for Research Affiliates. In one scenario an investor continues to hold $100 in US Large Stocks at a basis of $33.33 (a 200% gain) for 10 years. In another scenario the investor liquidates and purchase EAFE stocks.
taxRateDiv <- 0.25 # Dividends are taxed at 25%
taxRateLTCG <- 0.25 # Capital gains are taxed at 25%
horizon <- 10 # The time horizon is 10 years
currentValue <- 100
currentBasis <- 33.33
h <- createScenario(currentValue,currentBasis,
marketAssumptions["US Large Stocks","Dividend Yield"],
marketAssumptions["US Large Stocks","Appreciation"],
taxRateDiv, taxRateLTCG, horizon)
currentValueAT <- currentValue - (currentValue - currentBasis) * h$taxRateLTCG
l <- createScenario(currentValueAT, currentValueAT,
marketAssumptions["EAFE","Dividend Yield"],
marketAssumptions["EAFE","Appreciation"],
taxRateDiv, taxRateLTCG, horizon)
hAT <- ATValue_scenario(h)
lAT <- ATValue_scenario(l)
kable(hAT[,1:5], digits = 2, caption = "Hold US")
Value | Basis | Dividend | Tax | Growth | |
---|---|---|---|---|---|
0 | 100.00 | 33.33 | 0.00 | 0.00 | 0.00 |
1 | 101.93 | 34.75 | 1.90 | 0.48 | 0.50 |
2 | 103.89 | 36.21 | 1.94 | 0.48 | 0.51 |
3 | 105.89 | 37.69 | 1.97 | 0.49 | 0.52 |
4 | 107.93 | 39.20 | 2.01 | 0.50 | 0.53 |
5 | 110.00 | 40.73 | 2.05 | 0.51 | 0.54 |
6 | 112.12 | 42.30 | 2.09 | 0.52 | 0.55 |
7 | 114.28 | 43.90 | 2.13 | 0.53 | 0.56 |
8 | 116.48 | 45.53 | 2.17 | 0.54 | 0.57 |
9 | 118.72 | 47.19 | 2.21 | 0.55 | 0.58 |
10 | 121.01 | 48.88 | 2.26 | 0.56 | 0.59 |
kable(lAT[,1:5], digits = 2, caption = "Liquidate, buy EAFE")
Value | Basis | Dividend | Tax | Growth | |
---|---|---|---|---|---|
0 | 83.33 | 83.33 | 0.00 | 0.00 | 0.00 |
1 | 88.35 | 85.27 | 2.58 | 0.65 | 3.08 |
2 | 93.68 | 87.32 | 2.74 | 0.68 | 3.27 |
3 | 99.32 | 89.50 | 2.90 | 0.73 | 3.47 |
4 | 105.30 | 91.81 | 3.08 | 0.77 | 3.67 |
5 | 111.65 | 94.26 | 3.26 | 0.82 | 3.90 |
6 | 118.38 | 96.86 | 3.46 | 0.87 | 4.13 |
7 | 125.51 | 99.61 | 3.67 | 0.92 | 4.38 |
8 | 133.07 | 102.53 | 3.89 | 0.97 | 4.64 |
9 | 141.09 | 105.62 | 4.13 | 1.03 | 4.92 |
10 | 149.59 | 108.90 | 4.37 | 1.09 | 5.22 |
From the “Value” column, we see that liquidating and investing in the EAFE portfolio results in a higher expected terminal value $149.59 versus $121.01.
The question we asked initially was how much more return would be need to justify the trade. We have two sources of return: dividends and appreciation. Because dividends are more predictable, we will only solve for the appreciation required.
breakeven <- appreciationRoot(h,l,6,"Value")
In the example we are using, EAFE has higher dividends than US Large stocks. It turns out that the appreciation of EAFE needs to be 1.48% for the trade to be as good as not trading (we’ll call this a breakeven rate). This would make the total return 4.58% compared to the US Large Stock return of 2.4%. Below is the table for the values assuming the appreciation is the breakeven rate and note the terminal value matches the terminal value of holding onto the US Large Cap portfolio.
l2 <- l
l2$appreciation <- breakeven$root
kable(ATValue_scenario(l2)[,1:5], digits = 2, caption = "Liquidate, buy EAFE assuming breakeven appreciation")
Value | Basis | Dividend | Tax | Growth | |
---|---|---|---|---|---|
0 | 83.33 | 83.33 | 0.00 | 0.00 | 0.00 |
1 | 86.50 | 85.27 | 2.58 | 0.65 | 1.23 |
2 | 89.79 | 87.28 | 2.68 | 0.67 | 1.28 |
3 | 93.20 | 89.37 | 2.78 | 0.70 | 1.32 |
4 | 96.74 | 91.54 | 2.89 | 0.72 | 1.38 |
5 | 100.42 | 93.78 | 3.00 | 0.75 | 1.43 |
6 | 104.23 | 96.12 | 3.11 | 0.78 | 1.48 |
7 | 108.20 | 98.54 | 3.23 | 0.81 | 1.54 |
8 | 112.31 | 101.06 | 3.35 | 0.84 | 1.60 |
9 | 116.58 | 103.67 | 3.48 | 0.87 | 1.66 |
10 | 121.01 | 106.38 | 3.61 | 0.90 | 1.72 |
Now that we’ve illustrated the concept and process, let’s consider 9 investors with $100 in SPY who purchased their position for $10, $20, $30, … $90. How much more return must they expect to induce them to trade given an expected return of 2.4% for US Large Stocks?
out <- sapply(seq(10,90,10), function(x) {
h$initBasis <- x
l$initValue <- h$initValue - (h$initValue-h$initBasis)*h$taxRateLTCG
l$initBasis <- l$initValue
appreciationRoot(h,l,6,"Value")$root
})
result <- cbind(out,out+l$dividendYld,out+l$dividendYld-h$dividendYld-h$appreciation)
row.names(result) <- paste0("$",seq(10,90,10))
colnames(result) <- c("Appreciation","Total Return", "Excess")
kable(result*100,digits=2, caption = "Breakeven rates (%)")
Appreciation | Total Return | Excess | |
---|---|---|---|
$10 | 2.23 | 5.33 | 2.93 |
$20 | 1.90 | 5.00 | 2.60 |
$30 | 1.58 | 4.68 | 2.28 |
$40 | 1.27 | 4.37 | 1.97 |
$50 | 0.97 | 4.07 | 1.67 |
$60 | 0.68 | 3.78 | 1.38 |
$70 | 0.40 | 3.50 | 1.10 |
$80 | 0.12 | 3.22 | 0.82 |
$90 | -0.14 | 2.96 | 0.56 |
plot(seq(10,90,10),result[,"Appreciation"], col="red",
pch=19, type="b",
main="Breakeven based on cost basis",
ylim=c(min(result),max(result)),
xlab="Cost basis", ylab= "Return")
points(seq(10,90,10),result[,"Total Return"], col="blue", pch=18, type="b")
abline(h=h$dividendYld+h$appreciation,col="gray")
abline(h=0,col="gray")
legend(10, 0.015,legend=c("Appreciation","Total Return"),
col=c("red","blue"),
lty=1:2, pch=c(19,18), box.lty = 0)
The appreciation is the return so that the terminal value “breaks even” with that of the hold scenario. The total return combines the appreciation with the dividend yield. The excess is the difference over the total return (yield + appreciation) of the hold strategy.
Time horizon
Let’s consider different time horizons while maintaining our $33.33 basis. We consider horizons out to 40 years given how long investors may live.
thorizon <- seq(1,40)
out <- sapply(thorizon, function(x) {
h$horizon <- x
l$horizon <- x
l$initValue <- h$initValue - (h$initValue-h$initBasis)*h$taxRateLTCG
l$initBasis <- l$initValue
appreciationRoot(h,l,6, "Value")$root
})
result <- cbind(out,out+l$dividendYld,out+l$dividendYld-h$dividendYld-h$appreciation)
row.names(result) <- paste0(thorizon,"Y")
colnames(result) <- c("Appreciation","Total Return", "Excess")
kable(result*100,digits=2, caption = "Breakeven rates (%)")
Appreciation | Total Return | Excess | |
---|---|---|---|
1Y | 19.99 | 23.09 | 20.69 |
2Y | 9.33 | 12.43 | 10.03 |
3Y | 5.99 | 9.09 | 6.69 |
4Y | 4.35 | 7.45 | 5.05 |
5Y | 3.39 | 6.49 | 4.09 |
6Y | 2.74 | 5.84 | 3.44 |
7Y | 2.29 | 5.39 | 2.99 |
8Y | 1.95 | 5.05 | 2.65 |
9Y | 1.69 | 4.79 | 2.39 |
10Y | 1.48 | 4.58 | 2.18 |
11Y | 1.30 | 4.40 | 2.00 |
12Y | 1.16 | 4.26 | 1.86 |
13Y | 1.04 | 4.14 | 1.74 |
14Y | 0.94 | 4.04 | 1.64 |
15Y | 0.85 | 3.95 | 1.55 |
16Y | 0.77 | 3.87 | 1.47 |
17Y | 0.70 | 3.80 | 1.40 |
18Y | 0.64 | 3.74 | 1.34 |
19Y | 0.58 | 3.68 | 1.28 |
20Y | 0.53 | 3.63 | 1.23 |
21Y | 0.49 | 3.59 | 1.19 |
22Y | 0.45 | 3.55 | 1.15 |
23Y | 0.41 | 3.51 | 1.11 |
24Y | 0.38 | 3.48 | 1.08 |
25Y | 0.35 | 3.45 | 1.05 |
26Y | 0.32 | 3.42 | 1.02 |
27Y | 0.29 | 3.39 | 0.99 |
28Y | 0.27 | 3.37 | 0.97 |
29Y | 0.24 | 3.34 | 0.94 |
30Y | 0.22 | 3.32 | 0.92 |
31Y | 0.20 | 3.30 | 0.90 |
32Y | 0.18 | 3.28 | 0.88 |
33Y | 0.16 | 3.26 | 0.86 |
34Y | 0.15 | 3.25 | 0.85 |
35Y | 0.13 | 3.23 | 0.83 |
36Y | 0.12 | 3.22 | 0.82 |
37Y | 0.10 | 3.20 | 0.80 |
38Y | 0.09 | 3.19 | 0.79 |
39Y | 0.08 | 3.18 | 0.78 |
40Y | 0.07 | 3.17 | 0.77 |
plot(thorizon,result[,"Appreciation"], col="red",
pch=19, type="b",
main="Breakeven based on horizon",
ylim=c(min(result),max(result)),
xlab="Horizon (years)", ylab= "Return")
points(thorizon,result[,"Total Return"], col="blue", pch=18, type="b")
abline(h=h$dividendYld+h$appreciation,col="gray")
abline(h=0,col="gray")
legend(6, 0.15,legend=c("Appreciation","Total Return"),
col=c("red","blue"),
lty=1:2, pch=c(19,18), box.lty = 0)
An excellent article on the subject is Is Your Alpha Big Enough to Cover Its Taxes? Revisited by Arnott, Berkin and Bouchey, 2011 Investments & Wealth Monitor. For more on R visit [R-bloggers](https://www.r-bloggers.com/).
The code used in this article is available from this [Github repository](https://github.com/rexmacey/TaxAlpha).