When are investment losses too much to recover from?

by Franklin J. Parker, CFA

Traditional investment wisdom says “buy and hold forever.” Don’t worry when markets sell off because they will come back. I remember early in my career repeating these lines often — it was 2008 and market losses were all anyone wanted to call and talk to me about.

However, what I learned the hard way was that for investors with a goal to achieve (like retirement), losses do matter. And they can matter quite a lot. It isn’t because I worry that markets won’t recover. Historically, US markets have recovered and gone on to new highs. Rather, it is a worry about whether they will recover in time for you to hit your goal.

This is something I have written about extensively, including in my book Goals-Based Portfolio Theory. In this post, I want to use python to help us build an intuition around when investment losses become too great to recover from.

A quick background

In traditional investment theory, we look to maximize the following function

$$ u = m – \frac{1}{2}gs $$

where m is the expected return of your portfolio, s is the expected standard deviation of those returns, and g is how averse you are to volatility.

What should be clear is that this equation assumes that the only thing you are averse to is volatility — that is why your financial advisor gives you a risk-tolerance questionnaire. But that isn’t really true, is it?

You are probably investing because you want to do something with that money at some point in the future. You are, most likely, a goals-based investor because you have, well, goals to achieve. That means you aren’t averse to volatility per se, but rather averse to “not having the money you need when you need it,” to quote my friend, Martin Tarlie.

I’ll spare the entire background, but it should be clear that this changes the nature of the investment problem entirely. You now want to maximize the probability of achieving your goal:

$$ u = P( R | m, s ) $$

where P is the probability that your portfolio meets your required return, R, given your portfolio’s expected return and volatility, m and s. In this equation, volatility is an input to the equation, of course, but it isn’t what you are ultimately caring about. You ultimately care about the probability that you get the return you need to accomplish your goal in time.

A simple way to think about losses

Since what you really care about is achieving your return requirement, let’s dig into that a bit further. We can use the time-value of money to set up this equation for thinking about the role of losses in your portfolio:

$$L = \frac{ W }{w(r+1)^{t-1} } – 1 $$

where L is your maximum allowable loss, W is the total wealth you need to achieve your goal, w is the wealth you have dedicated to this goal today, r is the return markets provide during a recovery (after a signficant loss), and t is the time horizon within which you’d like to achieve your goal.

Here’s the logic: we’ve assumed that we had a one-year loss in your portfolio meaning we have a new and higher return requirement. If we have some assumption about the recovery rate of markets, r, then we can rearrange the whole thing into the equation above, solving for the maximum loss we can sustain in a year so that our new required return is met by the recovery return of the market.

Using python, let’s visualise our portfolio’s maximum loss tolerance with various inputs (I’ll generate it based on time as L decreases with time horizon). We’ll start by loading our libraries:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
from scipy.optimize import minimizeplt

From here we can build our L function and then input some variables to build some intuition about portfolio losses over time, and at various levels of funding.

# Build a simple max loss function
def maximum_loss(w, W, t, r):
    return W / (w * (r+1)**(t-1) ) - 1  

# Make time a variable and return max allowable loss
t = np.arange(5, 20, 0.5)

# Assumes I have $650,000 (or $500,000) with a need for $1,000,000 in t years.
# Portfolio recovery return is 12%
MAL_1 = maximum_loss( 650000, 1000000, t, 0.12)
MAL_2 = maximum_loss( 500000, 1000000, t, 0.12)

# Arrange into a dataframe
df = pd.DataFrame({'Time Until Goal': t, 'Maximum Allowable Loss, 65%': MAL_1,
                   'Maximum Allowable Loss, 50%': MAL_2})

# Generate visualization
plt.plot(df['Time Until Goal'], df['Maximum Allowable Loss, 65%'], label = 'Max Loss, 65% Funded', color = 'blue')
plt.plot(df['Time Until Goal'], df['Maximum Allowable Loss, 50%'], label = 'Max Loss, 50% Funded', color = 'black')
plt.xlabel('Years Until Goal')
plt.ylabel('')
plt.title('Maxmium Allowable Loss Over Time')
plt.legend()

