Overall Statistics |
Total Orders 526 Average Win 1.65% Average Loss -1.32% Compounding Annual Return -0.221% Drawdown 26.500% Expectancy 0.025 Start Equity 100000 End Equity 96177.60 Net Profit -3.822% Sharpe Ratio -0.518 Sortino Ratio -0.686 Probabilistic Sharpe Ratio 0.000% Loss Rate 54% Win Rate 46% Profit-Loss Ratio 1.25 Alpha -0.022 Beta 0.026 Annual Standard Deviation 0.041 Annual Variance 0.002 Information Ratio -0.364 Tracking Error 0.156 Treynor Ratio -0.815 Total Fees $2372.88 Estimated Strategy Capacity $3400000.00 Lowest Capacity Asset IJT RWQR2INKP0TH Portfolio Turnover 2.02% |
#region imports from AlgorithmImports import * #endregion # https://www.quantconnect.com/tutorials/strategy-library/momentum-and-style-rotation-effect # https://quantpedia.com/Screener/Details/91 class MomentumAndStyleRotationAlgorithm(QCAlgorithm): def initialize(self): self.set_start_date(2001, 1, 1) self.set_end_date(2018, 8, 1) self.set_cash(100000) tickers = ["IJJ", # iShares S&P Mid-Cap 400 Value Index ETF "IJK", # iShares S&P Mid-Cap 400 Growth ETF "IJS", # iShares S&P Small-Cap 600 Value ETF "IJT", # iShares S&P Small-Cap 600 Growth ETF "IVE", # iShares S&P 500 Value Index ETF "IVW"] # iShares S&P 500 Growth ETF lookback = 12*20 # Save all momentum indicator into the dictionary self.set_security_initializer(BrokerageModelSecurityInitializer( self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices))) self._momp = dict() for ticker in tickers: symbol = self.add_equity(ticker, Resolution.DAILY).symbol self._momp[symbol] = self.momp(symbol, lookback) self.set_warm_up(lookback) # Portfolio monthly rebalance self.schedule.on(self.date_rules.month_start("IJJ"), self.time_rules.at(0, 0), self._rebalance) def _rebalance(self): '''Sort securities by momentum. Short the one with the lowest momentum. Long the one with the highest momentum. Liquidate positions of other securities''' # Order the MOM dictionary by value sorted_mom = sorted(self._momp, key=lambda x: self._momp[x].current.value) # Liquidate the ETFs that are no longer selected for symbol in sorted_mom[1:-1]: if self.portfolio[symbol].invested: self.liquidate(symbol, 'No longer selected') self.set_holdings(sorted_mom[-1], -0.5) # Short the ETF with lowest MOM self.set_holdings(sorted_mom[0], 0.5) # Long the ETF with highest MOM