Overall Statistics |
Total Trades 97 Average Win 3.05% Average Loss -2.48% Compounding Annual Return 34.473% Drawdown 24.100% Expectancy 0.068 Net Profit 4.961% Sharpe Ratio 0.774 Probabilistic Sharpe Ratio 43.253% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 1.23 Alpha -0.129 Beta 3.499 Annual Standard Deviation 0.533 Annual Variance 0.284 Information Ratio 0.609 Tracking Error 0.423 Treynor Ratio 0.118 Total Fees $97.00 Estimated Strategy Capacity $590000.00 Lowest Capacity Asset TQQQ UK280CGTCB51 |
from AlgorithmImports import * class IntelligentSkyRodent(QCAlgorithm): def Initialize(self): self.SetStartDate(2023, 1, 1) # Set Start Date # self.SetEndDate(2020, 1, 10) self.SetCash(1000) # Set Strategy Cash # self.SetSecurityInitializer(self.CustomSecurityInitializer) # Define a list of equities to be used by the algorithm self.equities = ["SPY", "TQQQ", "SPXL", "UVXY", "SQQQ", "BSV", "TECL", "SMH", "SOXL", "DIA", "UDOW", "URPO", "QQQ", "PSQ", "TLT", "XLP"] self.indicators = dict() # Initialize a dictionary to store technical analysis indicators for each equity # Initialize technical analysis indicators for each equity for equity in self.equities: self.AddEquity(equity, Resolution.Minute) self.Securities[equity].SetDataNormalizationMode(DataNormalizationMode.Raw) self.indicators[equity] = dict() # Initialize RSI indicators for each equity self.indicators[equity]['RSI'] = dict() self.indicators[equity]['RSI']['Period-5'] = RelativeStrengthIndex(5) self.indicators[equity]['RSI']['Period-10'] = RelativeStrengthIndex(10) self.indicators[equity]['RSI']['Period-14'] = RelativeStrengthIndex(14) self.indicators[equity]['RSI']['Period-60'] = RelativeStrengthIndex(60) self.indicators[equity]['RSI']['Period-70'] = RelativeStrengthIndex(70) # Initialize SMA indicators for each equity self.indicators[equity]['SMA'] = dict() self.indicators[equity]['SMA']['Period-20'] = SimpleMovingAverage(20) self.indicators[equity]['SMA']['Period-200'] = SimpleMovingAverage(200) # Schedule the FunctionBeforeMarketClose method to run once per day before market close self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 5), self.FunctionBeforeMarketClose) # Define a method to calculate return of a given equity over a given period def CalculateReturn(self, equity: str, period: int) -> float: history = self.History(equity, period, Resolution.Daily) history = list(history) return (history[0].Close / history[-1].Close) - 1 # Initialize trade bar consolidators for each equity self.consolidators = dict() for equity in self.equities: self.consolidators[equity] = TradeBarConsolidator(timedelta(minutes=5)) self.consolidators[equity].DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(equity, self.consolidators[equity]) # Schedule the consolidators to run at the specified time before market close self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 10), self.Consolidators_Ready) def Consolidators_Ready(self): # Tell the consolidators to start consolidating data for consolidator in self.consolidators.values(): consolidator.Start() def OnDataConsolidated(self, sender, bar): equity = sender.Symbol.Value # Update all RSI indicators for the current equity for period, rsi in self.indicators[equity]['RSI'].items(): # If the RSI indicator is not ready, update its history if not rsi.IsReady: history = self.History(equity, period, Resolution.Daily) for historical_bar in history: rsi.Update(historical_bar.EndTime, historical_bar.Close) # Update the current RSI value rsi.Update(self.Time, bar.Close) # Update all SMA indicators for the current equity for period, sma in self.indicators[equity]['SMA'].items(): # If the SMA indicator is not ready, update its history if not sma.IsReady: history = self.History(equity, period, Resolution.Daily) for historical_bar in history: sma.Update(historical_bar.EndTime, historical_bar.Close) # Update the current SMA value sma.Update(self.Time, bar.Close) def FunctionBeforeMarketClose(self): # Iterate over each equity for equity in self.equities: if self.Portfolio[equity].HoldStock: # Liquidate the position self.Liquidate(equity) if not self.indicators[equity]['RSI']['Period-5'].IsReady: history = self.History(equity, 5, Resolution.Daily) for bar in history: self.indicators[equity]['RSI']['Period-5'].Update(bar.EndTime, bar.Close) if not self.indicators[equity]['RSI']['Period-10'].IsReady: history = self.History(equity, 10, Resolution.Daily) for bar in history: self.indicators[equity]['RSI']['Period-10'].Update(bar.EndTime, bar.Close) if not self.indicators[equity]['RSI']['Period-14'].IsReady: history = self.History(equity, 14, Resolution.Daily) for bar in history: self.indicators[equity]['RSI']['Period-14'].Update(bar.EndTime, bar.Close) if not self.indicators[equity]['RSI']['Period-60'].IsReady: history = self.History(equity, 60, Resolution.Daily) for bar in history: self.indicators[equity]['RSI']['Period-60'].Update(bar.EndTime, bar.Close) if not self.indicators[equity]['RSI']['Period-70'].IsReady: history = self.History(equity, 70, Resolution.Daily) for bar in history: self.indicators[equity]['RSI']['Period-70'].Update(bar.EndTime, bar.Close) if not self.indicators[equity]['SMA']['Period-20'].IsReady: history = self.History(equity, 20, Resolution.Daily) for bar in history: self.indicators[equity]['SMA']['Period-20'].Update(bar.EndTime, bar.Close) if not self.indicators[equity]['SMA']['Period-200'].IsReady: history = self.History(equity, 200, Resolution.Daily) for bar in history: self.indicators[equity]['SMA']['Period-200'].Update(bar.EndTime, bar.Close) self.indicators[equity]['RSI']['Period-5'].Update(self.Time, self.Securities[equity].Close) self.indicators[equity]['RSI']['Period-10'].Update(self.Time, self.Securities[equity].Close) self.indicators[equity]['RSI']['Period-14'].Update(self.Time, self.Securities[equity].Close) self.indicators[equity]['RSI']['Period-60'].Update(self.Time, self.Securities[equity].Close) self.indicators[equity]['RSI']['Period-70'].Update(self.Time, self.Securities[equity].Close) self.indicators[equity]['SMA']['Period-20'].Update(self.Time, self.Securities[equity].Close) self.indicators[equity]['SMA']['Period-200'].Update(self.Time, self.Securities[equity].Close) # Implement the main decision tree for the algorithm # If the current price of SPY is above its 200-day SMA price if self.Securities['SPY'].Close > self.indicators['SPY']['SMA']['Period-200'].Current.Value: # If the 10-day RSI of TQQQ is above 79 if self.indicators['TQQQ']['RSI']['Period-10'].Current.Value > 79: # Buy UVXY self.SetHoldings("UVXY", 1) else: # If the 10-day RSI of SPXL is above 80 if self.indicators['SPXL']['RSI']['Period-10'].Current.Value > 80: # Buy UVXY self.SetHoldings("UVXY", 1) else: # If the 5-day return of TQQQ is above 20% if self.CalculateReturn('TQQQ', 5) > 0.2: # If the 10-day RSI of TQQQ is below 31 if self.indicators['TQQQ']['RSI']['Period-10'].Current.Value < 31: # Buy TQQQ self.SetHoldings("TQQQ", 1) else: # Buy one asset from the list [UVXY, SQQQ] with the highest 10-day RSI if self.indicators['UVXY']['RSI']['Period-10'].Current.Value > self.indicators['SQQQ']['RSI']['Period-10'].Current.Value: self.SetHoldings("UVXY", 1) else: self.SetHoldings("SQQQ", 1) else: # Buy TQQQ self.SetHoldings("TQQQ", 1) else: # If the 10-day RSI of TQQQ is below 31 if self.indicators['TQQQ']['RSI']['Period-10'].Current.Value < 31: # Buy TECL self.SetHoldings("TECL", 1) else: # If the 10-day RSI of SMH is below 30 if self.indicators['SMH']['RSI']['Period-10'].Current.Value < 30: # Buy SOXL self.SetHoldings("SOXL", 1) else: # If the 10-day RSI of DIA is below 27 if self.indicators['DIA']['RSI']['Period-10'].Current.Value < 27: # Buy UDOW self.SetHoldings("UDOW", 1) else: # If the 14-day RSI of SPY is below 28 if self.indicators['SPY']['RSI']['Period-14'].Current.Value < 28: # Buy URPO self.SetHoldings("URPO", 1) else: # Allocate 50% of the portfolio to Group 1 and 50% to Group 1 self.Group1() self.Group2() def Group1(self): # Group 1: If the 200-day return of QQQ is below -20% if self.CalculateReturn('QQQ', 200) < -0.2: # If the current price of QQQ is below its 20-day SMA price if self.Securities['QQQ'].Close < self.indicators['QQQ']['SMA']['Period-20'].Current.Value: # If the 60-day return of QQQ is below -12% if self.CalculateReturn('QQQ', 60) < -0.12: # Allocate 50% of the portfolio to Group 3 and 50% to Group 4 self.Group3() self.Group4() else: # If the 10-day RSI of TLT is above the 10-day RSI of SQQQ if self.indicators['TLT']['RSI']['Period-10'].Current.Value > self.indicators['SQQQ']['RSI']['Period-10'].Current.Value: # Buy TQQQ self.SetHoldings("TQQQ", 0.5) else: # Buy SQQQ self.SetHoldings("SQQQ", 0.5) else: # If the 10-day RSI of SQQQ is below 31 if self.indicators['SQQQ']['RSI']['Period-10'].Current.Value < 31: # Buy PSQ self.SetHoldings("PSQ", 0.5) else: # Choose one asset from the list [QQQ, SMH] with the highest 10-day RSI if self.indicators['QQQ']['RSI']['Period-10'].Current.Value > self.indicators['SMH']['RSI']['Period-10'].Current.Value: self.SetHoldings("QQQ", 0.5) else: self.SetHoldings("SMH", 0.5) else: # If the current price of QQQ is below its 20-day SMA price if self.Securities['QQQ'].Close < self.indicators['QQQ']['SMA']['Period-20'].Current.Value: # If the 10-day RSI of TLT is above the 10-day RSI of SQQQ if self.indicators['TLT']['RSI']['Period-10'].Current.Value > self.indicators['SQQQ']['RSI']['Period-10'].Current.Value: # Buy TQQQ self.SetHoldings("TQQQ", 0.5) else: # Buy SQQQ self.SetHoldings("SQQQ", 0.5) else: # If the 10-day RSI of SQQQ is below 31 if self.indicators['SQQQ']['RSI']['Period-10'].Current.Value < 31: # Buy SQQQ self.SetHoldings("SQQQ", 0.5) else: # If the 10-day return of QQQ is above 5.5% if self.CalculateReturn('QQQ', 10) > 0.055: # Buy SQQQ self.SetHoldings("SQQQ", 0.5) else: # Choose one asset from the list [TQQQ, SOXL] with the highest 10-day RSI if self.indicators['TQQQ']['RSI']['Period-10'].Current.Value > self.indicators['SOXL']['RSI']['Period-10'].Current.Value: self.SetHoldings("TQQQ", 0.5) else: self.SetHoldings("SOXL", 0.5) def Group2(self): # Group 2: If the current price of QQQ is below its 20-day SMA price if self.Securities['QQQ'].Close < self.indicators['QQQ']['SMA']['Period-20'].Current.Value: # If the 60-day return of QQQ is below -12% if self.CalculateReturn('QQQ', 60) < -0.12: # Allocate 50% of the portfolio to Group 3 and 50% to Group 4 self.Group3() self.Group4() else: # If the 10-day RSI of TLT is above the 10-day RSI of SQQQ if self.indicators['TLT']['RSI']['Period-10'].Current.Value > self.indicators['SQQQ']['RSI']['Period-10'].Current.Value: # Buy TQQQ self.SetHoldings("TQQQ", 0.5) else: # Buy SQQQ self.SetHoldings("SQQQ", 0.5) else: # If the 10-day RSI of SQQQ is below 31 if self.indicators['SQQQ']['RSI']['Period-10'].Current.Value < 31: # Buy QQQ self.SetHoldings("QQQ", 0.5) else: # If the 70-day return of QQQ is below -15% if self.CalculateReturn('QQQ', 70) < -0.15: # Choose one asset from the list [TQQQ, SOXL] with the highest 10-day RSI if self.indicators['TQQQ']['RSI']['Period-10'].Current.Value > self.indicators['SOXL']['RSI']['Period-10'].Current.Value: self.SetHoldings("TQQQ", 0.5) else: self.SetHoldings("SOXL", 0.5) else: # Choose two assets from the list [SPY, QQQ, DIA, XLP] with the highest 15 day return and weigh the picks equally equities = ["SPY", "QQQ", "DIA", "XLP"] returns = {} for equity in equities: returns[equity] = self.CalculateReturn(equity, 15) sorted_returns = sorted(returns.items(), key=lambda x: x[1], reverse=True) top_2_equities = sorted_returns[:2] self.SetHoldings(top_2_equities[0][0], 0.25) self.SetHoldings(top_2_equities[1][0], 0.25) def Group3(self): # If the current price of SPY is above its 20-day SMA price if self.Securities['SPY'].Close > self.indicators['SPY']['SMA']['Period-20'].Current.Value: # Buy SPY self.SetHoldings("SPY", 0.25) else: # If the 10-day RSI of TLT is above the 10-day RSI of SQQQ if self.indicators['TLT']['RSI']['Period-10'].Current.Value > self.indicators['SQQQ']['RSI']['Period-10'].Current.Value: # Buy QQQ self.SetHoldings("QQQ", 0.25) else: # Buy PSQ self.SetHoldings("PSQ", 0.25) def Group4(self): # If the 10-day RSI of TLT is above the 10-day RSI of SQQQ if self.indicators['TLT']['RSI']['Period-10'].Current.Value > self.indicators['SQQQ']['RSI']['Period-10'].Current.Value: # Buy QQQ self.SetHoldings("QQQ", 0.25) else: # Buy PSQ self.SetHoldings("PSQ", 0.25)