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)