And this yields a plot showing how time erodes our portfolio loss tolerance in an exponential way. Also of interest is how your funding level also erodes your portfolio’s loss tolerance.

Upside risk versus downside risk

The method above, however, only looks at downside risk. This is, of course, the most common type of risk investors think about. However, goals-based investors must also balance upside risk against downside risk. That is because you are unlikely to achieve your goal unless you gain the return that financial markets provide. Upside risk is, in summary, the risk that you are in cash when markets run higher.

A simple framework for thinking about this balance might be

$$I = \frac{S-B}{P-B}$$

where I is the percent of our portoflio we need to invest, S is the price at which we sold and moved to cash, B is our desired breakeven price, and P is our buy-back-in price.

Here’s what is going on: our breakeven price is the price at which we must buy back in lest we fall behind because markets moved higher without us. By default, that price is the price at which we exit. When we buy back in at a lower price (or higher price), that breakeven level moves higher (or lower). We can set an arbitrary value here, but something like 10% to 20% higher than our exit price would give us some comfortable room to breathe. If we sold as markets went down, then bought back in at a lower price with some of our portfolio, then our breakeven price is higher than the level we sold at — we gained some advantage in the sale.

Assuming, then, that we have some market outlook (if we don’t, then this whole exercise is moot), we can balance our downside risk with the same variables:

$$I = \frac{L}{G}$$

where L is the expected portfolio loss, I is the percent we reinvest at this new price, and G is the expected portfolio loss still to go. Using these two equations we can begin thinking about the balance between upside and downside risk. Let’s set up the problem in python:

# Build our % invested for downside risk
def invested_downside(L,G):
    return L/G

# Build our function for % invested upside risk
def invested_upside(S,B,P):
    return (S-B)/(P-B)

# Build our visualization using some assumptions
P = np.arange(0.65, 1.00, 0.01) # Price is our variable
# Percent to invest to mitigate downside risk
downside = invested_downside( maximum_loss(0.65, 1, 6, 0.12), 0.50 - P)
# Percent to invest to make our breakeven 20% higher (we exit at 1.00)
upside = invested_upside( 1.00, 1.20, P )

# Generate visualization

What this plot is showing us is when upside risk outweighs downside risk, and vice versa. As this demonstrates, we could invest a little under 50% of our portfolio when price drops to about $0.77, and thereby neutralize both upside and downside risk at the same time (that is the point where the two lines cross). Then, so long as we reinvest the remainder of our portfolio at $1.20 or less (we exited at $1.00), then we are ahead on the trade.

Of course, our market outlook could be wrong! Such is the travesty of investing: generally, all you can do is move risks around — you can never eliminate them. That said, the goals-based approach at least helps us quantify which risks you can afford to take, and which risk you can’t afford to take. Ideally, we move risks from the places you cannot afford it to the places where you can.

Again, this is a simplistic way to think about the problem, but it does at least offer us some framework for thinking. And, notice, none of this has anything whatsoever to do with your psychological risk tolerance (whatever that is). It is quantitatively derived from your goals.

Paying for hedges

When we talk about protecting against downside risk, hedging is an obvious solution. The next obvious step is to ask, “what are you willing to pay for those hedges?” And therein lies the rub.

So, what are we willing to pay for hedges, as goals-based investors? It turns out that is a quantitative question that we can answer.

The full derivation of this solution is a bit too long to post here, but you can read about it in chapter 5 of the book. But let’s sketch the basic idea.

We have two axes of things we care about. First, what is the probability of having a loss year verses a typical year (call this p)? And second, for each of those scenarios, what is the return of the hedged versus non-hedged porfolio? To visualize:

Hedged PortfolioNon-Hedged Portfolio
Typical year, 1 – pR_HR
Bad year, pR_H&LR_L

