Introduction

Return on Equity (ROE) is defined as the ratio of net income over shareholders equity, where shareholders’ equity is the difference between a company's total assets and total liabilities. Shareholders' equity is often referred to as the book value of the company. ROE is a measure of how efficiently a company uses its assets to produce earnings. It can explain many anomalies related to earnings and profitability. This algorithm will build a long-short portfolio with the ROE factor.

Method

The investment universe contains all stocks on NYSE and AMEX and Nasdaq. In the CoarseSelectionFunction, we eliminated ETFs which does not have fundamental data.

  1. def coarse_selection_function(self, coarse):
  2. if self.monthly_rebalance:
  3. self.coarse = True
  4. filtered_coarse = [x.symbol for x in coarse if x.has_fundamental_data]
  5. return filtered_coarse
  6. else:
  7. return Universe.UNCHANGED

In the FineSelectionFunction, stocks with sales greater than 10 milion USD are selected. Then we calculate the market cap for those stocks and sort them into two groups: Big size group with the higher market cap and small size group with the lower market cap. Each half is then divided into deciles based on Return on assets (ROA).

  1. def fine_selection_function(self, fine):
  2. if self.monthly_rebalance:
  3. fine =[i for i in fine if i.earning_reports.basic_average_shares.three_months != 0
  4. and i.earning_reports.basic_e_p_s.twelve_months != 0
  5. and i.valuation_ratios.pe_ratio != 0
  6. # sales is greater than 10 million
  7. and i.valuation_ratios.sales_per_share*i.earning_reports.diluted_average_shares.value > 10000000
  8. and i.operation_ratios.ROA.value != 0]
  9. # sort into 2 halfs based on market capitalization
  10. sorted_market_cap = sorted(fine, key = lambda x:x.market_cap, reverse=True)
  11. top = sorted_market_cap[:int(len(sorted_market_cap)*0.5)]
  12. bottom = sorted_market_cap[-int(len(sorted_market_cap)*0.5):]
  13. # each half is then divided into deciles based on Return on Assets (ROA)
  14. sorted_top_by_r_o_a = sorted(top, key = lambda x: x.operation_ratios.ROA.value, reverse = True)
  15. sorted_bottom_by_r_o_a = sorted(bottom, key = lambda x: x.operation_ratios.ROA.value, reverse = True)
  16. # long top decile from each market capitalization group
  17. long = sorted_top_by_r_o_a[:int(len(sorted_top_by_r_o_a)*0.1)] + sorted_bottom_by_r_o_a[:int(len(sorted_top_by_r_o_a)*0.1)]
  18. self.long_stocks = [i.symbol for i in long]
  19. # short bottom decile from each market capitalization group
  20. short = sorted_top_by_r_o_a[-int(len(sorted_top_by_r_o_a)*0.1):] + sorted_bottom_by_r_o_a[-int(len(sorted_top_by_r_o_a)*0.1):]
  21. self.short_stocks = [i.symbol for i in short]
  22. return self.long_stocks + self.short_stocks
  23. else:
  24. return Universe.UNCHANGED
+ Expand

The algorithm goes long the top decile from each market capitalization group and short the bottom decile. The strategy is rebalanced monthly and stocks are equally weighted.

  1. def on_data(self, data):
  2. if not (self.monthly_rebalance and self.coarse): return
  3. self.coarse = False
  4. self.monthly_rebalance = False
  5. stocks_invested = [x.key for x in self.portfolio if x.value.INVESTED]
  6. for i in stocks_invested:
  7. if i not in self.long_stocks+self.short_stocks:
  8. self.liquidate(i)
  9. long_weight = 0.5/len(self.long_stocks)
  10. for i in self.long_stocks:
  11. self.set_holdings(i, long_weight)
  12. short_weight = 0.5/len(self.short_stocks)
  13. for i in self.short_stocks:
  14. self.set_holdings(i, -short_weight)
+ Expand


Reference

  1. Quantpedia - ROA Effect within Stocks

Author

Jing Wu

August 2018