Overall Statistics
Total Trades
15
Average Win
0.97%
Average Loss
-0.68%
Compounding Annual Return
0.060%
Drawdown
5.800%
Expectancy
0.037
Net Profit
0.127%
Sharpe Ratio
0.031
Probabilistic Sharpe Ratio
4.534%
Loss Rate
57%
Win Rate
43%
Profit-Loss Ratio
1.42
Alpha
-0.002
Beta
0.064
Annual Standard Deviation
0.041
Annual Variance
0.002
Information Ratio
-0.33
Tracking Error
0.155
Treynor Ratio
0.019
Total Fees
$482.20
Estimated Strategy Capacity
$1900000.00
Lowest Capacity Asset
BIL TT1EBZ21QWKL
# region imports
from AlgorithmImports import *
# endregion

class AdaptableYellowLeopard(QCAlgorithm):

    def Initialize(self):
        start = datetime(2021, 1, 1)   # Start date
        end = datetime(2024, 12, 30)    # End date
        cash = 1000000                  # Starting capital
        self.period = 200               # rolling period to consider for drawup and drawdown calculations

        self.SetStartDate(start)  # Set Start Date
        self.SetEndDate(end)
        self.SetCash(cash)  # Set Strategy Cash

        self.AddEquity("SPY", Resolution.Minute)
        self.AddEquity("BIL", Resolution.Minute)
        self.AddEquity("TLT", Resolution.Minute)
        self.AddEquity("IEF", Resolution.Minute)
        self.AddEquity("IAU", Resolution.Minute)
        self.AddEquity("HYG", Resolution.Minute)
        # self.AddEquity("VCLT", Resolution.Minute)
        self.AddEquity("QQQ", Resolution.Minute)
        self.AddEquity("VBR", Resolution.Minute)
        # self.AddEquity("VWEHX", Resolution.Minute)

        self.high = RollingWindow[float](self.period)
        self.low = RollingWindow[float](self.period)
        self.close = RollingWindow[float](self.period)

        self.state1 = False
        self.state2 = False
        self.state3 = False

        # self.spy
        # self.Schedule.On(self.DateRules.MonthEnd("SPY", 1), 
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
            self.TimeRules.BeforeMarketClose("SPY", 2),
            self.FunctionBeforeMarketClose)

    def OnData(self, slice: Slice):
        pass

    def LiquidateExisting(self, symbols):

        for symbol in symbols:

            quantity = self.Portfolio[symbol].Quantity 

            if quantity != 0:
                self.MarketOrder(symbol, -quantity, tag=f"Rebalancing {symbol}")

    def FunctionBeforeMarketClose(self):

        self.close = self.Securities['SPY'].Close
        self.high.Add(self.Securities['SPY'].High)  
        self.low.Add(self.Securities['SPY'].Low)

        # self.close = self.Securities['HYG'].Close
        # self.high.Add(self.Securities['HYG'].High)  
        # self.low.Add(self.Securities['HYG'].Low)

        if self.high.IsReady:
            dd = abs((self.close / max(self.high)) - 1) * 100
            du = (1 - (min(self.low) / self.close)) * 100

            if dd == 0:
                dd = .0000001    
            if du == 0:
                du = .0001   

        # if dd != 0:
            ddd = dd
            # ddd = dd / du

            if ddd < 3.75 and not self.state1:
                # 100% SPY
                self.LiquidateExisting(['BIL', 'TLT', 'IAU', 'IEF','VBR'])

                # quantity = self.CalculateOrderQuantity("SPY", 1.0)
                # self.MarketOrder('SPY', quantity, tag='100% SPY')
                quantity = self.CalculateOrderQuantity("SPY", 1.)
                self.MarketOrder('SPY', quantity, tag='100% SPY')
                # quantity = self.CalculateOrderQuantity("VBR", 0.1)
                # self.MarketOrder('VBR', quantity, tag='40% VBR')
                # quantity = self.CalculateOrderQuantity("IEF", 0.1)
                # self.MarketOrder('IEF', quantity, tag='40% IEF')

                self.state1 = True
                self.state2 = False
                self.state3 = False

            if ddd >= 3.75 and not self.state2:
                # 50% BIL, 40% TLT, 10% IAU
                self.LiquidateExisting(['SPY','QQQ','IEF', 'VBR'])
                # self.LiquidateExisting(['QQQ'])
                quantity = self.CalculateOrderQuantity("BIL", .7)
                self.MarketOrder('BIL', quantity, tag='50% BIL')

                # quantity = self.CalculateOrderQuantity("TLT", 0.2)
                # self.MarketOrder('TLT', quantity, tag='40% TLT')

                # quantity = self.CalculateOrderQuantity("IEF", 0.17)
                # self.MarketOrder('IEF', quantity, tag='40% IEF')

                # quantity = self.CalculateOrderQuantity("IAU", 0.30)
                # self.MarketOrder('IAU', quantity, tag='10% IAU')

                # quantity = self.CalculateOrderQuantity("VBR", 0.33)
                # self.MarketOrder('VBR', quantity, tag='10% VBR')

                # quantity = self.CalculateOrderQuantity("BIL", 0.25)
                # self.MarketOrder('BIL', quantity, tag='50% BIL')

                # quantity = self.CalculateOrderQuantity("TLT", 0.2)
                # self.MarketOrder('TLT', quantity, tag='40% TLT')

                # quantity = self.CalculateOrderQuantity("IAU", 0.5)
                # self.MarketOrder('IAU', quantity, tag='10% IAU')

                self.state2 = True
                self.state1 = False
                self.state3 = False

            # if 1.2 >= ddd >= 0.8 and not self.state3:
            #     # 50% SPY, 50% BIL
            #     self.LiquidateExisting(['TLT', 'IAU'])

            #     quantity = self.CalculateOrderQuantity("SPY", 0.25)
            #     self.MarketOrder('SPY', quantity, tag='50% SPY')

            #     quantity = self.CalculateOrderQuantity("BIL", 0.25)
            #     self.MarketOrder('BIL', quantity, tag='50% BIL')
            #     self.state3 = True
            #     self.state1 = False
            #     self.state2 = False