Introduction
Equity valuation may be a predictive signal for future Equity return. There are various methodologies to evaluate whether the Equity is undervalued or overvalued using metrics like price-to-earnings (P/E), return on equity (ROE), dividend yield, book-to-equity and so on. In this algorithm, we use a ten-year normalized earnings metrics invented by Yale University professor Robert Shiller to find the fair value of the Equity market.
Method
The cyclically adjusted price-to-earnings ratio (CAPE) compares the stock prices with earnings smoothed across multiple years. It is the price divided by the average of ten years of earnings (moving average), adjusted for inflation. The backward-looking earnings smooth out the economic cycle as well as the price fluctuations.
The investment universe consists of 26 countries with easily accessible Equity markets via ETFs. We import the custom CAPE ratio (Shiller PE Ratio) data of those 26 countries and create a dictionary to save the corresponding country ETF. This custom data is from Barclays Indices is in monthly resolution and starts January 1982.
class CAPE(PythonData):
def get_source(self, config, date, isLiveMode):
return SubscriptionDataSource("https://indices.cib.barclays/file.app?action=shared&path=shiller/cape.csv", SubscriptionTransportMedium.REMOTE_FILE)
def reader(self, config, line, date, isLiveMode):
if not (line.strip() and line[1].replace('.', '', 1).isdigit()): return None
try:
index = CAPE()
index.symbol = config.symbol
data = line.split(',')
index.time = datetime.strptime(data[0], "%d/%m/%Y")
symbols = Symbols().tickers
for key, value in symbols.items():
index[key] = float(data[value[0]]) if data[value[0]] else 100000 # very large number to avoid be selected
return index
except:
return None
class Symbols:
def __init__(self):
# the indiex is the country name
# the first element of the value is the column number of CAPE ratio value in custom dataset
# the second element of the value is the corresponding country ETF
self.tickers = {"Australia":[1, "EWA"], # ASX All Ordinaries Index: iShares MSCI Australia ETF
"Brazil":[2, "EWZ"], # Indice Bovespa (Ibovespa): iShares MSCI Brazil ETF
"Canada":[3, "XIC"], # S&P/TSX Composite Index: iShares S&P TSX Capped Cmpst Indx Fnd
"China":[4, "MCHI"], # SSE Composite: iShares MSCI China Index Fund
"Europe":[5, "IEUR"], # STOXX Europe 600 Index: iShares Core MSCI Europe ETF
"France":[6, "EWQ"], # CAC 40 Index: iShares MSCI France ETF
"Germany":[7, "EWG"], # HDAX Index: iShares MSCI Germany ETF
"Hong Kong":[8, "EWH"], # Hang Seng Index: iShares MSCI Hong Kong Index Fund
"Italy":[9, "EWI"], # FTSE MIB Index: iShares MSCI Italy ETF
"India":[10, "INDY"], # NIFTY 50 Index: iShares India 50 ETF
"Israel":[11, "EIS"], # Tel Aviv 125 Index: iShares MSCI Israel ETF
"Japan":[12, "EWJ"], # All Public Companies: iShares MSCI Japan ETF
"Korea":[13,"EWY"], # KOSPI Index: iShares MSCI South Korea ETF
"Mexico":[14, "EWW"], # &P/BMV IPC Index: iShares MSCI Mexico ETF
"Netherlands":[15, "EWN"], # NL 25 Index: iShares MSCI Netherlands ETF
"Poland":[16, "EPOL"], # WIG Index: iShares MSCI Poland ETF
"Russia":[17, "ERUS"], # RTS Index: iShares MSCI Russia ETF
"Singapore":[18, "EWS"], # STI Index: iShares MSCI Singapore ETF
"Southafrica":[19, "EZA"], # FTSE/JSE CAP Top 40 Index: iShares MSCI South Africa ETF
"Spain":[20, "EWP"], # IBEX 35 Index: iShares MSCI Spain ETF
"Sweden":[21, "EWD"], # OMXS 30 index: iShares MSCI Sweden ETF
"Switzerland":[22, "EWL"], # CH 20 index: iShares MSCI Switzerland ETF
"Taiwan":[23, "EWT"], # TWSE: iShares MSCI Taiwan ETF
"Turkey":[24, "TUR"], # BIST 100: iShares MSCI Turkey ETF
"UK":[25, "EWU"], # FTSE 100 Index: iShares MSCI United Kingdom ETF
"USA":[26, "SPY"] # S&P 500 Index: SPDR S&P 500 ETF
}
According to the academic research of Shiller and Campbell, using market data from the S&P index, the lower the CAPE, the higher the investors' likely return from Equities. Therefore, the algorithm then invests in the cheapest 33% of countries from the sample with the lowest CAPE ratio if those countries have a CAPE below 15. If there are no countries with CAPE lower than 15, the algorithm holds cash instead of country ETFs. The portfolio is equally weighted and rebalanced monthly by every update of the CAPE data.
def on_data(self, data):
if data.contains_key(self.symbol):
cape = {}
for key, value in self.symbols.items():
cape[value[1]] = data[self.symbol].get_property(key)
sorted_cape = sorted(cape, key = lambda x: cape[x])
# invests the cheapest 33% of countries if those countries have a CAPE below 15
lowest_cape = sorted_cape[:int(1/3*len(sorted_cape))]
long_list = [i for i in lowest_cape if cape[i] < 15]
invested = [x.key for x in self.portfolio if x.value.INVESTED]
for i in invested:
if i.value not in long_list:
self.liquidate(i)
for i in long_list:
self.set_holdings(i, 1/len(long_list))
Derek Melchin
See the attached backtest for an updated version of the algorithm with the following changes:
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Jing Wu
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!