In this paper, I will review the size effect, potential reasons why one observes the size effect, and correct common misconceptions and address criticisms of the Size Premia (SP). Throughout this paper, I will show that using a pure market factor as the sole risk factor in estimating the expected return provide an incomplete estimate. For the last four decades, research have shown that adjustments to the CAPM are required. I will address some of the criticism to the theoretical basis of the SP and to the application adopted through the CRSP Decile Size Premia and Risk Premium Report - Size Study. Specifically, I demonstrate that the size premium critique by Clifford Ang is not warranted and that the alternative methodology proposed by that author is misleading and cannot be considered as an alternative to the Duff & Phelps’ SP. The methodology the author is proposing picks up statistical errors that he was set to avoid by proposing a variation of Duff and Phelps’ methodology. Finally, I will provide some practical guidance on efficiently and correctly applying SP.
Keywords: size effect, CAPM, cost of capital
- Target assets: Stocks from the NYSE, AMEX, and NASDAQ.
- Organize stocks into five groups determined by their market value.
- Choose the group with the smallest market capitalization.
- Hold for one year.
- Rebalance portfolio annually.
import backtrader as bt import datetime class MarketCapStrategy(bt.Strategy): params = ( ('quintile', 5), ('rebalance_days', 252), ) def __init__(self): self.counter = 0 def next(self): self.counter += 1 if self.counter % self.params.rebalance_days == 0: self.rebalance_portfolio() def rebalance_portfolio(self): market_caps =  for data in self.datas: market_cap = data.close * data.volume market_caps.append((data, market_cap)) sorted_data = sorted(market_caps, key=lambda x: x) quintile_size = len(sorted_data) // self.params.quintile lowest_quintile = sorted_data[:quintile_size] # Calculate total market cap for lowest quintile total_market_cap = sum([x for x in lowest_quintile]) # Sell all current holdings for data in self.datas: self.order_target_percent(data, target=0) # Buy stocks in lowest quintile for data, market_cap in lowest_quintile: target_weight = market_cap / total_market_cap self.order_target_percent(data, target=target_weight) if __name__ == '__main__': cerebro = bt.Cerebro() # Add investment universe for ticker in ['NYSE_ticker1', 'NYSE_ticker2', 'AMEX_ticker1', 'NASDAQ_ticker1']: data = bt.feeds.YahooFinanceData( dataname=ticker, fromdate=datetime.datetime(2015, 1, 1), todate=datetime.datetime(2021, 9, 30), adjclose=True, plot=False, ) cerebro.adddata(data) cerebro.addstrategy(MarketCapStrategy) cerebro.broker.setcash(100000.0) cerebro.broker.setcommission(commission=0.001) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())