Where each return scenario has a different definition. The hedged portfolio’s return in a typical year, for example, is the return of the portfolio in a typical year minus the cost of the hedge. Drawing from our probability equation in the top section, we can then set up our problem in python.

# Build our probability function - use left-tail logistic cdf
def phi(x, location, scale):
    return 1 - 1/(1 + math.exp( -(x - location)/scale) )

# build our optimizer function
def optimization_objective( cost ):
    # In this function, R_L is the recovery needed in a non-hedged portfoliio that experienced a loss
    # R is the recovery return needed in a non-hedged portfolio that experiences a typical year
    # R_HL is the return needed after a loss with a hedge.
    # R_H is the return needed after a typical year where you paid for a hedge.
    R_L = (required_wealth / (1 + loss_return * initial_wealth) )**(1 / (time_until_goal - 1)) - 1
    R = (required_wealth / ( (1 + typical_return) * initial_wealth ) )**(1 / (time_until_goal - 1)) - 1
    R_HL = (required_wealth / ( (1 + amount_of_max_loss) * (initial_wealth + cost) ) )**(1 / (time_until_goal - 1)) - 1
    R_H = (required_wealth / ( (1 + typical_return) * (initial_wealth + cost)) )**(1 / (time_until_goal - 1)) - 1
 
    # Probability of attaining the long-term return requirement in each scenario.
    phi_L = phi(R_L, recovery_return, recovery_vol)
    phi_R = phi(R, typical_return, typical_vol)
    phi_HL = phi(R_HL, recovery_return, recovery_vol)
    phi_H = phi(R_H, typical_return, typical_vol)

    output = abs(p * phi_HL + (1-p) * phi_H - p * phi_L - (1-p) * phi_R)
    return output
    
# Probability of a bad year as our input variable
prob = np.arange(0.01, 0.65, 0.01)

# Look at how different variable values change FV cost to hedge
# Scenario A
loss_return = -0.40 # loss in a bad year
amount_of_max_loss = -0.25 # what is our maximum loss tolerance
initial_wealth = 1.00
required_wealth = 1.35
time_until_goal = 10
typical_return = 0.08
typical_vol = 0.11
recovery_return = 0.10
recovery_vol = 0.09
p = 0.45
c = []
for i in range(0, len(prob)):
    p = prob[i]
    c.append( minimize(optimization_objective, -0.01).x )

# Scenario B
loss_return = -0.30 # Change loss return to -30%
amount_of_max_loss = -0.15 # change hedge protection to -15%
c2 = []
for i in range(0, len(prob)):
    p = prob[i]
    c2.append( minimize(optimization_objective, -0.01).x )

# Scenario C
time_until_goal = 5 # Change time horizon to 5 years
loss_return = -0.40 # change loss return back to -40%
c3 = []
for i in range(0, len(prob)):
    p = prob[i]
    c3.append( minimize(optimization_objective, -0.01).x )

# Generate visualization

Giving us the plot below. As the plot demonstrates (and the numbers bear out in our modeling), how much you are willing to pay for a hedge is dependent on numerous factors. But, all of those factors are quantitative, bringing together your goals, your market outlook, and what the hedge does for us.

Closing thoughts

Despite the relatively simple framework, this analysis at least gives us some idea of how to think about hedging in light of our goals. Once we input your goal variables we get a simple number — 2.5% of your portfolio, let’s say — and we can then look at the market price of a hedge. If the market price is lower than our fair-value, we should hedge the portfolio. If it is higher than our fair-value, we do not hedge (or we hedge in another way!).

In any event, it is worth thinking through for investors with goals to achieve. Those goals are valuable. We should protect them.

