Strategy Library

Value Effect within Countries


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.


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 22 countries with easily accessible equity markets via ETFs. We import the custom CAPE ratio(Shiller PE Ratio) data of those 22 countries and create a dictionary to save the corresponding country ETF. This data from Quandl is in monthly resolution and starts January 2000.

  class CAPE(PythonData):

      def GetSource(self, config, date, isLiveMode):
          return SubscriptionDataSource("", SubscriptionTransportMedium.RemoteFile)

      def Reader(self, config, line, date, isLiveMode):
          if not (line.strip() and line[1].isdigit()): return None
          index = CAPE()
          index.Symbol = config.Symbol
          # data format
          # Date       Canada  UK     United States  France    Germany   Italy    Spain ...
          # 1/31/00    45.7    25.08  42.18          55.94     51.35     54.34    32.16 ...
          data = line.split(',')
          index.Time = datetime.strptime(data[0], "%m/%d/%y")
          symbols = Symbols().tickers
          for key, value in symbols.items():
              index[key] = float(data[value[0]]) if data[value[0]] else None
          return index

  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 = {"Canada":[1, "XIC"],          # S&P/TSX Composite Index: iShares S&P TSX Capped Cmpst Indx Fnd
                          "Uk":[2, "EWU"],              # FTSE 100 Index: iShares MSCI United Kingdom ETF
                          "Us":[3, "SPY"],              # S&P 500 Index: SPDR S&P 500 ETF
                          "France":[4, "EWQ"],          # CAC 40 Index: iShares MSCI France ETF
                          "Germany":[5, "EWG"],         # HDAX Index: iShares MSCI Germany ETF
                          "Italy":[6, "EWI"],           # FTSE MIB Index: iShares MSCI Italy ETF
                          "Spain":[7, "EWP"],           # IBEX 35 Index: iShares MSCI Spain ETF
                          "Russia":[8, "ERUS"],         # RTS Index: iShares MSCI Russia ETF
                          "India":[9, "INDY"],          # NIFTY 50 Index: iShares India 50 ETF
                          "Japan":[10, "EWJ"],          # All Public Companies: iShares MSCI Japan ETF
                          "Singapore":[11, "EWS"],      # STI Index:  iShares MSCI Singapore ETF
                          "Korea":[12,"EWY"],           # KOSPI Index: iShares MSCI South Korea ETF
                          "China":[13, "MCHI"],         # SSE Composite: iShares MSCI China Index Fund
                          "Hongkong":[14, "EWH"],       # Hang Seng Index: iShares MSCI Hong Kong Index Fund
                          "Brazil":[15, "EWZ"],         # Indice Bovespa (Ibovespa): iShares MSCI Brazil ETF
                          "Mexico":[16, "EWW"],         # &P/BMV IPC Index: iShares MSCI Mexico ETF
                          "Southafrica":[17, "EZA"],    # FTSE/JSE CAP Top 40 Index: iShares MSCI South Africa ETF
                          "Australia":[18, "EWA"],      # ASX All Ordinaries Index: iShares MSCI Australia ETF
                          "Turkey":[19, "TUR"],         # BIST 100: iShares MSCI Turkey ETF
                          "Poland":[20, "EPOL"],        # WIG Index: iShares MSCI Poland ETF
                          "Indonesia":[21, "EIDO"],     # IDX Composite: iShares MSCI Indonesia ETF
                          "Philippines":[22, "EPHE"]}   # PSE Composite:  iShares MSCI Philippines Investable

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.

  def Rebalance(self):
      self.cape = {}
      for key, value in self.symbols.items():
          cape = getattr(self.slice["CAPE"], key)
          if cape is not None:
              self.cape[value[1]] = cape
      sorted_cape = sorted(self.cape, key = lambda x: self.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 self.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:
      for i in long_list:
          self.SetHoldings(i, 1/len(long_list))


You can also see our Documentation and Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the tutorials: