
“Investor utilizes Russell’s ETFs for six equity styles. Monthly, they calculate 12-month momentum, going long on winners and short on losers, with monthly rebalancing.”
ASSET CLASS: ETFs | REGION: United States | FREQUENCY: Monthly | MARKET:
equities | KEYWORD: Momentum
I. STRATEGY IN A NUTSHELL
Russell’s ETFs for six equity styles are used (small-cap value, mid-cap value, large-cap value, small-cap growth, mid-cap growth, large-cap growth). Each month, the investor calculates 12-month momentum for each style and goes long on the winner and short on the loser. The portfolio is rebalanced each month.
II. ECONOMIC RATIONALE
The obvious observation is that styles perform differently over time (the same way different assets do). The popularity of style investing itself may influence the structure and dynamics of asset returns since prices deviate substantially from fundamental values as styles become popular or unpopular. This non-random behavior gives the foundation to the rise of exploitable momentum.
III. SOURCE PAPER
Using Style Index Momentum to Generate Alpha [Click to Open PDF]
Samuel L. Tibbs, American University of Sharjah – School of Business and Management ; Stanley G. Eakins, East Carolina University – College of Business ; William DeShurko, 401 Advisor, LLC
<Abstract>
Russell style indexes exhibit significant momentum, particularly after medium term out- and underperformance. The existence of this momentum produces a diversified, index-based low-cost means to exploit momentum by incorporating relative style index performance into tactical allocation strategies. Such style index momentum trading strategies have outperformed on both a raw and risk-adjusted return basis, with the long minus short portfolio generating an average 9.25% annual return over the 34-year period analyzed. Although the excess returns vary, they are robust through time and after controlling for potentially confounding effects. Additionally, the returns are not driven by any single style index and portfolio reconstruction is, on average, required every six months.

IV. BACKTEST PERFORMANCE
| Annualised Return | 9.25% |
| Volatility | 16.01% |
| Beta | -0.042 |
| Sharpe Ratio | -0.246 |
| Sortino Ratio | -0.278 |
| Maximum Drawdown | 53.5% |
| Win Rate | 52% |
V. FULL PYTHON CODE
from AlgoLib import *
class MomentumFactorAndStyleRotationEffect(XXX):
def Initialize(self):
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)
self.tickers = [
'IWS', # iShares Russell Midcap Value ETF
'IWP', # iShares Russell Midcap Growth ETF
'IWN', # iShares Russell 2000 Value ETF
'IWO', # iShares Russell 2000 Growth ETF
'IVE', # iShares S&P 500 Value ETF
'IVW' # iShares S&P 500 Growth ETF
]
self.mom = {}
self.period = 12 * 21
self.SetWarmUp(self.period)
for ticker in self.tickers:
security = self.AddEquity(ticker, Resolution.Daily)
security.SetFeeModel(CustomFeeModel())
security.SetLeverage(10)
self.mom[security.Symbol] = self.MOM(security.Symbol, self.period)
self.recent_month = -1
def OnData(self, data):
if self.recent_month == self.Time.month:
return
self.recent_month = self.Time.month
mom_ready = [ s for s in self.mom if self.mom[s].IsReady and s in data]
if mom_ready:
sorted_mom = sorted(mom_ready, key = lambda x: self.mom[x].Current.Value, reverse=True)
for symbol in sorted_mom[1:-1]:
if self.Portfolio[symbol].Invested:
self.Liquidate(symbol)
winner = sorted_mom[0]
loser = sorted_mom[-1]
if self.Securities[winner].Price != 0 and self.Securities[winner].IsTradable:
if (self.Time.month == 10 and self.Time.year == 2020) and winner.Value == 'IVW': # prevent data error
self.Liquidate(winner)
else:
self.SetHoldings(winner, 1)
if self.Securities[loser].Price != 0 and self.Securities[loser].IsTradable:
if (self.Time.month == 10 and self.Time.year == 2020) and loser.Value == 'IVW': # prevent data error
self.Liquidate(loser)
else:
self.SetHoldings(loser, -1)
# Custom fee model.
class CustomFeeModel(FeeModel):
def GetOrderFee(self, parameters):
fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
return OrderFee(CashAmount(fee, "USD"))