This document is a general communication being provided for informational purposes only. It is educational in nature and not designed to be taken as advice or a recommendation for any specific investment product, strategy, plan feature or other purpose in any jurisdiction, nor is it a commitment from Directional Advisors to participate in any of the transactions mentioned herein. Any examples used are generic, hypothetical and for illustration purposes only. This material does not contain sufficient information to support an investment decision and it should not be relied upon by you in evaluating the merits of investing in any securities or products. In addition, users should make an independent assessment of the legal, regulatory, tax, credit, and accounting implications and determine, together with their own financial professionals, if any investment mentioned herein is believed to be appropriate to their personal goals. Investors should ensure that they obtain all available relevant information before making any investment. Any forecasts, figures, opinions or investment techniques and strategies set out are for information purposes only, based on certain assumptions and current market conditions and are subject to change without prior notice. All information presented herein is considered to be accurate at the time of production, but no warranty of accuracy is given and no liability in respect of any error or omission is accepted. It should be noted that investment involves risks, the value of investments and the income from them may fluctuate in accordance with market conditions and taxation agreements and investors may not get back the full amount invested. Both past performance and yields are not reliable indicators of current and future results.

What Does the P/E Ratio Tell You About the Market’s Growth Expectations?

by Franklin J. Parker, CFA

I am a big fan of extracting market expectations on various questions. It can give a starting point for your own analysis, giving a sort of “benchmark of knowledge” on a question. Here is what the market thinks, do I agree with that? If I do not agree, why not? Do I have more evidence/insight than the market or should I just adopt that view?

One use-case for this idea is extracting the market’s implied earnings growth rate from a company’s price to earnings ratio. While it isn’t obvious at first, a P/E ratio does carry some information about expected earnings growth. Here’s how.

The Concept

Since equity holders are owners of a company, they are entitled to its profits. Therefore, we can think of current price simply as the sum of all future cashflows discounted back to today:

$$ P = \sum_i^T \frac{E_i(1+g)^i}{(1+d)^i} $$

If we adjust today’s earnings, E, back to $1, that reduces the “price” side of our equation down to the price-to-earnings ratio, so, really

$$ P/E = \sum_i^T \frac{(1+g)^i}{(1+d)^i} $$

where g is the growth rate of earnings, d is the discount rate, and T is the number of years we care about.

What is great about this way of thinking is that we have all of the variables except one: the growth rate of earnings. We know P/E, we know the discount rate (usually it is the yield on the treasury maturing in the year we are discounting for). However, because of the dicounting summation, there is not a closed form solution (at least, I haven’t taken the time to derive it). Which means, we need to use a numerical method to solve for the g that will make the formula match our observed P/E.

Enter python.

Analysis: How Markets Infer a Growth Rate in P/E

After loading the requisite libraries, we will define the equation above as a function in python:

import numpy as np
import pandas as pd # not used, but I always import
from scipy.optimize import minimize
import matplotlib.pyplot as plt

# Define Price Function
#  Inputs the Growth Rate expected, the discount rate, and the time horizon
#  Outputs the expected Price/Earnings ratio
def price_function( growth_rate, discount_rate, time ):
    cashflows = [] # Prime the cashflows variable
    for t in range(1, time+1): # Build discounted cashflows over the time interval
        cashflows.append( (1 + growth_rate)**t / (1 + discount_rate)**t )
    return sum( cashflows )

This is helpful, but it is not a function that we can use our minimizer for, so using this function, let’s build a function that we can minimize:

# Create a function that we can minimize
def solver_function( growth_rate ):
    return ( PE - price_function( growth_rate[0], discount_rate, time ) )**2

Now, we input our known variables. I’ve solved for two time horizons, 10-years to breakeven and 15-years to breakeven, both of which are nested in the for loop:

# Input the known variables
discount_rate = 0.045 # 10-year UST yield. Could use different yields for different time horizons.
time = 15 # initialize the variable
PE = 20 # initialize the variable

# Now we iterate through various P/E ratios to determine what growth rate the 
# market expects
pe = list( range(1,250+1) )
g_15 = []
g_10 = []
for i in range(0, len(pe)):
    PE = pe[i]
    time = 15
    g_15.append( minimize( solver_function, 0.09 ).x[0] )
    time = 10
    g_10.append( minimize( solver_function, 0.09 ).x[0] )

