Overall Statistics |
Total Orders 6259 Average Win 0.08% Average Loss -0.07% Compounding Annual Return 17.830% Drawdown 31.600% Expectancy 0.631 Start Equity 1000000 End Equity 5058048.84 Net Profit 405.805% Sharpe Ratio 0.675 Sortino Ratio 0.711 Probabilistic Sharpe Ratio 17.449% Loss Rate 24% Win Rate 76% Profit-Loss Ratio 1.13 Alpha 0.026 Beta 1.098 Annual Standard Deviation 0.171 Annual Variance 0.029 Information Ratio 0.593 Tracking Error 0.058 Treynor Ratio 0.105 Total Fees $9085.74 Estimated Strategy Capacity $1900000000.00 Lowest Capacity Asset PG R735QTJ8XC9X Portfolio Turnover 1.15% |
# region imports from AlgorithmImports import * from dateutil.relativedelta import relativedelta # endregion class TOPTAnalysisAlgorithm(QCAlgorithm): def initialize(self): self.set_start_date(2014, 12, 31) self.set_cash(1_000_000) spy = Symbol.create('SPY', SecurityType.EQUITY, Market.USA) self.set_security_initializer( BrokerageModelSecurityInitializer(self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices)) ) # Add a universe of daily data. self.universe_settings.resolution = Resolution.DAILY self._universe = self.add_universe( self.universe.etf( Symbol.create('SPY', SecurityType.EQUITY, Market.USA), universe_filter_func=lambda constituents: [ c.symbol for c in sorted( [c for c in constituents if c.weight], key=lambda c: c.weight )[-20:] ] ) ) #self._universe = self.add_universe( # lambda fundamentals: [f.symbol for f in sorted(fundamentals, key=lambda f: f.market_cap)[-20:]] #) # Create a Scheduled Event to record new daily prices and # rebelance the portfolio. self.schedule.on( self.date_rules.every_day(spy), # The fund is dynamically rebalanced on a quarterly basis - the 3rd Friday # of March, June, September, and December. # Source: https://www.ishares.com/us/strategies/top-20#top-5-companies #FuncDateRule( # name="third_friday_of_the_quarter_end_month", # get_dates_function=self._third_friday_of_the_quarter_end_month #), self.time_rules.at(0, 1), self._rebalance ) self.set_warm_up(timedelta(30)) def _rebalance(self): if self.is_warming_up or not self._universe.selected: return symbols = [s for s in self._universe.selected if s in self.securities and self.securities[s].price] if not symbols: return market_cap_sum = sum([self.securities[s].fundamentals.market_cap for s in symbols]) if not market_cap_sum: return self.set_holdings([PortfolioTarget(symbol, self.securities[symbol].fundamentals.market_cap/market_cap_sum) for symbol in symbols], True) def _third_friday_of_the_quarter_end_month(self, start_date, end_date): dt = start_date.replace(day=1).replace(tzinfo=None) dates = [] while dt <= end_date: if dt.month in [3, 6, 9, 12]: days_until_friday = (4 - dt.weekday()) % 7 # 4 represents Friday first_friday = dt + timedelta(days=days_until_friday) third_friday = first_friday + timedelta(weeks=2) dates.append(third_friday) dt += relativedelta(months=1) return dates