| Overall Statistics |
|
Total Orders 1808 Average Win 0.50% Average Loss -0.75% Compounding Annual Return 19.953% Drawdown 50.000% Expectancy 0.136 Start Equity 100000 End Equity 248302.93 Net Profit 148.303% Sharpe Ratio 0.503 Sortino Ratio 0.603 Probabilistic Sharpe Ratio 12.383% Loss Rate 32% Win Rate 68% Profit-Loss Ratio 0.67 Alpha 0.053 Beta 1.204 Annual Standard Deviation 0.29 Annual Variance 0.084 Information Ratio 0.293 Tracking Error 0.236 Treynor Ratio 0.121 Total Fees $2870.03 Estimated Strategy Capacity $4300000.00 Lowest Capacity Asset HL R735QTJ8XC9X Portfolio Turnover 5.60% Drawdown Recovery 1036 |
# region imports
from AlgorithmImports import *
# endregion
class StockSelectionStrategyBasedOnFundamentalFactorsAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(datetime.now()-timedelta(5*365))
self.set_cash(100000)
self.universe_settings.schedule.on(self.date_rules.month_start("SPY"))
self.add_universe(self._select)
self.set_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(30)))
self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(lambda _: None))
def _select(self, fundamental):
top_volume = 300
top_rank = 10
fundamental = sorted(
[
x for x in fundamental
if not any([np.isnan(factor) for factor in [
x.valuation_ratios.fcf_yield,
x.valuation_ratios.price_change_1m,
x.valuation_ratios.book_value_per_share,
x.earning_reports.total_dividend_per_share.three_months
]])
],
key=lambda x: x.dollar_volume, reverse=True)[:top_volume]
sorted_by_factor1 = sorted(fundamental, key=lambda x: x.valuation_ratios.fcf_yield, reverse=True)
sorted_by_factor2 = sorted(fundamental, key=lambda x: x.valuation_ratios.price_change_1m, reverse=False)
sorted_by_factor3 = sorted(fundamental, key=lambda x: x.valuation_ratios.book_value_per_share, reverse=True)
sorted_by_factor4 = sorted(fundamental, key=lambda x: x.earning_reports.total_dividend_per_share.three_months, reverse=True)
stock_dict = { }
for rank1, ele in enumerate(sorted_by_factor1):
rank2 = sorted_by_factor2.index(ele)
rank3 = sorted_by_factor3.index(ele)
rank4 = sorted_by_factor4.index(ele)
stock_dict[ele] = rank1 + rank2 + rank3 + rank4
sorted_stock = sorted(stock_dict.items(), key=lambda d:d[1], reverse=True)[:top_rank]
return [x.symbol for x,_ in sorted_stock]