Which gives us two arrays of implied growth rates — one for a 15-year breakeven (g_15), and one for a 10-year breakeven (g_10). Finally, let’s illustrate our results:

# Create visualization
plt.plot( pe, g_15, label = '15-Year Breakeven', color = 'blue' )
plt.plot( pe, g_10, label = '10-Year Breakeven', color = 'black' )
plt.title('Market-Implied Earnings Growth Rate')
plt.xlabel('P/E Ratio')
plt.legend()
plt.grid(True, linestyle = ':', color = 'gray')

As our plot demonstrates, as P/E ratios get above, say, 50 or so, the growth rate required to just break even from earnings gets to be a stretch. At a P/E of 50, we can infer that the market expects a growth rate of 19.4% every year for 15 years, or a growth rate of 34% every year for 10 years! At a P/E of 200, the implied growth rate is 60% for 10 years.

Analysis: How the Discount Rate Affects P/E

We’ve seen how we can derive an implied earnings growth rate from P/E, but what about the discount rate? How does that affect implied growth rates? Again, let’s continue with the code above to find out.

# Analysis of the discount rate
dr = [0.025, 0.045, 0.065] # Test various levels of discount rate
# Create an empty array with pe in rows and discount rates in columns
g_15 = np.empty((len(pe), len(dr)), dtype = float) 
g_10 = np.empty((len(pe), len(dr)), dtype = float)

# Iterate through different discount rates
for j in range(0, len(dr)):
    discount_rate = dr[j]
    # Iterate through pe
    for i in range(0, len(pe)):
        PE = pe[i]
        time = 15
        g_15[i,j] = minimize( solver_function, 0.09 ).x[0]
        time = 10
        g_10[i,j] = minimize( solver_function, 0.09 ).x[0]

And, if we then visualize the results, we find something to talk about.

What we can begin to see in this plot is that as discount rates move higher, growth rates must also move higher to support the same levels of P/E. We can say the same thing a different way: if discount rates move higher, P/E ratios will move lower assuming earnings growth expectations stay the same.

This, by the way, is why bond markets matter to stock markets! US Treasuries are typically the discount rate applied to earnings in coming years. As US Treasury yields rise, stock markets will tend to fall because the discount rate increases. In fact, let’s look at the problem from that perspective:

# Analyze how discount rates affect P/E ratios
dr = np.linspace(0.001, 0.100, num = 100) # Various discount rates
gr = [0.10, 0.15, 0.20, 0.25] # Various Growth rates
pe = np.empty( (len(dr), len(gr)) ) # Empty array with rows as dr and columns as gr

for g in range(0, len(gr)):
    for d in range(0, len(dr)):
        pe[d, g] = price_function( gr[g], dr[d], 10 )

Visualizing the results:

And here we see that P/E rates move downward in a subexponential way as discount rates increase, and vice versa — assuming that expected earnings growth remains the same (which is often not the case).

P/E Ratios are Speaking to You

What is important about this idea, and slicing it in different ways, is that P/E ratios are telling you something about what the market expects. From there, we can ask ourselves, is this reasonable? Do I agree with this expectation?

Isolating each angle can help us understand the magnitude of the affect of a particular variable. For example, moving from a P/E ratio of 200 to 150 only implies a decrease from 60% growth to about 55% growth. However, moving from 200x earnings to 150x earnings means a price drop of 25%. This is an exponential affect: a lowering of growth by 8% means a lowering of price by 25%.

For more extreme scenarios, we might seriously question whether the market is overestimating (or understimating) what might happen. I’m not aware of a company that averaged 60% compounding earnings growth over a 10-year period, but that is what a P/E ratio of 200 implies! And, as we just mentioned, there is a lot of price risk in a small adjustment of expectations.

