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.
def coarse_selection_function(self, coarse):
if self.monthly_rebalance:
self.coarse = True
filtered_coarse = [x.symbol for x in coarse if x.has_fundamental_data]
return filtered_coarse
else:
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).
def fine_selection_function(self, fine):
if self.monthly_rebalance:
fine =[i for i in fine if i.earning_reports.basic_average_shares.three_months != 0
and i.earning_reports.basic_e_p_s.twelve_months != 0
and i.valuation_ratios.pe_ratio != 0
# sales is greater than 10 million
and i.valuation_ratios.sales_per_share*i.earning_reports.diluted_average_shares.value > 10000000
and i.operation_ratios.ROA.value != 0]
# sort into 2 halfs based on market capitalization
sorted_market_cap = sorted(fine, key = lambda x:x.market_cap, reverse=True)
top = sorted_market_cap[:int(len(sorted_market_cap)*0.5)]
bottom = sorted_market_cap[-int(len(sorted_market_cap)*0.5):]
# each half is then divided into deciles based on Return on Assets (ROA)
sorted_top_by_r_o_a = sorted(top, key = lambda x: x.operation_ratios.ROA.value, reverse = True)
sorted_bottom_by_r_o_a = sorted(bottom, key = lambda x: x.operation_ratios.ROA.value, reverse = True)
# long top decile from each market capitalization group
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)]
self.long_stocks = [i.symbol for i in long]
# short bottom decile from each market capitalization group
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):]
self.short_stocks = [i.symbol for i in short]
return self.long_stocks + self.short_stocks
else:
return Universe.UNCHANGED
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.
def on_data(self, data):
if not (self.monthly_rebalance and self.coarse): return
self.coarse = False
self.monthly_rebalance = False
stocks_invested = [x.key for x in self.portfolio if x.value.INVESTED]
for i in stocks_invested:
if i not in self.long_stocks+self.short_stocks:
self.liquidate(i)
long_weight = 0.5/len(self.long_stocks)
for i in self.long_stocks:
self.set_holdings(i, long_weight)
short_weight = 0.5/len(self.short_stocks)
for i in self.short_stocks:
self.set_holdings(i, -short_weight)
Pavel Fedorov
 in the research environment it is clear we can use the GetFundamental method to access for a given symbol and date pair any fundamental morning star data available… but in order to get historical data for a universe of stocks, i need to access the equivalent of a coarse and fine filter and obtain such symbols for each date? how can I do this could you advise? otherwise how is it possible to assemble a dataset of price and fundamental data for symbols that were traded during some period of dates in the past ? this is vital for training a supervised ML model but i dont see any example for this
Derek Melchin
See the attached backtest for an updated version of the algorithm with the following changes:
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Jing Wu
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!