Quant BuffetRelax, Not Over Thinking

Why Do US Stocks Outperform EM and EAFE Regions?

Log in to collect

Academic paper

Why Do US Stocks Outperform EM and EAFE Regions?

AuthorsCyril Dujava; Radovan Vojtko

Institute
  • ?Quantpedia
  • ?Quantpedia.com

Strategy in a nutshell

This strategy applies a simple trend-following rule on the spread between U.S. equities (SPY) and emerging markets (EEM). If the spread shows positive performance over the past 12 months, go long SPY and short EEM; otherwise, reverse the position. Positions are rebalanced yearly.

Economic rationale

The strategy leverages long-term outperformance of U.S. equities versus global markets, combined with momentum effects and U.S. dollar trends that influence commodities and emerging market stocks, reinforcing spread-based trading opportunities.

Backtest performance

Annualised return7.14%
Volatility19.5%
Beta0.132
Sharpe ratio0.37
Sortino ratio0.308
Maximum drawdown-62.28%
Win rate67%

Full Python code

from AlgorithmImports import *
import data_tools
from pandas.core.frame import DataFrame
# endregion

class WhyDoUSStocksOutperformEMandEAFERegions(QCAlgorithm):

def Initialize(self) -> None:
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)

self.period: int = 365
self.leverage: int = 3

self.spread_assets: List[Symbol] = [
    self.AddEquity('SPY', Resolution.Daily).Symbol,
    self.AddEquity('EEM', Resolution.Daily).Symbol
]

for symbol in self.spread_assets:
    self.Securities[symbol].SetLeverage(self.leverage)

self.Settings.MinimumOrderMarginPortfolioPercentage = 0.
self.current_month: int = -1

def OnData(self, data: Slice) -> None:
# monthly rebalance
if self.Time.month == self.current_month:
    return
self.current_month = self.Time.month

trade_direction: int = 0

returns_df: DataFrame = self.History(self.spread_assets, timedelta(days=self.period), Resolution.Daily)['close'].unstack(level=0).pct_change().iloc[1:].dropna(axis=1)
if returns_df.shape[1] == 2:
    spread: pd.Series = returns_df[self.spread_assets[0]] - returns_df[self.spread_assets[1]]
    spread_equity: float = (1 + spread).cumprod()
    trade_direction: int = 1 if spread_equity[-1] > spread_equity[0] else -1

# order execution
portfolio: List[PortfolioTarget] = [PortfolioTarget(symbol, ((-1)**i) * trade_direction) for i, symbol in enumerate(self.spread_assets) if symbol in data and data[symbol]]
self.SetHoldings(portfolio, True)