Overall Statistics |
Total Trades 457 Average Win 2.21% Average Loss -2.14% Compounding Annual Return 8.668% Drawdown 48.000% Expectancy 0.314 Net Profit 323.510% Sharpe Ratio 0.475 Probabilistic Sharpe Ratio 0.347% Loss Rate 35% Win Rate 65% Profit-Loss Ratio 1.03 Alpha 0.011 Beta 0.775 Annual Standard Deviation 0.149 Annual Variance 0.022 Information Ratio -0.071 Tracking Error 0.087 Treynor Ratio 0.092 Total Fees $1268.00 Estimated Strategy Capacity $78000000.00 Lowest Capacity Asset XLB RGRPZX100F39 Portfolio Turnover 2.40% |
import numpy as np import pandas as pd from datetime import datetime from AlgorithmImports import * class EmmausAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2006, 1, 1) self.SetCash(30000) # choose 11 sector ETFs tickers = [ "XLY", # Materials "XLB", # Communication Services "XLE", # Energy "XLF", # Financials "XLK", # Technology "XLP", # Staples "IYR", # Real Estate "XLU", # Utilities "XLV", # Health Care "XLT", ] # Discretionary self.data = {} for ticker in tickers: symbol = self.AddEquity(ticker, Resolution.Daily).Symbol self.data[symbol] = {"roc": RateOfChangePercent(3), "dollar_return": None} consolidator = TradeBarConsolidator(CalendarType.Monthly) self.RegisterIndicator(symbol, self.data[symbol]["roc"], consolidator) self.SetWarmUp(30) # shcedule the function to fire at the month start self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(8, 0), self.Rebalance) def Rebalance(self): if self.IsWarmingUp: return # calculate dollar return for last trading year start_date = self.Time.replace(year=self.Time.year-1, month=1, day=1) end_date = self.Time.replace(year=self.Time.year-1, month=12, day=31) for symbol in self.data: history = self.History([symbol], start_date, end_date, Resolution.Daily) if not history.empty: self.data[symbol]["dollar_return"] = self.Portfolio[symbol].Price / history.iloc[0]["close"] - 1 # calculate momentum rank based on combination of last 3 months' return and dollar return for last trading year momentum_rank = {symbol: 0 for symbol in self.data} for symbol, data in self.data.items(): roc = data["roc"].Current.Value dollar_return = data["dollar_return"] if dollar_return is None: # if no dollar return data, use 0 dollar_return = 0 momentum_rank[symbol] = roc + dollar_return # select top 3 momentum ETFs top3 = sorted(momentum_rank.items(), key=lambda x: x[1], reverse=True)[:3] top3_symbols = [symbol for symbol, rank in top3] for kvp in self.Portfolio: symbol = kvp.Key if symbol in top3_symbols: continue # liquidate the security which is no longer in the top3 momentum list if kvp.Value.Invested: self.Liquidate(symbol, 'Not selected') for symbol in top3_symbols: if not self.Portfolio[symbol].Invested: self.SetHoldings(symbol, 1/3)