Of course, there are other things going on, too. Movement in discount rates implies a change in P/E ratios, all else equal. Of course, all else is rarely equal, so think about all the angles.

All that said, I’ve included the full code below so you can play with your own expectations and see how their changes might affect price multiples in the company you care about.

But, P/E ratios are speaking to you. You can hear them if you know how to listen.

Full Code

import numpy as np
import pandas as pd
from scipy.optimize import minimize
import matplotlib.pyplot as plt

# Define Price Function
#  Inputs the Growth Rate expected, the discount rate, and the time horizon
#  Outputs the expected Price/Earnings ratio
def price_function( growth_rate, discount_rate, time ):
    cashflows = [] # Prime the cashflows variable
    for t in range(1, time+1): # Build discounted cashflows over the time interval
        cashflows.append( (1 + growth_rate)**t / (1 + discount_rate)**t )
    return sum( cashflows )

# Create a function that we can minimize
def solver_function( growth_rate ):
    return ( PE - price_function( growth_rate[0], discount_rate, time ) )**2

# Input the known variables
discount_rate = 0.045
time = 15
PE = 20

# Now we iterate through various P/E ratios to determine what growth rate the 
# market expects
pe = list( range(1,250+1) )
g_15 = []
g_10 = []
for i in range(0, len(pe)):
    PE = pe[i]
    time = 15
    g_15.append( minimize( solver_function, 0.09 ).x[0] )
    time = 10
    g_10.append( minimize( solver_function, 0.09 ).x[0] )
 
# Create visualization

# Analysis of the discount rate
dr = [0.025, 0.045, 0.065] # Test various levels of discount rate
# Create an empty array with pe in rows and discount rates in columns
g_15 = np.empty((len(pe), len(dr)), dtype = float) 
g_10 = np.empty((len(pe), len(dr)), dtype = float)

# Iterate through different discount rates
for j in range(0, len(dr)):
    discount_rate = dr[j]
    # Iterate through pe
    for i in range(0, len(pe)):
        PE = pe[i]
        time = 15
        g_15[i,j] = minimize( solver_function, 0.09 ).x[0]
        time = 10
        g_10[i,j] = minimize( solver_function, 0.09 ).x[0]

# Create Visualization

# Analyze how discount rates affect P/E ratios
dr = np.linspace(0.001, 0.100, num = 100) # Various discount rates
gr = [0.10, 0.15, 0.20, 0.25] # Various Growth rates
pe = np.empty( (len(dr), len(gr)) ) # Empty array with rows as dr and columns as gr

for g in range(0, len(gr)):
    for d in range(0, len(dr)):
        pe[d, g] = price_function( gr[g], dr[d], 10 )

# Create Visualization

This document is a general communication being provided for informational purposes only. It is educational in nature and not designed to be taken as advice or a recommendation for any specific investment product, strategy, plan feature or other purpose in any jurisdiction, nor is it a commitment from Directional Advisors to participate in any of the transactions mentioned herein. Any examples used are generic, hypothetical and for illustration purposes only. This material does not contain sufficient information to support an investment decision and it should not be relied upon by you in evaluating the merits of investing in any securities or products. In addition, users should make an independent assessment of the legal, regulatory, tax, credit, and accounting implications and determine, together with their own financial professionals, if any investment mentioned herein is believed to be appropriate to their personal goals. Investors should ensure that they obtain all available relevant information before making any investment. Any forecasts, figures, opinions or investment techniques and strategies set out are for information purposes only, based on certain assumptions and current market conditions and are subject to change without prior notice. All information presented herein is considered to be accurate at the time of production, but no warranty of accuracy is given and no liability in respect of any error or omission is accepted. It should be noted that investment involves risks, the value of investments and the income from them may fluctuate in accordance with market conditions and taxation agreements and investors may not get back the full amount invested. Both past performance and yields are not reliable indicators of current and future results.

Exit mobile version
%%footer%%