Overall Statistics
Total Orders
694
Average Win
1.67%
Average Loss
-0.29%
Compounding Annual Return
29.279%
Drawdown
11.700%
Expectancy
2.248
Start Equity
100000
End Equity
819958.94
Net Profit
719.959%
Sharpe Ratio
1.091
Sortino Ratio
1.511
Probabilistic Sharpe Ratio
82.944%
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
5.75
Alpha
0.189
Beta
-0.151
Annual Standard Deviation
0.163
Annual Variance
0.027
Information Ratio
0.413
Tracking Error
0.245
Treynor Ratio
-1.177
Total Fees
$0.00
Estimated Strategy Capacity
$1600000.00
Lowest Capacity Asset
BIL TT1EBZ21QWKL
Portfolio Turnover
8.18%
Drawdown Recovery
356
# region imports
from AlgorithmImports import *
# endregion

class QuantLeague(QCAlgorithm):
    def initialize(self):
        self.set_brokerage_model(BrokerageName.ALPACA) 
        self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.RAW

        self.set_start_date(2018, 1, 1)
        self.set_cash(100000)

        tqqq = self.add_equity("TQQQ", Resolution.MINUTE)
        self.tqqq = tqqq.Symbol

        self.uvxy = self.add_equity("UVXY", Resolution.MINUTE)
        self.bil = self.add_equity("BIL", Resolution.MINUTE)

        self.rsi3 = RelativeStrengthIndex(3)
        self.rsi4 = RelativeStrengthIndex(4)
        self.rsi5 = RelativeStrengthIndex(5)
        self.rsi6 = RelativeStrengthIndex(6)
        self.rsi7 = RelativeStrengthIndex(7)
        self.rsi8 = RelativeStrengthIndex(8)
        self.rsi9 = RelativeStrengthIndex(9)
        self.rsi10 = RelativeStrengthIndex(10)

        self.set_warm_up(20 * 390, Resolution.MINUTE)  # 20 days * 390 minutes per day

    def on_data(self, slice):
        if self.time.hour == 15 and self.time.minute == 45:
            # Get daily history and update RSI indicators
            history = self.history(self.tqqq, 20, Resolution.DAILY)
            for index, row in history.iterrows():
                time = index[1]

                close_price = float(row['close'])

                self.rsi3.update(time, close_price)
                self.rsi4.update(time, close_price)
                self.rsi5.update(time, close_price)
                self.rsi6.update(time, close_price)
                self.rsi7.update(time, close_price)
                self.rsi8.update(time, close_price)
                self.rsi9.update(time, close_price)
                self.rsi10.update(time, close_price)
            
            # Update with current bar close
            if slice.bars.contains_key(self.tqqq):
                bar = slice.bars[self.tqqq]
                time = bar.end_time

                close_price = bar.close

                self.rsi3.update(time, close_price)
                self.rsi4.update(time, close_price)
                self.rsi5.update(time, close_price)
                self.rsi6.update(time, close_price)
                self.rsi7.update(time, close_price)
                self.rsi8.update(time, close_price)
                self.rsi9.update(time, close_price)
                self.rsi10.update(time, close_price)

            if not self.rsi10.is_ready:
                return
            
            if self.is_warming_up:
                return

            uvxyCount = 0
            bilCount = 0

            if self.rsi3.current.value > 95:
                uvxyCount += 1
            else: 
                bilCount += 1

            if self.rsi4.current.value > 93:
                uvxyCount += 1
            else: 
                bilCount += 1

            if self.rsi5.current.value > 90:
                uvxyCount += 1
            else: 
                bilCount += 1

            if self.rsi6.current.value > 88:
                uvxyCount += 1
            else: 
                bilCount += 1

            if self.rsi7.current.value > 86:
                uvxyCount += 1
            else: 
                bilCount += 1

            if self.rsi8.current.value > 83:
                uvxyCount += 1
            else: 
                bilCount += 1

            if self.rsi9.current.value > 79:
                uvxyCount += 1
            else: 
                bilCount += 1

            if self.rsi10.current.value > 76:
                uvxyCount += 1
            else: 
                bilCount += 1

            bilWeigth = bilCount / (bilCount + uvxyCount)
            uvxyWeigth = uvxyCount / (bilCount + uvxyCount)

            self.set_holdings([PortfolioTarget("UVXY", uvxyWeigth), PortfolioTarget("BIL", bilWeigth)])