Overall Statistics
Total Orders
2113
Average Win
3.69%
Average Loss
-2.03%
Compounding Annual Return
38.255%
Drawdown
41.700%
Expectancy
0.384
Start Equity
5000
End Equity
1797256.00
Net Profit
35845.120%
Sharpe Ratio
1.1
Sortino Ratio
1.105
Probabilistic Sharpe Ratio
62.191%
Loss Rate
51%
Win Rate
49%
Profit-Loss Ratio
1.82
Alpha
0.206
Beta
0.528
Annual Standard Deviation
0.218
Annual Variance
0.048
Information Ratio
0.817
Tracking Error
0.215
Treynor Ratio
0.454
Total Fees
$39045.29
Estimated Strategy Capacity
$48000000.00
Lowest Capacity Asset
XLU RGRPZX100F39
Portfolio Turnover
22.51%
from AlgorithmImports import *

class RSIRebalanceStrategy(QCAlgorithm):

    def Initialize(self):
        self.set_start_date(2007, 1, 1)
        self.set_cash(5000)

        self.set_warmup(timedelta(days=250))

        self.qqq = self.add_equity("QQQ", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).Symbol
        self.qld = self.add_equity("TQQQ", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).Symbol
        self.spy = self.add_equity("SPY", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).Symbol
        self.itot = self.add_equity("VT", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).Symbol
        self.xlp = self.add_equity("XLP", Resolution.DAILY).Symbol
        self.xlu = self.add_equity("XLU", Resolution.DAILY).Symbol
        self.bil = self.add_equity("BIL", Resolution.DAILY).Symbol
        self.vixy = self.add_equity("UVXY", Resolution.DAILY).Symbol

        self.qqq_rsi = self.rsi(self.qqq, 10)
        self.spy_sma_200 = self.sma(self.spy, 200)
        self.spy_sma_30 = self.sma(self.spy, 30)

        self.schedule.on(self.date_rules.every_day(), self.time_rules.after_market_close(self.spy, 0), self.Rebalance)
        self.schedule.on(self.date_rules.week_end(), self.time_rules.after_market_close(self.spy, 0), self.add_cash)

    def add_cash(self): 
        self.portfolio.cash_book["USD"].add_amount(75)

    def Rebalance(self):
        if not self.qqq_rsi.IsReady or not self.spy_sma_200.IsReady or not self.spy_sma_30.IsReady:
            return

        rsi_value = self.qqq_rsi.Current.Value
        spy_price = self.securities[self.spy].Price
        spy_sma_200 = self.spy_sma_200.Current.Value
        spy_sma_30 = self.spy_sma_30.Current.Value

        if rsi_value > 79:
            liquidate = not self.portfolio[self.vixy].invested
            self.set_holdings(self.vixy, 1, liquidate)
        elif rsi_value < 31:
            liquidate = not self.portfolio[self.qld].invested
            self.set_holdings(self.qld, 1, liquidate)
        elif spy_price > spy_sma_200:
            if spy_price > spy_sma_30:
                liquidate = not self.portfolio[self.qqq].invested
                self.set_holdings(self.qqq, 1, liquidate)
            else:
                # self.set_holdings([PortfolioTarget(self.xlp, 0.5), PortfolioTarget(self.xlu, 0.5)], True)
                liquidate = not self.portfolio[self.xlu].invested
                self.set_holdings(self.xlu, 1, liquidate)

        else:
            if spy_price > spy_sma_30:
                # self.set_holdings([PortfolioTarget(self.xlp, 0.5), PortfolioTarget(self.xlu, 0.5)], True)
                liquidate = not self.portfolio[self.xlu].invested
                self.set_holdings(self.xlu, 1, liquidate)

            else:
                liquidate = not self.portfolio[self.bil].invested
                self.set_holdings(self.bil, 1, liquidate)