Overall Statistics |
Total Orders 9090 Average Win 0.11% Average Loss -0.08% Compounding Annual Return 7.419% Drawdown 17.000% Expectancy 0.203 Start Equity 1000000 End Equity 2058091.14 Net Profit 105.809% Sharpe Ratio 0.556 Sortino Ratio 0.52 Probabilistic Sharpe Ratio 12.706% Loss Rate 48% Win Rate 52% Profit-Loss Ratio 1.33 Alpha 0.044 Beta 0.001 Annual Standard Deviation 0.08 Annual Variance 0.006 Information Ratio -0.144 Tracking Error 0.181 Treynor Ratio 35.759 Total Fees $20357.95 Estimated Strategy Capacity $0 Lowest Capacity Asset CAFD W1I7J18MUIQT Portfolio Turnover 0.52% |
#region imports from AlgorithmImports import * #endregion class AssetGrowth(QCAlgorithm): _blacklisted_assets = ["TOPT T0KDYN9C3IHX"] # /datasets/issue/15180 def initialize(self): #rebalancing should occur in July self.set_start_date(2008, 6, 15) self.set_end_date(2018, 7, 15) self.set_cash(1000000) self.set_security_initializer(BrokerageModelSecurityInitializer( self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices))) self.settings.minimum_order_margin_portfolio_percentage = 0 self.universe_settings.resolution = Resolution.DAILY self._previous_fine = None self._filtered_fine = None self.add_universe(self._coarse_selection_function, self._fine_selection_function) self.add_equity("SPY", Resolution.DAILY) #monthly scheduled event but will only rebalance once a year self.schedule.on(self.date_rules.month_end("SPY"), self.time_rules.midnight, self.rebalance) self._months = -1 self._yearly_rebalance = False self.set_warmup(timedelta(365)) def _coarse_selection_function(self, coarse): if self._yearly_rebalance: # drop stocks which have no fundamental data return [x.symbol for x in coarse if x.has_fundamental_data and x.market == Market.USA] else: return [] def _fine_selection_function(self, fine): if self._yearly_rebalance: fine = [ x for x in fine if (x.financial_statements.balance_sheet.total_assets.value > 0 and x.security_reference.exchange_id in ['NYS', 'NAS', 'ASE'] and x.company_reference.industry_template_code != "B" and x.company_reference.industry_template_code != "I" and str(x.symbol.id) not in self._blacklisted_assets) ] if not self._previous_fine: #will wait one year in order to have the historical fundamental data self._previous_fine = fine self._yearly_rebalance = False return [] else: #will calculate and sort the stocks on asset growth self._filtered_fine = self._calculate(fine, self._previous_fine) sorted_filter = sorted(self._filtered_fine, key=lambda x: x.delta_assets) self._filtered_fine = [i.symbol for i in sorted_filter] #we save the fine data for the next year's analysis self._previous_fine = fine return self._filtered_fine else: return [] def _calculate(self, current, previous): growth = [] for stock_data in current: #compares this and last year's fine fundamental objects try: prev_data = None for x in previous: if x.symbol == stock_data.symbol: prev_data = x break #growth = (tota_assets(t)-total_assets(t-1))/total_assets(t-1) assets = float(stock_data.financial_statements.balance_sheet.total_assets.value) previous_assets = float(prev_data.financial_statements.balance_sheet.total_assets.value) stock_data.delta_assets = (assets - previous_assets) / previous_assets growth.append(stock_data) except: #value in current universe does not exist in the previous universe pass return growth def rebalance(self): #yearly rebalance self._months+=1 if self._months%12 == 0: self._yearly_rebalance = True def _get_tradable_assets(self, symbols): tradable_assets = [] for symbol in symbols: security = self.securities[symbol] if security.price and security.is_tradable: tradable_assets.append(symbol) return tradable_assets def on_data(self, data): if not (self._yearly_rebalance and self._filtered_fine): return if not self.is_warming_up: filtered_fine = self._get_tradable_assets(self._filtered_fine) portfolio_size = int(len(filtered_fine)/10) #pick the upper decile to short and the lower decile to long targets = [] weight = 0.5 / portfolio_size for symbol in filtered_fine[-portfolio_size:]: targets.append(PortfolioTarget(symbol, -weight)) for symbol in filtered_fine[:portfolio_size]: targets.append(PortfolioTarget(symbol, weight)) self.set_holdings(targets, True) self._yearly_rebalance = False self._filtered_fine = False