Return Driver | Category | Core Idea | How it is measured | Ideal Values are… |
---|---|---|---|---|
High EBIT / EV | Growth | Earnings before interest and taxes relative to enterprise value | EBIT divided by enterprise value | High |
FCF/Price | Value | Free cash flow relative to stock price | Free cash flow divided by stock price | High |
Cash/Assets | Value | Proportion of assets held in cash | Cash divided by total assets | High |
Inventory Change | Fundamentals | Efficiency of inventory management | Change in inventory over a period | High |
Asset Turnover | Fundamentals | Efficiency of asset utilization | Revenue divided by average assets | High |
ROE | Fundamentals | Profitability relative to shareholder equity | Net income divided by shareholder equity | High |
ROA | Fundamentals | Profitability relative to total assets | Net income divided by total assets | High |
FCF Per Share | Fundamentals | Amount of free cash flow generated per share | Free cash flow divided by number of shares | High |
EBITDA Margin | Fundamentals | Operating profitability excluding certain expenses | EBITDA divided by revenue | High |
ROCE | Fundamentals | Efficiency of capital employed | Earnings before interest and taxes divided by capital employed | High |
Momentum | Technical/Price | Price trend indicating continued performance in the same direction | Rate of change in price over time | High |
Low Beta | Technical/Price | Lower beta compared to market | Measure of systematic risk relative to market | Low |
Low Vol | Technical/Price | Lower volatility compared to market | Measure of standard deviation of returns | Low |
Price/Sales | Technical/Price | Ratio of market capitalization to total sales | Market capitalization divided by total sales | High |
For each of these return drivers above, I rank all companies in the S&P 500 from best to worst and go long the top 10, rebalancing each month. For example for the first return driver - EBIT / EV - every month I am ranking companies based this ratio and because the “Ideal Values” are high values, I sort companies by EBIT/EV from high to low and go long the “best” 10.
The investment universe is companies in the S&P 500 at the given time in the backtest, who have at least 1 year of price data, and who are not in the top 10% of firms ranked by Beta. There’s evidence to suggest that extremely high beta firms generally don’t do well in the long run so I filter those out across all tests. The backtest periods are from 1 January 2000 to 1 July 2023. I won’t be sharing the nitty gritty details of these factors and their construction but the outcomes in general are indicative I think…
Avg. Ann. Return | Avg. Ann. Std | Annual Sharpe | Worst Loss 1Y | Winning Years | |
---|---|---|---|---|---|
Inventory Change | 10.30% | 20.50% | 0.50 | -52.11% | 79.17% |
Asset Turnover | 11.52% | 14.74% | 0.78 | -29.84% | 87.50% |
ROE | 11.42% | 17.08% | 0.67 | -25.21% | 79.17% |
ROA | 9.90% | 19.56% | 0.51 | -49.22% | 83.33% |
EBIT/EV | 9.32% | 25.21% | 0.37 | -52.24% | 75.00% |
FCF Per Share | 12.92% | 29.92% | 0.43 | -96.46% | 79.17% |
EBITDA Margin | 8.76% | 23.35% | 0.38 | -62.64% | 70.83% |
FCF/Price | 10.34% | 29.09% | 0.36 | -70.58% | 62.50% |
Low Beta | 8.87% | 11.03% | 0.80 | -23.18% | 83.33% |
ROCE | 7.36% | 17.63% | 0.42 | -54.32% | 83.33% |
Momentum | 7.37% | 24.29% | 0.30 | -77.60% | 75.00% |
Low Vol | 10.17% | 11.43% | 0.89 | -13.87% | 75.00% |
Cash/Assets | 8.95% | 24.97% | 0.36 | -73.99% | 70.83% |
Price/Sales | 10.35% | 28.25% | 0.37 | -71.79% | 75.00% |
Of course if you were to implement these yourself, I recommend doing your own research (standard “This is not financial advice” disclaimer here). It’s also important to reiterate that these are 10-position long only portfolios so your mileage will vary if you add more stocks.
]]>Let’s say for example that you’re a hedge fund manager who employs traders or portfolio managers with superior stock picking skill, and whose returns have low - or no - correlation with the market. Furthermore, you may say to yourself “not only do I want returns which are materially different or uncorrelated to the market, I also want their returns to be uncorrelated to the well known risk premiums like Momentum”. Factors are essentially risk premiums, and risk premiums hypothesise that if you take a certain risk, you should get a certain compensation for it. And as a hedge fund manager, you’re not compensating these people in return for just getting you exposure to well-known returns! You want returns which are not explainable by the market’s returns or the well known risk premiums, and this “un-explainable” return is often referred to as “alpha”.
Now, let’s think about the opposite perspective of someone who might want to prove that they are exposed to these factors. Imagine you work for an asset manager that issues and oversees a myriad of exchange-traded funds and mutual funds, all designed to mimic the returns closely aligned with factors like Value, Size, Momentum. Your clients might use your funds to diversify their holdings or perhaps because they see tactical opportunities to “time” their exposure to a specific factor. Imagine that someone raises concerns about one of your funds—the “US Value ETF.” They’re worried that it’s “beta” exposure to the Value factor hypothetical returns are not sufficiently significant. This can be due to a poorly specified investment approach, or some other effect such as style drift. This situation will likely prompt you t o seek out multiple avenues—both qualitative and quantitative—to validate that your fund is replicating Value returns as intended.
In both these scenarios, you might perform a factor regression to determine whether or not the returns of a portfolio or stock have significant exposure to one or more risk factors.
There are - of course - other reasons, such as wanting to control our risk exposure in general for risk management purposes. But let’s play with these two scenarios for now.
Although the two scenarios above explain why we might want to measure factor exposure, we haven’t been precise on what we’re measuring yet. Let’s quickly revisit the Fama French Three Factor model’s arithmetic…
\[R_{i,t} - R_{f,t} = \beta_{i} \times (R_{M,t} - R_{f,t}) + s_{i} \times SMB_{t} + h_{i} \times HML_{t} + \epsilon_{i,t}\]where:
In general, this model is asserting that it can explain all asset price returns. It’s saying that all returns ($R_{i,t} - R_{f,t}$) are made up of some amount ($\beta_{i}$) of market return ($R_{M,t} - R_{f,t}$), some amount ($s_{i}$) of Size return ($SMB_{t}$), and some amount ($h_{i}$) of Value return ($HML_{t}$), plus some random variation ($\epsilon_{i,t}$) that can be positive or negative but that averages out to be zero in the long run. But that contradicts what our hedge fund manager wants, which is returns which are not-explainable by a model like this. We can add a term called “alpha” into the model to reflect this…
\[R_{i,t} - R_{f,t} = \alpha_{i} + \beta_{i} \times (R_{M,t} - R_{f,t}) + s_{i} \times SMB_{t} + h_{i} \times HML_{t} + \epsilon_{i,t}\]where:
The alpha ($\alpha_{t}$) term that we just added is going to measure returns that are not explainable by this model. The Three Factor model kind of always had this term, but given that the model claims to be able to explain all returns, the model claims that the value of $\alpha$ is zero, so it is simply not shown. So the task for the hedge fund manager is to measure their trader’s alpha $\alpha$ and make sure that it ISN’T zero. If it turns out to be zero, or some number that’s not significantly different to zero, then all their returns are explained by the Three Factor model and they should be fired. In short - they will want to validate that their trader/PM has positive and significant alpha.
Our asset manager will want to measure a different thing. They will want to make sure that their returns do indeed have some amount of factor exposure. In our example, they will want to make sure that their returns are comprised of some amount ($h_{i}$) of the Value factor ($HML_{t}$). They will also want to make sure that the exposure coefficient to Value is statistically significant - it’s not good enough for their returns to be sort of exposed to the Value factor - we have to show that it has a statistically significant exposure. In short - they will want to validate that their fund has positive and significant beta to the Value factor.
We will use Ordinary Least Squares regressions to measure these values. There are more rigorous ways to specify and explain tests, but I’ll save it for another statistics-focused post which will have a bit more mathematical rigour.
To perform a factor regression, we need factor return data, and stock or portfolio data. Let’s start with some really simple examples and some boilerplate python code to gather data for stocks & etfs, as well as some Factor returns data from Ken French’s data library…
# Get the monthly log-returns for a given ticker from Yahoo Finance
def get_stock_log_returns(ticker):
data = yf.download(ticker, interval='1d', progress=False)['Close']
data = data.resample('1m').last().iloc[:-1]
log_returns = np.log(data.pct_change()+1).dropna()
log_returns.name = ticker
return log_returns
# Get the monthly log-returns from Ken French's Data Library
def get_ff_data(data, start='1-1-1960'):
factor_data = pdr.get_data_famafrench(data, start)[0]
factor_data.index = (factor_data.index.to_timestamp() + MonthEnd(0)).date
factor_data.index = pd.to_datetime(factor_data.index)
return factor_data
# Align & merge the Yahoo Finance and Factor returns dataframes
def merge_stock_and_ff_data(stock_log_rets, factor_data):
return pd.concat([stock_log_rets*100, factor_data], axis=1).dropna()
# Do all the steps above in one go
def gather_stock_factor_data(ticker='AAPL', factor_data='F-F_Research_Data_5_Factors_2x3'):
stock_data = get_stock_log_returns(ticker)
ff_data = get_ff_data(factor_data)
merged_data = merge_stock_and_ff_data(stock_data, ff_data)
return merged_data
So for example if I run gather_stock_factor_data('AMZN')
I will get a dataframe that looks like this…
AMZN | Mkt-RF | SMB | HML | RMW | CMA | RF | |
---|---|---|---|---|---|---|---|
2023-02-28 | -9.03 | -2.58 | 0.69 | -0.78 | 0.9 | -1.4 | 0.34 |
2023-03-31 | 9.18 | 2.51 | -7.01 | -9.01 | 1.92 | -2.29 | 0.36 |
2023-04-30 | 2.07 | 0.61 | -2.56 | -0.03 | 2.31 | 2.85 | 0.35 |
2023-05-31 | 13.41 | 0.35 | -0.43 | -7.8 | -1.76 | -7.2 | 0.36 |
2023-06-30 | 7.8 | 6.46 | 1.33 | -0.2 | 2.2 | -1.75 | 0.4 |
So I have data on a stock - Amazon (AMZN), and the Factor returns for the same periods in the other columns. I now need to perform an Ordinary Least Squares regression to measure the beta coefficients for each of the risk factors, and the alpha term that we talked about in the previous section. We can do this in python using Statsmodels and the following function…
def point_in_time_regression(ticker, start_date='1960-01',
end_date=datetime.datetime.now().date()):
merged_data = gather_stock_factor_data(ticker)
merged_data = merged_data.loc[start_date:end_date]
endog = merged_data[ticker] - merged_data.RF.values
exog_vars = [item for item in list(merged_data.columns) if item not in [ticker, 'RF']]
exog = sm.add_constant(merged_data[exog_vars])
ff_model = sm.OLS(endog, exog, ).fit()
ff_model = ff_model.get_robustcov_results(cov_type='HAC', maxlags=1)
print(ff_model.summary())
# Plot Partial Regression Plot:
fig = sm.graphics.plot_partregress_grid(ff_model, fig = plt.figure(figsize=(12,8)))
plt.show()
Let’s test it out on AAPL using the Three Factor model, and using data starting in the year 2005 and see what we get…
point_in_time_regression(
ticker='AAPL',
factor_data='F-F_Research_Data_Factors',
start_date='2005'
)
There are a lot of figures here but the important ones are listed in the middle panel here…
The rows of this panel are the explanatory variables that we discussed previously. “const” is short for “constant” which is another way of referring to the $\alpha$ term that we spoke about earlier. Mkt-RF, SMB, HML have also been explained earlier in this post. The values in the columns merit a little more explanation…
So plugging these values into our Three Factor model… this regression claims the following…
\[R_{AAPL,t} - R_{f,t} = \alpha_{AAPL} + \beta_{AAPL} \times (R_{M,t} - R_{f,t}) + s_{AAPL} \times SMB_{t} + h_{AAPL} \times HML_{t} + \epsilon_{AAPL,t}\] \[R_{AAPL, t} - R_{f, t} = 1.1152 + 1.3390 \times (R_{M,t} - R_{f,t}) -0.3852 \times SMB_{t} - 0.6975 \times HML_{t} + \epsilon_{i,t}\]Some high level statements we can draw from the regression are…
From what we know about Apple, that was probably expected. Let’s see how Berkshire Hathaway - Warren Buffett’s value-investing focused company - looks…
Some high level statements about Berkshire Hathaway might be…
At the beginning of the article, we outlined a hypothetical scenario in which we as an asset manager were getting concerning feedback that our “US Value ETF” wasn’t tracking the Value factor performance sufficiently well. We could use what we’ve learned above to examine our own fund’s exposure to the Value Factor. Let’s look at the “baseline” which might be the S&P 500 index…
The S&P 500 index has a 0.0181 beta coefficient to the “value” factor, and the P>|t| value implies that there’s a 6% likelyhood that this is purely by chance. So with this in mind as a “baseline”, let’s look at what we see when we examine the Blackrock’s MSCI USA Value ETF…
So here we can see that the Value factor exposure is dramatically different to the S&P 500 index - we see a beta coefficient of 0.4384 and which is strongly statistically significant. So over the long run we can safely say that this ETF exposes its owners to the Value factor (which we want). We can go further and do a full sample dot plot on each of the regressors…
In the bottom right panel numbered #4 we can see that the line drawn through the scatter plot points upwards from left to right (positive relationship) and has an angle (slope) that moves upwards significantly. This is what we would want to see if we wanted to prove that our fund as positive & significant exposure to a factor or regressor.
We may want to get an idea however as to how this beta or exposure varies through time. We can see that the 25th percentile exposure during the period was 0.379 and the 75th percentile exposure was 0.498. That might be nice to see in the table but I always like to see things visually if possible. Let’s write some code that will plot graphs of the rolling 5-year beta coefficients to each of our regressors (one of which is Value) over time…
def rolling_regression(ticker, window=60, factor_data='F-F_Research_Data_5_Factors_2x3',
start_date='1960-01', end_date=datetime.datetime.now().date()):
merged_data = gather_stock_factor_data(ticker,factor_data=factor_data)
merged_data = merged_data.loc[start_date:end_date]
endog = merged_data[ticker] - merged_data.RF.values
exog_vars = [item for item in list(merged_data.columns) if item not in [ticker, 'RF']]
exog = sm.add_constant(merged_data[exog_vars])
rols = RollingOLS(endog, exog, window=window)
rres = rols.fit()
print('Most recent (ending) Beta Coefficients\n\n',rres.params.iloc[-1])
fig = rres.plot_recursive_coefficient(variables=exog_vars, figsize=(10,18))
So if we run this on ‘VLUE’ we will get the following…
So interestingly we can see that over this period of time, the 5-year beta to “Value” increased from 0.2 in 2018 to 0.5 in 2023. A longer lookback might give some context as to why this might have occurred, but for now we should be satisfied to see these data in a time series format.
So now that we’ve learned how to measure factor exposure, we can confirm that our randomly picked ETF - VLUE - does indeed have exposure to the Value factor. Our hypothetical scenario is only one trivial example of how we might make use of factor regressions in the real world. We can use the practice to validate, or reject, the idea that a fund or investment strategy has exposure to a traditional risk factor. In some other cases, we might be performing this analysis expecting (or hoping) the exposure to be small and insignificant, which might imply that our investment outcomes are distinct and separate from other risk factors.
The code for this post is available on github here.
]]>One of the main sources of data for the “traditional” set of risk factors is Ken French’s “Data Library” website. Ken - as you may remember from the previous post - is the co-creator of the “Fama-French Three Factor Model” alongside Eugene Fama. Ken provides a great service to the finance world by curating and offering these data for general use - his data library is used regularly by academics and practitioners alike. Ken’s site offers data in the form of text files which provide daily, or monthly returns.
In order to make the gathering of these data a bit more convenient, we will access these data via the “getFamaFrenchFactors” python module.
# Installation
pip install getFamaFrenchFactors
# Sample Usage
import getFamaFrenchFactors as gff
# Get the Fama-French three factor model (monthly data)
df_ff3_monthly = gff.famaFrench3Factor(frequency='m')
# Get the Fama-French three factor model (annual data)
df_ff3_annual = gff.famaFrench3Factor(frequency='a')
This module just provides a convenient way of capturing data from Ken’s website. In the event that you want to calculate the factor returns yourself - and if you have a WRDS account, you can use the famafrench module. But for this post we’ll just take the pre-prepared data from Ken’s website.
To recap, the Fama-French Three Factor model aims to explain stock returns using three^{1} primary risk factors: market return, the “size” or “SMB” factor return, and the “value” or “HML” factor return. These factors, along with some random noise, collectively account for the fluctuations in stock returns. The model suggests that each stock’s return is influenced by a combination of these three factors to differing extents.
\[R_{i,t} - R_{f,t} = \beta_{i} \times (R_{M,t} - R_{f,t}) + s_{i} \times SMB_{t} + h_{i} \times HML_{t} + \epsilon_{i,t}\]where:
We can get all the data for the Three Factor model by using the getFamaFrenchFactors
module:
import getFamaFrenchFactors as gff
df_ff3_monthly = gff.famaFrench3Factor(frequency='m')
df_ff3_monthly.set_index('date_ff_factors', inplace=True)
Let’s see what the most recent 10 rows look like by doing df_ff3_monthly.tail(10)
…
date_ff_factors | Mkt-RF | SMB | HML | RF |
---|---|---|---|---|
2022-09-30 00:00:00 | -0.0935 | -0.0079 | 0.0006 | 0.0019 |
2022-10-31 00:00:00 | 0.0783 | 0.0009 | 0.0805 | 0.0023 |
2022-11-30 00:00:00 | 0.046 | -0.034 | 0.0138 | 0.0029 |
2022-12-31 00:00:00 | -0.0641 | -0.0068 | 0.0132 | 0.0033 |
2023-01-31 00:00:00 | 0.0665 | 0.0502 | -0.0405 | 0.0035 |
2023-02-28 00:00:00 | -0.0258 | 0.0121 | -0.0078 | 0.0034 |
2023-03-31 00:00:00 | 0.0251 | -0.0559 | -0.0901 | 0.0036 |
2023-04-30 00:00:00 | 0.0061 | -0.0334 | -0.0003 | 0.0035 |
2023-05-31 00:00:00 | 0.0035 | 0.0153 | -0.078 | 0.0036 |
2023-06-30 00:00:00 | 0.0646 | 0.0155 | -0.002 | 0.004 |
So we have a big dataframe - each row represents the end-of-month return, and the columns in order represent…
Conceptual basis: Small companies tend to yield higher returns compared to large companies. Consequently, adopting a strategy of purchasing small companies while selling larger companies short should yield favourable returns. This rationale gives rise to the terminology “small minus big” or “SMB.”
Potential explanatory theories include:
Lets get the monthly returns for the Size factor and plot it to see visually how it looks…
# Filter on the SMB column and plot a cumulative return line chart
df_size = df_ff3_monthly['SMB']
df_size.cumsum().plot(title='SMB Factor Cumulative Returns')
# Print some performance metrics
annual_volatility = df_size.std()*(12**0.5)
mean_annualized_return = df_size.mean()*12
print(f"Cumulative Return: {round(df_size.sum()*100, 2)}%\
\nMean Annual Return: {round(mean_annualized_return*100, 2)}%\
\nAnnualised Volatility: {round(annual_volatility*100, 2)}%\
\nAnnual Sharpe Ratio: {round(mean_annualized_return/annual_volatility, 2)}")
Cumulative Return: 219.53%
Mean Annual Return: 2.26%
Annualised Volatility: 10.98%
Annual Sharpe Ratio: 0.21
So this is some numerical and visual information on the returns of the “Size” factor. I don’t want to make you re-read the same python code so I am going to make this into a function which we will reuse several times…
def show_me_factor_info(factor, df):
df_single_factor = df[factor]
df_single_factor.cumsum().plot(title='{} Factor Cumulative Returns'.format(factor))
annual_volatility = df_single_factor.std()*(12**0.5)
mean_annualized_return = df_single_factor.mean()*12
print(f"Cumulative Return: {round(df_single_factor.sum()*100, 2)}%\
\nMean Annual Return: {round(mean_annualized_return*100, 2)}%\
\nAnnualised Volatility: {round(annual_volatility*100, 2)}%\
\nAnnual Sharpe Ratio: {round(mean_annualized_return/annual_volatility, 2)}")
# Usage Example
show_me_factor_info('SMB', df_ff3_monthly)
Conceptual basis: Inexpensively valued companies tend to generate higher returns than their pricier counterparts.
Potential explanatory theories include:
show_me_factor_info('HML', df_ff3_monthly)
Output
Cumulative Return: 395.84%
Mean Annual Return: 4.08%
Annualised Volatility: 12.38%
Annual Sharpe Ratio: 0.33
The Carhart Four Factor Model builds upon the foundation of the Fama-French Three Factor model by introducing “Momentum” as an additional explanatory factor. This expansion involves incorporating Momentum into the existing framework and was exemplified in Mark Carhart’s 2012 paper titled “On Persistence in Mutual Fund Performance.”
\[R_{i,t} - R_{f,t} = \beta_{i} \times (R_{M,t} - R_{f,t}) + s_{i} \times SMB_{t} + h_{i} \times HML_{t} + u_{i} \times UMD_{t} + \epsilon_{i,t}\]where:
If you contrast this with the preceding section, you’ll observe the addition of a new component in the equation, denoted as “UMD,” signifying Up Minus Down. This element encapsulates the returns associated with owning companies whose stock prices have risen (winners) versus the returns of companies whose stock prices have fallen (losers). This phenomenon is commonly recognized as “Momentum,” reflecting the upward or downward momentum in stock prices. The pioneering paper on Momentum is “Returns to Buying Winners and Selling Losers” authored by Jegadeesh and Titman, published in 1993.
Underlying thinking: Companies that have performed well recently will continue to perform well in the near future
Potential explanatory theories include:
df_c4f_monthly = gff.carhart4Factor(frequency='m')
df_c4f_monthly.set_index('date_ff_factors', inplace=True)
show_me_factor_info('MOM', df_c4f_monthly)
Cumulative Return: 726.44%
Mean Annual Return: 7.53%
Annualised Volatility: 16.31%
Annual Sharpe Ratio: 0.46
While Momentum has exhibited robust long-term performance, it’s important to acknowledge that this factor is susceptible to significant crashes. If we take a step back and examine the data, we can identify instances of these substantial downturns, notably around 1929 and 2009. It’s worth noting that on the logarithmic scale of the chart, these crashes might appear less severe than they truly were. To gain a clearer perspective, let’s reassess the chart by depicting the losses over time as a percentage of the peak value, commonly referred to as the “Max Drawdown.”
## Turn Log Returns into Simple Returns
import numpy as np
mom_simple_returns = (np.exp(df_c4f_monthly['MOM'])).fillna(1)
cumulative_reinvested_return = mom_simple_returns.cumprod()
# Plot the Max Drawdown time series
((cumulative_reinvested_return - cumulative_reinvested_return.expanding().max())/
(cumulative_reinvested_return.expanding().max())*100).plot(title='MOM Max Drawdown in %')
A commonly held notion suggests that a maximum drawdown of around 30% is generally considered tolerable for investors with a reasonable risk appetite. However, it’s important to acknowledge that this is largely anecdotal and lacks definitive scientific evidence—it’s more of a rule of thumb. Evaluating the max drawdowns for the Momentum factor, the period from 1950 to 2008 appears relatively manageable. In contrast, the drawdowns observed prior to and following this time frame are notably deep, with the prospect of experiencing a rapid 50% loss over a few months being particularly unpleasant. This underscores one of the principal risks inherent in Momentum investing—namely, the potential for significant crashes. Due to the operational mechanics of Momentum strategies, recovery from such crashes often demands a considerable amount of time.
In 2015, Eugene Fama and Ken French published an extension of their Three Factor model which includes two new factors…
So now we have to update our arithmetic again to account for the two new explanatory factors…
\[R_{i,t} - R_{f,t} = \beta_{i}(R_{M,t} - R_{f,t}) + s_{i}SMB_{t} + h_{i}HML_{t} + p_iRMW_{t} + g_iCMA_{t} + \epsilon_{i,t}\]where:
Although the addition of these two factors filled some gaps in the literature, some academics and practitioners had mixed views on the efficacy of the Five Factor model. Robeco - a large institutional asset manager specialising in factor-based investing, among other approaches - noted surprise that Momentum was not formally included as a factor, leaving it to be covered by Carhart’s model, especially given that it had so much explanatory power. Others noted that the existence of the Low Volatility factor (a non-traditional factor which will be explored in a later post) which directly contradicts the existing Market Risk Premium factor present in both the three and five factor models has not been dealt with. Nevertheless, despite these critiques, the Five Factor model’s incorporation of the “Profitability” and “Investment” factors represented an enhancement over the original Three Factor model, even in light of its inherent limitations.
Suggestion: Companies with higher profit margins earn higher returns than those with lower profit margins
Potential explanatory theories include:
df_ff5f_monthly = gff.famaFrench5Factor(frequency='m')
df_ff5f_monthly.set_index('date_ff_factors', inplace=True)
show_me_factor_info('RMW', df_ff5f_monthly)
Cumulative Return: 204.1%
Mean Annual Return: 3.4%
Annualised Volatility: 7.69%
Annual Sharpe Ratio: 0.44
Suggestion: Companies who are re-investing a lot earn higher returns than those are a not
Potential explanatory theories include:
show_me_factor_info('CMA', df_ff5f_monthly)
Cumulative Return: 200.32%
Mean Annual Return: 3.34%
Annualised Volatility: 7.21%
Annual Sharpe Ratio: 0.46
At this point, you might notice something interesting. Both the Profitability and Investment factors perform well during times of market stress. Let’s plot them beside the general Market return and zoom in on the 1999 to 2022 period…
title = 'CMA/RMW Returns vs. Market Returns 1999 to 2022'
df_ff5f_monthly[['CMA', 'RMW', 'Mkt-RF']].loc['1999':'2022'].cumsum().plot(title=title)
Visually we can see that during the Dot com bubble and poor performance thereafter (2000 to 2003) the market performed poorly whereas RMW and CMA did quite well. Likewise we see a similar trend in 2007 to 2009 and 2022. We can see that the correlations of monthly returns for RMW and CMA against the Market return for this slice of time are negative at -0.35 and -0.26 respectively…
df_ff5f_monthly[['CMA', 'RMW', 'Mkt-RF']].loc['1999':'2022'].corr()
CMA | RMW | Mkt-RF | |
---|---|---|---|
CMA | 1 | 0.252842 | -0.264515 |
RMW | 0.252842 | 1 | -0.349071 |
Mkt-RF | -0.264515 | -0.349071 | 1 |
Behaviourally we could come up with some explanations for this…
In the next post, we’ll look at various approaches to performing factor regressions, which should illustrate the reason why these factors are so useful in explaining the sources or drivers of returns for investors. In the post after that, we’ll look at some “non-traditional” investment factors and talk about how to make sense of the “Factor Zoo”.
The code for this post is available on github here.
Technically four factors if you include the Risk Free Rate as a “factor”. It’s certainly time-varying but in general its not included as a risk factor because there’s no variation in how much the risk free rate impacts each stock. In more technical terms, market, size and value factors are factors because their coefficients vary in the cross-section of returns, whereas the risk free rate’s coefficient is always 1. ↩
In general the Risk Free return is either the Effective Federal Funds Rate or some similar short duration deposit facility. In past experience I’ve seen people use the US 10 Year Treasury Bond Yield as a risk-free rate, but that is by no means risk free. In general a risk-free rate could be defined differently for each investor based on what investments they have access to, their holding period, their geographic location, and other such factors. ↩
By focusing on specific factors, investors can potentially benefit from diversification and risk reduction, as well as potentially higher returns. For instance, the Small Size factor has historically outperformed the overall market, while the Value factor has exhibited long-term out-performance compared to Growth. By constructing a portfolio based on these factors, investors can potentially generate higher returns while mitigating some of the risks associated with investing in a single market.
Factor portfolios are a popular investment strategy used by both institutional and individual investors. They are often used in conjunction with other investment strategies and can be tailored to meet specific investment objectives. Overall, factor investing provides investors with a powerful tool to enhance their returns and better manage risk in their portfolios.
One of the fundamental concepts in finance is the Capital Asset Pricing Model (CAPM), which suggests that assets are priced based on their level of risk relative to the overall market. The model is expressed as follows:
\[R_{i,t} = R_{f} + \beta_{i} \times (R_{M} - R_{f})\]This equation states that the return on any investment $i$ at time $t$ is equal to the Risk-Free Rate of Return $R_{f}$ plus a coefficient $\beta$ that measures the investment’s level of risk relative to the market, which is given by the market’s excess returns above the risk-free rate $(R_{M} - R_{f})$.
While the CAPM has theoretical appeal, it has been subject to empirical challenges, as evidenced by the following:
Despite these challenges, William Sharpe was awarded the Nobel Prize in Economics in 1990 for his contributions to the development of the CAPM. While the model has limitations, it remains an important tool for understanding how asset prices are determined in finance.
The Fama-French 3 and 5 Factor models extend the CAPM and turn it into - what is essentially - a “multi-factor” model, vs. the CAPM which is a “single factor” model. Eugene Fama & Ken French suggest that…
\[R_{i,t} - R_{f,t} = \beta_{i} \times (R_{M,t} - R_{f,t}) + s_{i} \times SMB_{t} + h_{i} \times HML_{t} + \epsilon_{i,t}\]where:
In words; the model asserts that the return on any investment $i$ at time $t$ is equal to some fixed “alpha” return, plus some coefficients $\beta$ of the market’s excess returns as before, as well as some coefficient of the “size premium” and “value premium”, plus or minus some noise given by $\epsilon_{i,t}$.
The Size Premium is a phenomenon observed in the stock market where smaller companies tend to outperform larger companies over the long term. This effect is not a guarantee, but it is supported by empirical evidence. The rationale behind this premium is that smaller companies have greater growth potential compared to larger, more established companies. As a result, investors demand a higher return for investing in smaller companies due to their higher volatility.
The Value Premium is another well-documented anomaly in the stock market where companies with lower price-to-book ratios tend to outperform companies with higher price-to-book ratios. This anomaly can be explained by the market’s tendency to overestimate the growth potential of expensive companies and underestimate the growth potential of cheaper companies. Value investors often look for stocks that are trading at a discount to their intrinsic value, and this strategy has been popularized by legendary investor Warren Buffett.
Therefore, it is not accurate to say that the Size Premium implies that you should get lower expected returns for investing in Big Companies vs. Small Companies or that the Value Premium implies that you should get lower expected returns for investing in Expensive Companies (relative to Book Value) vs. Cheap Companies (relative to Book Value). Rather, both premiums suggest that investing in smaller and cheaper companies can lead to higher expected returns over the long term, but this is not a guarantee and investors should carefully consider their investment goals and risk tolerance before making any investment decisions.
The Model was later extended to include 2 more factors…
Eugene Fama won a Nobel Prize for this too.
The Fama French model has been instrumental in advancing our understanding of asset pricing and has provided a framework for researchers to identify new factors that may explain asset returns. However, the proliferation of new factors has led to concerns about data mining and overfitting, where researchers may identify spurious relationships that do not hold up in out-of-sample testing.
While some factors such as Betting Against Beta, Low Volatility, and Momentum have been widely accepted and implemented in investment strategies, the sheer number of research papers on new factors has led to a “factor zoo” of sorts. This has caused some academics in Finance to feel embarrassed as it has become more of a race to publish new papers on novel factors for the sake of citation counts, rather than advancing our understanding of asset pricing.
It is true that some researchers may have engaged in data mining to find relationships between accounting metrics and future returns, but it is important to note that legitimate research on new factors can provide valuable insights into the behaviour of financial markets. Nonetheless, investors should be cautious when considering new factors and should rely on a thorough understanding of the underlying economic rationale and robust out-of-sample testing before implementing them in their investment strategies.
Factors are designed to be market neutral. For instance, consider the Value factor, which represents the difference in returns between holding high-value companies and low-value companies. This essentially means that you pay a price in the form of lower returns for owning high-value companies over low-value companies. If we aim for higher returns, it implies that we can buy low-value companies and sell high-value companies. To construct such a portfolio, we can create two positions:
Here, “everything else” refers to the other factors in the models such as the Risk Free Rate, the Size factor, and the market return, among others. Simplifying the equation, we can write:
Portfolio Holdings = + Stocks with Low Value characteristics + everything else - Stocks with High Value characteristics - everything else
The “everything else” term cancels out, leaving us with:
Portfolio Holdings = + Stocks with Low Value characteristics - Stocks with High Value characteristics
In practice, if we go long on 10 stocks and short 10 stocks, and size the positions appropriately, we achieve a “delta neutral” position, meaning that any movement in the overall market is hedged.
Given that we’ve provided a high-level overview of the history of Factor Investing and covered some of the interesting topics in the field, in the next post we’ll conduct a review and back-testing of some of the popular factor strategies to evaluate their performance over time.
]]>One of the main benefits of using git is that it allows you to easily track changes to your code. You can see exactly what changes were made, who made them, and when they were made. Additionally, git allows you to create different branches of your code-base, allowing you to work on multiple features simultaneously without interfering with the main branch. This can save a lot of time and hassle, especially on large projects with multiple developers.
If you’re not already using git, it’s definitely worth learning and incorporating into your workflow. This post will give you a high level overview of the most common commands, which you can use as a cheat sheet once you start using it. I’ll only include one Git pun in this post, and with that warning in mind, lets git going…
On the Git website you can find installation instructions for your platform of choice here.
git config --global user.name "Firstname Surname"
sets your name.
git config --global user.email "email@address.domain"
sets your email address.
git config -l
to show all the config parameters, including the ones above.
git init
to initialises a new new git directory. If you’ve got all your code in a folder called MyCode
, you’d get started by navigating into the MyCode
folder in your terminal of choice and running git init
to apply Git’s functionality to the files therein.
git status
to show the status of changes tracked & untracked.
git add [filename]
add a file to staging. A file that’s “staged” means that when you next commit your code, the files which are staged are the ones which will be updated in the Git history. Changes in files not “staged” won’t be tracked, unless you stage them.
git restore [filename]
restores a file to its most recent committed state. Let’s say I’ve been working on a file and I’ve completely screwed it up. I hit backspace too enthusiastically perhaps and there’s a chunk of it missing, and no amount of CTRL+Z’ing is helping. git restore [filename]
will revert the given file back to its most recent committed state.
git commit
to commit staged changes. Typically when you do this, you’ll be shown a text file in which you can document the code changes you’re committing to the git repositoryGetting Started with Git. It’s really important to take time to document your changes clearly, as this can save you a lot of time down the road. How many times have you revisited code you wrote weeks or months ago and you can’t remember why it was written a certain way? Commit comments can mitigate this.
git commit -m "text"
commit changes along along with the message. This is like a shortcut to the git commit
step above, but where you just submit the headline summary of the change. Only recommended for small, or obvious changes, like adding something to your .gitignore file.
git commit -a
stage any changes from tracked files and commit in one step. This is another shortcut, where you basically are doing git add
and git commit -m
in one step.
git log
to show the list of commits and the info provided for each commit.
git show [commit ID]
show the log for a specific commit. Each git commit has an ID and are used for identification purposes.
git log --stats
show some stats regarding recent commits.
git rm [filename]
stage a change to remove/delete a file.
git mv [filename] [new_filename]
stage a rename or move of a file.
git diff --staged
show all staged files compared to the named commit.
git add -p
interactively review patches and add to the current commit.
git show -2
will show the most recent 2 commits. The number can be changed.
Oftentimes you’ll have a bunch of files in your directories that you don’t need - or don’t want - to be tracked in Git.
You can tell Git to ignore files in a directory by adding their filenames to a file called .gitignore
. You usually have to create this yourself, though.
Create an empty text file in your project directory and name it .gitignore
.
Once you have created your .gitignore
file you can tell Git to keep track of it by doing git add .gitignore
and commit it by doing git commit -m "text"
.
By adding the types of files you want to ignore (e.g. *.csv
to ignore all csv files in the directory) or more specific files using their filenames (e.g. fileToIgnore.txt
to ignore this specific file) Git will ignore them.
For example, if you were to make a change to the fileToIgnore.txt
file, Git won’t show it as a file with “untracked changes” if you do git status
.
git checkout
allows us to revert a file to a previous state, prior to it being staged or committed.
git reset HEAD [filename]
un-stages a file which has already been staged.
git commit --amend
will redo the most recent commit. This can be used in the event that something was incorrect, or missing from the most recent commit. This overwrites the most recent commit log, and thus removes some audit trail, and therefore should not be used for public/shared repos.
git revert HEAD
creates an inverse commit to the most recent one, to reverse changes. This will only revert to the most recent commit, so to revert to an earlier commit, you can do git revert [commit ID]
. Git will attempt to match on the commit ID characters provided, so you do not have to input the entire hash commit ID - typically the first five characters are sufficient.
A branch is a variant of a git repository. It is useful when trying out a new feature or a materially different behaviour, without having to work with the master branch.
You can see a list of branches by doing git branch
.
You can create a new branch by doing git branch [branch name]
.
You can switch to this branch by doing git checkout [branch name]
.
You can create a new branch and switch to it in one step by doing git checkout -b [branch name]
. You can delete a branch by doing git branch -d [branch name]
. You can forcibly do this by using a -D
flag.
Merging a branch is when you incorporate a branch into the master branch. You can merge a branch into the master branch by doing git merge [branch name]
. This can sometimes cause merge issues however. If there are merge conflicts then you can abort the merge by doing git marge --abort
.
You can see a summarised view of the commit history for a repo by doing git log --graph --oneline
.
I have some code I’ve been working on in a file called coolscript.py
in my ~/Uncentive/CoolStuff
directory. Where you might keep your own code is of course totally up to you.
(base) Uncentive[~]$ cd Coding/CoolStuff
I want to keep track of the changes I make to the script, so I am going to open my terminal and do cd ~/Uncentive/CoolStuff
to navigate to the script’s location, and do git init
to initiate a Git repo in that directory.
(base) Uncentive[~/Coding/CoolStuff]$ git init
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
Initialized empty Git repository in /home/Uncentive/Coding/CoolStuff/.git/
I know for sure that I want to keep track of coolscript.py
so I do git add coolscript.py
and commit that file to Git by doing git commit -m "Adding coolscript.py"
, and hit enter.
(base) Uncentive[~/Coding/CoolStuff]$ git add coolscript.py
(base) Uncentive[~/Coding/CoolStuff]$ git commit -m "Adding coolscript.py"
[master (root-commit) d237909] Adding coolscript.py
1 file changed, 1 insertion(+)
create mode 100644 coolscript.py
I decide actually that I hate how something in coolscript.py
works, so in my code editor I make my changes and test them successfully. coolscript.py
generates a csv file as its output, and I can now see cooloutput.csv
in the directory, because I’ve run it a bunch of times while making my changes. Back in my terminal window, I do git status
…
(base) Uncentive[~/Coding/CoolStuff]$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: coolscript.py
Untracked files:
(use "git add <file>..." to include in what will be committed)
cooloutput.csv
no changes added to commit (use "git add" and/or "git commit -a")
Given that I made changes to coolscript.py
, Git is showing me this file with the preface “modified: “. I want to stage this change to be committed later on, so I again do git add coolscript.py
and commit my changes.
(base) Uncentive[~/Coding/CoolStuff]$ git add coolscript.py
(base) Uncentive[~/Coding/CoolStuff]$ git commit -m "Changing the script"
[master 0fd9a0a] Changing the script
1 file changed, 1 insertion(+), 1 deletion(-)
Finally, I change my mind and decide actually I want to go back to the original version of coolscript.py
before I made my change. So I’m going to check out a previous version of the code. To do so, I need the ID of the commit from the history, so I do git log
and see my two commits…
(base) Uncentive[~/Coding/CoolStuff]$ git log
commit 0fd9a0aab1a955051880afc25c92c77785d88dc5 (HEAD -> master)
Author: Uncentive <Uncentive@protonmail.com>
Date: Wed Dec 28 23:38:09 2022 +0100
Changing the script
commit d237909462072c75697185ff2e49680b6f5511f7
Author: Uncentive <Uncentive@protonmail.com>
Date: Wed Dec 28 23:36:43 2022 +0100
Adding coolscript.py
The commit IDs are the long strings of letters and numbers which is referred to as a hash. I want the original one (commit 2 at 23:36:43 on Dec 28) so I copy the hash and do git checkout d237909462072c75697185ff2e49680b6f5511f7
which reverts the code in the directory to its previous state.
(base) Uncentive[~/Coding/CoolStuff]$ git checkout d237909462072c75697185ff2e49680b6f5511f7
Note: switching to 'd237909462072c75697185ff2e49680b6f5511f7'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at d237909 Adding coolscript.py
Git is such a ubiquitous tool that searching for terms like “Git intro” or “Git Cheat Sheet” will likely provide you with ample resources.
Personally I found git - the simple guide to be very beginner-friendly. For those of you who want a bit more interactivity and detail, I also recommend the Introduction to Git and GitHub Coursera course.
]]>As an employee at an investment firm, I often get asked questions like “What stocks should I buy?” and “What is a good investment right now?” While it’s flattering to be asked for investment advice, there is no easy answer. Everyone’s financial goals, circumstances, and potential withdrawal timeline (such as for retirement) are different, so it’s difficult to recommend specific stocks without knowing more about an individual’s situation. In general, it’s not ideal to invest in individual stocks, and there are other habits and practices, such as periodic rebalancing, that can be more beneficial to focus on. In this post, I will summarize some principles that can be useful for making investment decisions. I may write more in-depth posts on each of these principles in the future.
Diversification is key when it comes to investing. Don’t put all your eggs in one basket by betting on a single company’s stock, even if you think you know a lot about it. Unless you’re a high-level executive in a monopoly-run industry, you’re unlikely to have an edge. Several studies have shown that investment professionals cannot reliably beat the market; even those who have huge portfolios, lots of data, and an army of employees working for them struggle to outperform the market. Consider instead investing in an index Exchange Traded Fund (ETF^{1}) that tracks a broad set of companies instead.
Diversification is one of the few, if not the only, sure things when it comes to investing. This goes for the stocks you buy, as well as the other asset classes you mix them with. In the long run, it’s not effective or necessary to invest 100% of your money in equities (shares). Despite what you may initially think, being fully invested in equities does not necessarily yield the best financial outcome. This has been proven and reaffirmed in finance academia for decades. Investing in both bonds and equities can provide diversification, as they often move in opposite directions. When you lose money on shares, you may be able to make some money on bonds. This can be seen in the comparison of the three portfolios below…
This is what the growth of USD 10,000 looks like from 1994 to today. In general, you make the same gains (mostly) but with the addition of Bonds (the blue line), or Bonds & Gold (the yellow line) the growth is more stable; even higher during some periods. This shows up in the “Sharpe Ratio” on the table of figures, which is a metric that helps investors determine how much reward they’re getting versus how much risk they’re taking. Higher is better. You can see from the figures in the image that Equities + Bonds (0.48), or Equities + Bonds + Gold (0.49) has a higher Sharpe Ratio than just 100% Equities (0.44). This thinking of adding more assets to increase the efficiency of your portfolio comes from financial economics theory, which you can read up on if you like ^{2}. In general, it’s good to split your portfolio into asset classes, such as Equities, Bonds, and Gold. Give these assets a % allocation of your portfolio, like 10%, or 80%.
You’re now ready to start putting some money to work in the market. You’re feeling pretty good about yourself, you’ve done your research, and you’re ready to buy some shares of that ETF you’ve been reading about. But before you do, there’s one thing you need to be aware of: costs. Costs can come in all of shapes and sizes, from brokerage fees to transaction charges and more. And while they might not seem like a big deal at first glance, they can actually be a huge drag on your investment performance. Here’s why:
Let’s say you decide to buy $1,000
worth of shares in that hot new tech company. You’re feeling pretty smart, and you’re ready to watch your money grow. But before you can buy those shares, you have to pay your broker a $15
fee. So instead of investing $1,000
you’re only investing $985
. Now, let’s say you hold onto those shares for a five years and they do really well. You make 10% per year, which is a good return. But remember that $15
fee you paid upfront? That’s eating into your returns. Instead of making 61% in total for the full period, you’re only making 59%. Over time, those fees can really add up and take a big bite out of your returns. That’s just for one transaction at the very start as well!
So what can you do to avoid investing costs and make the most of your money? One option is to use a low-cost or no-cost brokerage that offers no-commission trading or has low fees. You can also consider using index funds or ETFs that track a basket of securities, rather than buying individual stocks. This can help to reduce your trading costs and diversify your portfolio.
And finally, one of the best ways to avoid investing costs is to simply hold onto your investments for the long term. The more you trade, the more fees you’ll pay. So if you can resist the temptation to buy and sell all the time, you’ll keep more of your money working for you. In the end, investing costs may not seem like a big deal at first, but they can really add up over time and eat into your returns. By being aware of these costs and taking steps to minimize them, you can help to maximize the amount of money you have invested.
Over time, the value of your portfolio’s investments may change. For example, a 60/40 allocation of equities and bonds may grow to 82/18 or even fall to 50/50. To keep your portfolio aligned with your original allocations, you should periodically rebalance your investments by buying or selling to bring them back to their original levels.
For example, if you invested $100,000
in a portfolio with 10% gold, 15% bonds, and 75% equities (like Portfolio 3 in the previous section) in 1972, and then forgot about it for 50 years, the value of your investments will have changed significantly. By 2022, your position in US equities would have grown from 75% to 95.2%, while gold and bonds would make up only 5% of your assets. This would result in a 50-year Sharpe ratio of 0.53. Your “max drawdown,” or worst loss at any point during this period, would be -44.84%, which occurred during the financial crisis from 2007 to 2009.
If you rebalance your holdings back to their original allocation percentages (10%, 15%, and 75%) once a year, you would end up with a 50-year Sharpe ratio of 0.56, which is slightly better than the 0.53 we saw earlier. Your max drawdown, however, would be much better, at only -37.85%, compared to -44.84% from before. If you were planning to retire during the 2005 to 2010 period, this difference in max drawdown could have made a significant impact to the value of your retirement fund just when you began to rely on it for income.
After choosing your assets and purchasing your ETFs, mark your calendar for when you need to check and rebalance your portfolio, and then leave it alone. Avoid checking it too frequently, as it can be stressful and counterproductive unless you are a professional investor or trader. Instead, let your portfolio do its thing. If you want to deposit more money or rebalance your portfolio, that’s fine, but otherwise, try to forget about it for a while. It’s also not necessary to keep your broker’s app on your phone unless you use it for two-factor authentication.
]]>Similarly, I have colleagues, friends and family who check their slow-moving investments - like their 401ks - on a near-daily basis.
I do this too, and although I trade several times a week at minimum, I suspect I might be checking the long-term stuff too often as well.
Checking the performance of long-term investments too often can harm your mental state, as well as induce you to make bad decisions when things get ugly. Even professional investors struggle to deal with this^{1}.
Conversely, my girlfriend could be the worlds most sanguine investor, as she rarely checks her investment performance other than when she’s actually doing something with her portfolio.
But surely being constantly up to date on your investment performance can only be a good thing, right?
Well..it’s not always that simple…
Humans exhibit a behavioral trait called Loss Aversion^{2}.
In English, this means that people in general have stronger feelings of anguish resulting from a loss than happiness resulting from a win.
Take for example a coin toss game where you win $
10 if you guess the side of the coin correctly, but lose $
10 if you guess incorrectly.
Loss Aversion implies that you’ll feel more emotional pain from losing $
10 than the comparative joy you’d feel from winning $
10.
In fact, Loss Aversion implies that for you to have the same intensity of feelings between the two outcomes, you might have to win much more (e.g. $
20), for every loss (e.g. $
10) for you to be indifferent.
This lop-sided impact arising from Loss Aversion can discourage you from holding investments for the long run, even if the odds are in your favor.
Take retirement savings accounts for example - think of a company pension plan or a 401k.
They’re designed to be long-term investments.
The returns from long-term investments are often based on “risk premiums”.
Risk premiums reliably compensate investors over long time horizons.
Like every investment, however, they fluctuate in value and encounter periods of underperformance.
To add more complexity, the “shape” of positive investment performance usually looks different from the “shape” of negative investment performance.
Most commonly, the daily returns in the types of investments in pension plans are often negatively skewed.
Using very simple figures, this means that - for example…
Over a long timeframe, this averages out to
You have “winning” days 51% of the time, and “losing” days 49% of the time
So over the long-term, you’ll average out to make about $0.05 per day.
But if you check your damn pension every day, you’re not going to experience this “long timeframe” behavior of earning $0.05 per day.
You’re going to experience the lop-sided negative skewed behavior of risk-premium-based assets.
As we learned earlier - when you observe “losing” days, they are going to impact you more than your “winning” days.
And what’s worse, is that given the negative skew of your investment, the “losing” days are going to feel a lot worse to observe^{3}.
If we define your loss aversion level as something like 10% - where you feel the pain of a loss 10% more than the same gain - it will feel like this…
So when factoring in loss aversion, if you observe each of these daily losses individually (checking your account daily), it will be difficult to rationalize that you’re making money over the long term, even if the figures speak for themselves objectively.
This is especially true when you have a sell-off in risk assets and you experience day after day of losses.
Here’s what it “feels” like to own Vanguard’s Total Stock Market ETF (VTI) over a long period of time, with this conceptual loss aversion of 10%, whether you check its performance daily, weekly, or monthly.
This is a diversified basket of equities; among the broadest and most diversified there is.
In terms of earning the Equity Risk Premium, there aren’t many better options than this.
But even worse, you’re going to feel even more pain if you experience consecutive strings of losses one after another, which have been shown to compound each other.
Let’s say that when you have a second loss in a row, your loss aversion increases to 1.21…
So even with one of the most reliable risk premiums on the planet, and with the most broadly diversified and cheapest way to access it, over a long period of time, using this naively simple Loss Aversion model, the only palatable frequency on which you should observe your results is monthly - daily and weekly feel like you’re losing money.
First of all, as long as you feel your risk is managed and that you have your ideal asset allocations - try to let your portfolio do its thing by leaving it alone.
If you rebalance your portfolio on a quarterly basis, and if you’re confident in the approach you’re using; perhaps try to only look at it at those quarterly rebalance events, and not in between.
There will of course be exceptions to the rule, and you should by no means neglect your finances, but try to slow things down if you can.
Go do something else - go outside, or think about how you can save more money, even!
That’s surely time better spend than looking at a number go up or down each day.
Haigh, Michael S., and John A. List. “Do Professional Traders Exhibit Myopic Loss Aversion? An Experimental Analysis.” The Journal of Finance 60, no. 1 (2005): 523–34. http://www.jstor.org/stable/3694846. ↩
Kahneman, Daniel, and Amos Tversky. “Prospect Theory: An Analysis of Decision under Risk.” Econometrica 47, no. 2 (1979): 263–91. https://doi.org/10.2307/1914185. ↩
Elkind, Daniel, Kathryn Kaminski, Andrew W. Lo, Kien Wei Siah, and Chi Heem Wong. “When Do Investors Freak Out? Machine Learning Predictions of Panic Selling.” Journal of Financial Data Science 4(1), 11–39. ↩
[…] using information or data in a study or simulation that would not have been known or available during the period being analyzed.
It’s important to avoid using a trading signal from $T+1$ in our backtest that we shouldn’t yet have as part of our trading actions taken on $T$. If we do, then our backtest is invalid.
An important but less-discussed benefit of backtests is that they help us determine whether we can mentally and emotionally tolerate the strategy’s volatility. If you have a strategy that’s profitable in the long run, but which has extreme short-term fluctuations, it’ll be hard to keep it running in spite of large or persistent drawdowns.
When you backtest, you can dispassionately observe the ups and downs of a strategy and contextualise its volatility versus the long-run expected return. But in reality, once you trade it live, you won’t have the luxury of foresight anymore. You’ll experience similar or worse losses “out of sample” without having the reassurance that the performance will pick up again. This puts us at risk of becoming discouraged from trading our strategy which - all things considered - might actually be great.
We could define our own variant of this risk tolerance look-ahead bias similarly to the generic definition above…
[risk tolerance look-ahead bias is the use of] information or data in a study or simulation that would not have been known or available during the period being analyzed [to assess whether a strategy’s short-term volatility aligns with our tolerance for risk].
I recently put a trend-focused strategy live. When designing the strategy I backtested it thoroughly and observed PnL graphs which looked like this one…
We’re looking at 5^{1} years of data. As you can see, there are ups and downs - slow and fast alike. Somewhere in there is a 1-day loss of over 10% of the starting capital. During another period, there’s a 100% gain followed by a sharp mean-reversion resulting in a 40% peak-to-valley loss. When you look at the graph - which shows the long(ish)-run behavior of the strategy - you might say to myself “yeah, this will be volatile, but I can stick with it because I know the long run results will be great.”
But once you’re trading live, with real money, are you sure you’d be this confident?
In my case, my strategy’s portfolio included the CME Heating Oil contract. For me that’s a big trade. At current rates it exposes the buyer (or seller) to a daily 1 standard deviation move of around $3.5k USD. That’s the expected daily 1 standard deviation of the entire strategy not including CME Heating Oil. This is a incorrectly large position for me to trade; other contracts in the strategy have the same oversized positions issue.
“But look at the long-run backtest!” I say to myself. “Sure it’s a big position and sure it swings a lot, but the long run behavior is worth it.” I was nowhere near this sanguine when I turned the strategy on in live trading and went Long CME:HO along with 5 other grown-up sized contracts…
Day 1: By 11am I’m down $2k on HO. “Well, that’s just a few hours in. I can’t determine anything based on 1 day, let alone 2 hours”.
Day 2: I check my PnL twice as often as Day 1. At 10am I’m down $3k on HO. “Ok this is starting to not be enjoyable…I guess this is how it’s going to be”. I look at the backtests again. I validate that the 95%ile 1 day VaR is x, and that a 5 standard deviation move based on the observed returns distribution is y.
Day 3: HO is flat. But I check my PnL several times per hour. I dread the idea of my portfolio having a third loss of the magnitude i’m now experiencing.
Day 4: HO has resumed selling off. I am now questioning myself. “Is my backtest actually representative?” and “What if my backtest was just a lucky period for the strategy?”. “If I could see into the future and know whether things get better, i’d happily just deal with this.”
Day 5: HO begins to sell off at lunch time. I’ve had enough - I know based on logic and my backtest that this can happen, but experiencing it first-hand is too much to bear. I sell at market and go looking for smaller contracts to replace it with.
In my experience, these three practices are a great start to avoiding this pattern:
Simulate the portfolio: Use a paper trading account for a few weeks to experience the feeling of not knowing what’s coming next. It doesn’t solve the issue entirely as we know intuitively that the PnL won’t be real, but it certainly helps.
Start MUCH smaller: In my case, I also started too big. When going live with a strategy, start as small as possible. Rather than a big CME futures contract, consider using the Mini or Micro contract, for example. Take 1-lot positions instead of 5-lot clips. Validate the expected behavior; get acquainted with the daily ebb & flow, and resolve any post-go live issues during this period.
Use “Training Wheels”: When you go live, put on a hedge for your initial set of positions for the first day or two with another asset or contract which is inversely correlated. This will allow you to be trading live at your small initial size without much risk. As you get more confident, you can reduce, or entirely unwind the hedge. Once you’re ready and comfortable, ramp up the size over time.
There are, of course, numerous other ways to not “freak out” but perhaps these three above are a good starting point for your own approach.
For a backtest, we know that 5 years is not a long time. 10+ years is ideal, with lots of varied market regimes thrown in. But for the purpose of this article, the length of the backtest isn’t the topic of discussion. ↩
From Wikipedia: A diagram representing a two-state Markov process, with the states labelled E and A. Each number represents the probability of the Markov process changing from one state to another state, with the direction indicated by the arrow. For example, if the Markov process is in state A, then the probability it changes to state E is 0.4, while the probability it remains in state A is 0.6.
The state dynamics are fully specified by:
\[A = \begin{bmatrix} a_{1,1} & ... & a_{1,N} \\ a_{i,1} & ... & a_{i,N} \\ a_{N,1} & ... & a_{N,N} \end{bmatrix}\]Since $\sum_{j}\mathbb{P}(s_t=j \mid s_{t-1=i})$, the elements of each row add up to unity:
\[a_{i,1} + ... + a_{i,N} = 1\]Let $e_i$ denote the i-th row vector of the N x N identity matrix. Let $\xi_t$ denote a 1 x N row vector that is equal to $e_i$ when the state $s_t$ is equal to i:
\[\xi_t = (0, ..., 0, 1_{i^{th}\\ element}, 0, ..., 1)\]The expectation of $\xi_{t+1}$ is a vector whose j-th element is the probability that $s_{t+1} = j$:
\[\mathbb{E}(\xi_{t+1} \mid s=i)=(a_{i,1}, ..., a_{i,N})\]We infer that $\mathbb{E}(\xi_{t+1} \mid s_t=1) = \xi_t\bf{A}$, or more generally that $\mathbb{E}(\xi_{t+1}\mid \xi_{t}) = \xi_t\bf{A}$ and since $s_t$ follows a Markov Chain:
\[\mathbb{E}(\xi_{t+1} \mid \xi_{1}, ..., \xi_t) = \xi_t\bf{A}\]In summary this means that when $s_t$ is i, then $\xi_t$ will represent a row-vector of the identity matrix which corresponds to the relevant transition probability. And when multiplied by the transition matrix gives you the transition probability. But of course, as Markov Chains only depend on the most recent state, the expectation of the next period’s $\xi$ value $\xi_{t+1}$ is simply equal to the current $\xi_t$ value times the transition matrix. It’s essentially like an over-complicated lookup function.
The probability that $s_{t+2}=j$ given $s_t=1$ by:
\[\mathbb{P}(s_{t+2}=j \mid s_t=i)=a_{i,1}a_{1,j}+...+a_{i,N}a_{N,j}\]which can also be recognized as the i-th row and j-th column element of the transition matrix squared $\bf{A}^2$. The odds of two things happening one after the other is simply the odds squared, which is what we are saying here.
In general, the probability that $s_{t+m}=j$ given $s_t=i$ is given by the row j, column i element of $\bf{A}^m$:
\[\mathbb{E}(\xi_{t+m} \mid \xi_t, \xi_{t-1}, ..., \xi_1) = \xi_t \bf{A}^m\]Ultimately we are locating the appropriate probability in the transition matrix and raising it to the nth power depending on how many steps forwards we are going.
Assume that we have received some information $I_t$ up to date $t$. Let
\[\pi_t = [\mathbb{P}(s_t=1 \mid I_t), ..., \mathbb{P}(s_t=N \mid I_t)]\]denote the conditional probability distribution over the state space. What is out best forecast of $s_{t+1}$ given $I_t$? Since $\pi_t = \mathbb{E}(\xi_t \mid I_t)$, we infer that
\[\pi_{t+1} = \mathbb{E}(\xi_{t+1}|I_t) = \mathbb{E}(\xi_t \mid I_t)\bf{A}\]If $I_t$ contains no leading information then $\mathbb{E}(\nu_{t+1} \mid I_t)=0$. The forecast state distribution is therefore
\[\pi_{t+1} = \pi_t\bf{A}\]This essentially means that the 1-step forward conditional probability distribution $\pi_{t+1}$ is equal to the current probability distribution $\bf{A}$ multiplied by the current period transition matrix $\pi_t$. The current probability distribution $\pi_t$ already includes all the information up until t.
To make note of something related to Forecasting Transitions; a distribution $\pi$ is stationary if it satisfies $\pi = \pi\bf{A}$, which means that today’s forecast distribution $\pi$ is the same as today’s distribution $\bf{A}$. If the Markov Chain is ergodic, then the system
\[\begin{align} \pi &= \pi\bf{A} \\ \pi\iota &= 1 \end{align}\]has a unique solution. Here $\iota$ denotes the $(N \times 1)$ vector with all elements equal to unity.
]]>Matrix multiplication is done by repetitive vector multiplication. Multiplication of two vectors is…
\[\begin{bmatrix}a_1 & a_2 & a_3 \end{bmatrix}\begin{bmatrix}a_1\\b_1\\c_1\end{bmatrix} = a_1b_1 + a_2b_2 + a_3b_3 + ... + a_nb_n = \sum^{n}_{i=1}a_ib_i\]If we are denoting these matrices as A and B then we can say in this case that AB = BA. We can’t multiply two column vectors as that won’t work with the way that matrix multiplication works.
If the two matrices being multiplied do not have the same number of rows and columns, then your resulting matrix will be an $m \times p$ sized matrix. For example, if matrix A has m rows and n columns$(m \times n)$, and if matrix B has n rows and p columns $(n \times p)$, then the resulting matrix will be a $(m \times p)$ sized matrix.
If a matrix is multiplied by a scalar (an individual value) then all elements of the matrix are simply multiplied by that scalar value.
Transpose is the process of making the matrix rows into columns, and columns into rows. Often we have to do this so that we can perform matrix multiplication. \(A' = A^T = \begin{bmatrix}a_1 & a_2 & a_3\end{bmatrix}^T = \begin{bmatrix}a_1\\a_2\\a_3\end{bmatrix}\) And in relation to matrix multiplication as explained above… \(a'b = b'a = \sum^{n}_{i=1}a_ib_i\)
Matrix addition is done by adding the corresponding elements of each matrix. So if we are to add matrices A and B together, we’d simply do…\(\begin{bmatrix} a_1 \\ a_2 \\ a_3 \end{bmatrix} + \begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix} = \begin{bmatrix} a_1 + b_1 \\ a_2 + b_2 \\ a_3 + b_3 \end{bmatrix}\)
Two matrices can only be added together if they are of the same $(m \times n)$ size. The resulting matrix will also be the same size. The order in which the matrices are added is not relevant.
If we say that A is equal to B we are simply saying that the first element in A is equal to the first element in B, and so on.
An operation on two matrices resulting in a block matrix. If A = an m x n matrix, and B is a p x q matrix, then the Kronecker product $A \otimes B$ is an pm x qn block matrix. For example…
\[\begin{bmatrix} 1 & 2 \\ 3 & 4 \\ \end{bmatrix} \otimes \begin{bmatrix} 0 & 5 \\ 6 & 7 \\ \end{bmatrix} = \begin{bmatrix} 1 \begin{bmatrix} 0 & 5 \\ 6 & 7 \\ \end{bmatrix} & 2 \begin{bmatrix} 0 & 5 \\ 6 & 7 \\ \end{bmatrix} \\ 3 \begin{bmatrix} 0 & 5 \\ 6 & 7 \\ \end{bmatrix} & 4 \begin{bmatrix} 0 & 5 \\ 6 & 7 \\ \end{bmatrix} \\ \end{bmatrix}\] \[\begin{bmatrix} 1\times 0 & 1\times 5 & 2\times 0 & 2\times 5 \\ 1\times 6 & 1\times 7 & 2\times 6 & 2\times 7 \\ 3\times 0 & 3\times 5 & 4\times 0 & 4\times 5 \\ 3\times 6 & 3\times 7 & 4\times 6 & 4\times 7 \\ \end{bmatrix} = \begin{bmatrix} 0 & 5 & 0 & 10 \\ 6 & 7 & 12 & 14 \\ 0 & 15 & 0 & 20 \\ 18 & 21 & 24 & 28 \end{bmatrix}\]The trace of a matrix is the sum of the diagonal elements. It is denoted as $tr(A)$.
The determinant is a scalar value that is a function of the entries of a square matrix. In the case of a 2 × 2 matrix the determinant can be defined as: \(\begin{align}|A| = \begin{vmatrix} a & b\\c & d \end{vmatrix}=ad-bc.\end{align}\)
Similarly, for a 3 × 3 matrix ‘‘A’’, its determinant is: \(\begin{align} |A| = \begin{vmatrix} a & b & c \\ d & e & f \\ g & h & i \end{vmatrix} &= a\,\begin{vmatrix} e & f \\ h & i \end{vmatrix} - b\,\begin{vmatrix} d & f \\ g & i \end{vmatrix} + c\,\begin{vmatrix} d & e \\ g & h \end{vmatrix} \\[3pt] &= aei + bfg + cdh - ceg - bdi - afh. \end{align}\)
The determinant is nonzero if and only if the matrix is Invertible.
]]>