Overall Statistics
Total Trades
1129
Average Win
0.32%
Average Loss
-0.36%
Compounding Annual Return
31.980%
Drawdown
11.900%
Expectancy
0.310
Net Profit
87.048%
Sharpe Ratio
1.832
Sortino Ratio
2.509
Probabilistic Sharpe Ratio
95.948%
Loss Rate
31%
Win Rate
69%
Profit-Loss Ratio
0.89
Alpha
0.187
Beta
-0.014
Annual Standard Deviation
0.102
Annual Variance
0.01
Information Ratio
0.878
Tracking Error
0.19
Treynor Ratio
-12.959
Total Fees
$1962.48
Estimated Strategy Capacity
$700000.00
Lowest Capacity Asset
VIXM UT076X30D0MD
Portfolio Turnover
7.45%
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class OffseasonCocktail15Strategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.OffseasonCocktail15()
    def OffseasonCocktail15(self):
        self.SimpleVTI()
        self.SimpleVGT()
        self.SimpleVXUS()
        self.ManagedFutures()

    def SimpleVTI(self):
        if RSI(self.algorithm, 'VIXM', 10) > 70:
            AH(self.algorithm, 'BIL', 3, 0.4)
        elif SMA(self.algorithm, 'VTI', 21) > SMA(self.algorithm, 'VTI', 210):
            if RSI(self.algorithm, 'TLT', 60) < 50:
                AH(self.algorithm, 'VDC', 3, 0.1143)
            else:
                AH(self.algorithm, 'VTI', 3, 0.4)
        elif RSI(self.algorithm, 'VTI', 10) < 30:
            if GetCurrentPrice(self.algorithm, 'VTI') > SMA(self.algorithm, 'VTI', 31):
                AH(self.algorithm, 'VTI', 3, 0.4)
            else:
                AH(self.algorithm, 'BIL', 3, 0.4)
        elif GetCurrentPrice(self.algorithm, 'SPY') > SMA(self.algorithm, 'SPY', 200):
            AH(self.algorithm, 'VTI', 3, 0.4)
        elif RSI(self.algorithm, 'QQQ', 10) < 30:
            AH(self.algorithm, 'QLD', 3, 0.1143)
        elif RSI(self.algorithm, 'QQQ', 10) > 80:
            AH(self.algorithm, 'SH', 3, 0.1143)
        else:
            AH(self.algorithm, 'VTI', 3, 0.4)

    def SimpleVGT(self):
        if RSI(self.algorithm, 'VIXM', 10) > 70:
            AH(self.algorithm, 'BIL', 3, 0.4)
        elif SMA(self.algorithm, 'QQQ', 21) > SMA(self.algorithm, 'QQQ', 210):
            if RSI(self.algorithm, 'TLT', 60) < 50:
                AH(self.algorithm, 'VDC', 3, 0.1143)
            else:
                AH(self.algorithm, 'VGT', 3, 0.4)
        elif RSI(self.algorithm, 'QQQ', 10) < 30:
            if GetCurrentPrice(self.algorithm, 'SPY') > SMA(self.algorithm, 'SPY', 31):
                AH(self.algorithm, 'VGT', 3, 0.4)
            else:
                AH(self.algorithm, 'BIL', 3, 0.4)
        elif GetCurrentPrice(self.algorithm, 'SPY') > SMA(self.algorithm, 'SPY', 200):
            AH(self.algorithm, 'VGT', 3, 0.4)
        elif RSI(self.algorithm, 'QQQ', 10) < 30:
            AH(self.algorithm, 'QLD', 3, 0.1143)
        elif RSI(self.algorithm, 'QQQ', 10) > 80:
            AH(self.algorithm, 'SH', 3, 0.1143)
        else:
            AH(self.algorithm, 'VGT', 3, 0.4)

    def SimpleVXUS(self):
        if RSI(self.algorithm, 'VIXM', 10) > 70:
            AH(self.algorithm, 'BIL', 3, 0.4)
        elif SMA(self.algorithm, 'VEA', 21) > SMA(self.algorithm, 'VEA', 210):
            if RSI(self.algorithm, 'TLT', 60) < 50:
                AH(self.algorithm, 'VDC', 3, 0.1143)
            else:
                AH(self.algorithm, 'VXUS', 3, 0.4)
        elif RSI(self.algorithm, 'VEA', 10) < 30:
            if GetCurrentPrice(self.algorithm, 'VEA') > SMA(self.algorithm, 'VEA', 31):
                AH(self.algorithm, 'VXUS', 3, 0.4)
            else:
                AH(self.algorithm, 'BIL', 3, 0.4)
        elif GetCurrentPrice(self.algorithm, 'VEA') > SMA(self.algorithm, 'VEA', 200):
            AH(self.algorithm, 'VXUS', 3, 0.4)
        elif RSI(self.algorithm, 'QQQ', 10) < 29:
            AH(self.algorithm, 'QLD', 3, 0.1143)
        elif RSI(self.algorithm, 'QQQ', 10) > 80:
            AH(self.algorithm, 'SH', 3, 0.1143)
        else:
            AH(self.algorithm, 'VXUS', 3, 0.4)

    def ManagedFutures(self):
        AH(self.algorithm, ['CTA', 'KMLM'], 3, 0.1)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class OilandVolatilityQuantconnectStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.OilAndVolatility()

    def OilAndVolatility(self):
        if RSI(self.algorithm, 'NRGU', 10) < 12:
            AH(self.algorithm, ['NRGU'], 12, 1)
        else:
            if MaxDD(self.algorithm, 'NRGU', 9) > 13:
                if RSI(self.algorithm, 'NRGU', 10) < 25:
                    AH(self.algorithm, 'SHV', 12, 1)
                else:
                    AH(self.algorithm, 'SVXY', 12, 1)
            else:
                if RSI(self.algorithm, 'NRGU', 10) > 78:
                    AH(self.algorithm, 'VIXM', 12, 1)
                else:
                    AH(self.algorithm, 'SHV', 12, 1)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class Opus12NotBoringGoldenPonyVolHedgeAAWV16BStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.Opus12()

    def Opus12(self):
        self.EfficientCore()
        self.VolatilityHedge()
        self.SectorMomentum()
        self.LargeCapValue()
        self.CommodityMomentum()
        self.NotBoring()
        self.GoldenPony()
        self.VolHedge()
        self.AAWV16()

    def EfficientCore(self):
        Sort(self.algorithm, "CumReturn",
             ["NTSX"], 200, True, 1, 11, 1)
        Sort(self.algorithm, "IV", ["GLD", "DBMF"], 30, False, 1, 11, 0.25)

    def VolatilityHedge(self):

        if RSI(self.algorithm, "VIXY", 97) > 54:
            if GetCurrentPrice(self.algorithm, 'QQQ') > SMA(self.algorithm, 'QQQ', 25):
                Sort(self.algorithm, "RSI", [
                     "QLD", "SPUU"], 21, False, 1, 11, 0.75)
            else:
                AH(self.algorithm, ['SHY', 'SUB', 'BSV', 'BIL'], 11, 0.25)

        else:
            Sort(self.algorithm, "SMADayRet",
                 ["BND", "BIL"], 60, True, 1, 11, 0.3)
            if CumReturn(self.algorithm, 'BND', 60) > CumReturn(self.algorithm, 'BIL', 60):
                if MaxDD(self.algorithm, 'SPY', 10) < 5:
                    Sort(self.algorithm, "SMADayRet", [
                         "UPRO", "TECL", "TQQQ", "SOXL", "FAS"], 10, False, 4, 11, 0.75)
                else:
                    Sort(self.algorithm, "SMADayRet", [
                         "SPY", "RSP", "RPV", "QUAL", "BTAL"], 10, True, 1, 11, 0.75)
            else:
                if SMADayRet(self.algorithm, 'TLT', 15) < 0:
                    if GetCurrentPrice(self.algorithm, 'SPY') > SMA(self.algorithm, 'SPY', 25):
                        Sort(self.algorithm, "RSI", [
                             "XLP", "XLE", "BTAL", "XLY", "XLF"], 10, False, 3, 11, 0.6)
                    else:
                        Sort(self.algorithm, "RSI", [
                             "XLP", "XLE", "SDS", "SQQQ", "BTAL"], 10, False, 3, 11, 0.6)
                    AH(self.algorithm, 'USDU', 11, 0.4)
                else:
                    if SMADayRet(self.algorithm, 'SPY', 25) > SMADayRet(self.algorithm, 'QUAL', 25):
                        if CumReturn(self.algorithm, 'QQQ', 5) < -5:
                            Sort(self.algorithm, "RSI", [
                                 "UPRO", "SSO", "TQQQ", "TECL"], 5, False, 1, 11, 0.75)
                        else:
                            Sort(self.algorithm, "CumReturn", [
                                 "RSP", "RPV", "QUAL", "BTAL"], 10, True, 1, 11, 0.75)
                    else:
                        Sort(self.algorithm, "CumReturn", [
                             "SCHD", "RSP", "RPV", "QUAL", "BTAL", "XLP", "XLF"], 10, True, 1, 11, 0.75)

    def SectorMomentum(self):
        Sort(self.algorithm, "CumReturn", [
             "VDE", "VNQ", "VHT", "VFH", "VOX", "VPU", "VAW", "VGT", "VIS", "VDC", "VCR"], 200, True, 2, 11, 0.25)

    def LargeCapValue(self):
        Sort(self.algorithm, "IV", ["VLUE", "FNDX",
             "VTV", "RWL"], 21, False, 1, 11, 0.2)

    def CommodityMomentum(self):
        Sort(self.algorithm, "CumReturn", [
             "DBA", "DBB", "DBO", "URA", "WOOD", "GLD", "DBE"], 42, True, 6, 11, 0.15/6)

    def NotBoring(self):

        if MaxDD(self.algorithm, 'QQQ', 10) > 6:
            self.RiskOff()
        else:
            self.RiskOn_CoreRiskParity()

    def RiskOff(self):
        if MaxDD(self.algorithm, 'TMF', 10) > 7:
            self.RiskOff()
        else:
            Sort(self.algorithm, "IV", [
                 "GLD", "UUP", "FAS", "TQQQ", "TMF"], 45, False, 1, 11, 0.75)

    def RiskOn_CoreRiskParity(self):
        Sort(self.algorithm, "IV", [
             "TMF", "FAS", "TQQQ"], 45, False, 1, 11, 1)

    def GoldenPony(self):
        AH(self.algorithm, ['NTSX', 'DBMF', 'FAAR', 'COM', 'RLY', 'GAA', 'TRTY',
           'GDMA', 'FTLS', 'MNA', 'VAMO', 'GMOM', 'SHV', 'ICSH', 'CCOR'], 11, 1/15)

    def VolHedge(self):
        if MaxDD(self.algorithm, 'SPY', 4) > 6:
            if CumReturn(self.algorithm, 'UVXY', 45) < 500:
                Sort(self.algorithm, "IV", [
                     "UVXY", "SHY", "GLD", "DBMF", "COM", "FAAR", "FTLS", "CCOR"], 45, False, 1, 11, 0.5)
            else:
                Sort(self.algorithm, "IV", [
                     "SHY", "GLD", "DBMF", "COM", "FAAR", "FTLS", "CCOR"], 45, False, 1, 11, 0.5)
        else:
            if MaxDD(self.algorithm, 'SPY', 15) > 11:
                if CumReturn(self.algorithm, 'UVXY', 45) < 500:
                    Sort(self.algorithm, "IV", [
                         "UVXY", "SHY", "GLD", "DBMF", "COM", "FAAR", "FTLS", "CCOR"], 45, False, 1, 11, 0.5)
                else:
                    Sort(self.algorithm, "IV", [
                         "SHY", "GLD", "DBMF", "COM", "FAAR", "FTLS", "CCOR"], 45, False, 1, 11, 0.5)
            else:
                Sort(self.algorithm, "IV", [
                     "SHY", "GLD", "DBMF", "COM", "FAAR", "FTLS", "CCOR"], 45, False, 1, 11, 0.5)

    def AAWV16(self):
        Sort(self.algorithm, "VGLT", "VGLT", 100, True, 1, 11, 0.6)
        Sort(self.algorithm, "VGIT", "VGIT", 100, True, 1, 11, 0.4)
        if CumReturn(self.algorithm, 'BND', 60) > CumReturn(self.algorithm, 'BIL', 60):
            if CumReturn(self.algorithm, 'QQQ', 5) < -5:
                Sort(self.algorithm, "CumReturn", [
                     "TMF", "TYD"], 21, True, 1, 11, 0.6)
                AH(self.algorithm, 'TYD', 11, 0.4)
            else:
                Sort(self.algorithm, "CumReturn", [
                     "RSP", "RPV", "QUAL", "BTAL", "XLP", "XLF"], 10, True, 1, 11, 0.75)
        else:
            Sort(self.algorithm, "RSI", [
                 "TMV", "TYO", "USDU"], 20, False, 1, 11, 0.6)
            AH(self.algorithm, 'USDU', 11, 0.4)
        if EMA(self.algorithm, 'DBC', 100) > EMA(self.algorithm, 'DBC', 300):
            if RSI(self.algorithm, 'DBC', 60) > RSI(self.algorithm, 'UUP', 60):
                AH(self.algorithm, 'PDBC', 11, 1)
            else:
                if RSI(self.algorithm, 'GLD', 60) < RSI(self.algorithm, 'BND', 60):
                    Sort(self.algorithm, "RSI", [
                         "GLD", "SLV", "GLTR", "PPLT"], 5, False, 1, 11, 0.75)
                else:
                    AH(self.algorithm, 'USDU', 11, 1)
        else:
            Sort(self.algorithm, "CumReturn", [
                 "VNQ", "VNQI", "MORT"], 21, True, 2, 11, 1)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class Opus12QuantconnectStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.Opus12()

    def Opus12(self):
        self.EfficientCore()
        self.VolatilityHedge()
        self.SectorMomentum()
        self.LargeCapValue()
        self.CommodityMomentum()

    def EfficientCore(self):
        AH(self.algorithm, "NTSX", 10, 1)

    def VolatilityHedge(self):
        AH(self.algorithm, ['GLD', 'DBMF'], 10, 1/2)

    def SectorMomentum(self):

        Sort(self.algorithm, "CumReturn", ["VDE", "VNQ", "VHT", "VFH", "VOX",
             "VPU", "VAW", "VGT", "VIS", "VDC", "VCR"], 200, True, 2, 10, 1/4)

    def LargeCapValue(self):
        AH(self.algorithm, ['VLUE', 'FNDX', 'VTV', 'RWL'], 10, 1/5)

    def CommodityMomentum(self):

        self.Agriculture()
        self.BaseMetals()
        self.Oil()
        self.Uranium()
        self.Timber()
        self.Gold()
        self.Energy()

    def Agriculture(self):

        if CumReturn(self.algorithm, "DBA", 42) > CumReturn(self.algorithm, "SHV", 42):
            AH(self.algorithm, "DBA", 10, 1/7)
        else:
            AH(self.algorithm, "SHV", 10, 1/7)

    def BaseMetals(self):
        if CumReturn(self.algorithm, "DBB", 42) > CumReturn(self.algorithm, "SHV", 42):
            AH(self.algorithm, "DBB", 10, 1/7)
        else:
            AH(self.algorithm, "SHV", 10, 1/7)

    def Oil(self):
        if CumReturn(self.algorithm, "DBO", 42) > CumReturn(self.algorithm, "SHV", 42):
            AH(self.algorithm, "DBO", 10, 1/7)
        else:
            AH(self.algorithm, "SHV", 10, 1/7)

    def Uranium(self):
        if CumReturn(self.algorithm, "URA", 42) > CumReturn(self.algorithm, "SHV", 42):
            AH(self.algorithm, "URA", 10, 1/7)
        else:
            AH(self.algorithm, "SHV", 10, 1/7)

    def Timber(self):
        if CumReturn(self.algorithm, "WOOD", 42) > CumReturn(self.algorithm, "SHV", 42):
            AH(self.algorithm, "WOOD", 10, 1/7)
        else:
            AH(self.algorithm, "SHV", 10, 1/7)

    def Gold(self):
        if CumReturn(self.algorithm, "GLD", 42) > CumReturn(self.algorithm, "SHV", 42):
            AH(self.algorithm, "GLD", 10, 1/7)
        else:
            AH(self.algorithm, "SHV", 10, 1/7)

    def Energy(self):
        if CumReturn(self.algorithm, "DBE", 42) > CumReturn(self.algorithm, "SHV", 42):
            AH(self.algorithm, "DBE", 10, 1/7)
        else:
            AH(self.algorithm, "SHV", 10, 1/7)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class Opus14QuantconnectStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.Opus14()

    def Opus14(self):
        self.EfficientCore()
        self.VolatilityHedge()
        self.SectorMomentum()
        self.LargeCapValue()
        self.CommodityMomentum()

    def EfficientCore(self):
        AH(self.algorithm, 'NTSX', 9, 1)

    def VolatilityHedge(self):
        IV(self.algorithm, 'GLD', 30)

    def SectorMomentum(self):
        Sort(self.algorithm, "CumReturn", ["VDE", "VNQ", "VHT", "VFH", "VOX",
             "VPU", "VAW", "VGT", "VIS", "VDC", "VCR"], 200, True, 2, 9, 0.168)

    def LargeCapValue(self):
        IV(self.algorithm, 'VLUE', 21)

    def CommodityMomentum(self):
        if CumReturn(self.algorithm, 'DBA', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'DBA', 9, 1/7)
        else:
            AH(self.algorithm, 'SHV', 9, 1/7)
        if CumReturn(self.algorithm, 'DBB', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'DBB', 9, 1/7)
        else:
            AH(self.algorithm, 'SHV', 9, 1/7)
        if CumReturn(self.algorithm, 'DBO', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'DBO', 9, 1/7)
        else:
            AH(self.algorithm, 'SHV', 9, 1/7)
        if CumReturn(self.algorithm, 'URA', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'URA', 9, 1/7)
        else:
            AH(self.algorithm, 'SHV', 9, 1/7)
        if CumReturn(self.algorithm, 'WOOD', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'WOOD', 9, 1/7)
        else:
            AH(self.algorithm, 'SHV', 9, 1/7)
        if CumReturn(self.algorithm, 'GLD', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'GLD', 9, 1/7)
        else:
            AH(self.algorithm, 'SHV', 9, 1/7)
        if CumReturn(self.algorithm, 'DBE', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'DBE', 9, 1/7)
        else:
            AH(self.algorithm, 'SHV', 9, 1/7)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class Opus69QuantconnectStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.Opus69()

    def Opus69(self):
        self.EfficientCore()
        self.VolatilityHedge()
        self.SectorMomentum()
        self.LargeCapValue()
        self.CommodityMomentum()

    def EfficientCore(self):
        AH(self.algorithm, 'UPRO', 8, 1)

    def VolatilityHedge(self):
        IV(self.algorithm, 'UGL', 30)
        IV(self.algorithm, 'UVXY', 30)

    def SectorMomentum(self):
        Sort(self.algorithm, "CumReturn", ["DIG", "URE", "CURE", "FAS", "TPOR",
             "UPW", "UYG", "ROM", "RXL", "UCC", "UJB"], 200, True, 2, 8, 1/6)

    def LargeCapValue(self):
        sum_IV_assets = IV(self.algorithm, 'UPRO', 45)+IV(self.algorithm, 'TMF', 45)+IV(self.algorithm, 'VIXM', 45)
        AH(self.algorithm, 'UPRO', 14, IV(self.algorithm, 'UPRO', 45)/sum_IV_assets)
        AH(self.algorithm, 'TMF', 14, IV(self.algorithm, 'TMF', 45)/sum_IV_assets)
        AH(self.algorithm, 'VIXM', 14, IV(self.algorithm, 'VIXM', 45)/sum_IV_assets)

    def CommodityMomentum(self):
        self.Agriculture()
        self.BaseMetals()
        self.Oil()
        self.Uranium()
        self.Timber()
        self.Gold()
        self.Energy()

    def Agriculture(self):
        if CumReturn(self.algorithm, 'DBA', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'DBA', 8, 1)
        else:
            AH(self.algorithm, 'SHV', 8, 1)

    def BaseMetals(self):
        if CumReturn(self.algorithm, 'DBB', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'DBB', 8, 1)
        else:
            AH(self.algorithm, 'SHV', 8, 1)

    def Oil(self):
        if CumReturn(self.algorithm, 'UCO', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'UCO', 8, 1)
        else:
            AH(self.algorithm, 'SHV', 8, 1)

    def Uranium(self):
        if CumReturn(self.algorithm, 'URA', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'URA', 8, 1)
        else:
            AH(self.algorithm, 'SHV', 8, 1)

    def Timber(self):
        if CumReturn(self.algorithm, 'WOOD', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'WOOD', 8, 1)
        else:
            AH(self.algorithm, 'SHV', 8, 1)

    def Gold(self):
        if CumReturn(self.algorithm, 'UGL', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'UGL', 8, 1)
        else:
            AH(self.algorithm, 'SHV', 8, 1)

    def Energy(self):
        if CumReturn(self.algorithm, 'DIG', 42) > CumReturn(self.algorithm, 'SHV', 42):
            AH(self.algorithm, 'DIG', 8, 1)
        else:
            AH(self.algorithm, 'SHV', 8, 1)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class OverfitunpoquitoQuantconnectStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.MuricaV2()

    def MuricaV2(self):
        if STD(self.algorithm, 'SPY', 21) < 1.5:
            if STD(self.algorithm, 'SPY', 21) < 1.25:
                    AH(self.algorithm, ['DIS', 'KO', 'AAPL', 'AMZN', 'GOOGL', 'XOM',
                       'UNH', 'HD', 'PG', 'JNJ', 'MSFT', 'WFC'], 7, ((1 - 0.45) / 12))
                    AH(self.algorithm, ['DIS', 'KO', 'AAPL', 'AMZN', 'GOOGL', 'XOM', 'UNH',
                       'HD', 'PG', 'JNJ', 'MSFT', 'WFC'], 7, (((1 - 0.45) / 12) * 0.65))
                    AH(self.algorithm, ['SHV'], 7,
                       (((1 - 0.45) / 12) * 0.35))
            else:
                AH(self.algorithm, ['DIS', 'KO', 'AAPL', 'AMZN', 'GOOGL', 'XOM',
                   'UNH', 'HD', 'PG', 'JNJ', 'MSFT', 'WFC'], 7, ((1 - 0.45) / 12))
                AH(self.algorithm, ['SHV'], 7, 0.45)
        else:
            AH(self.algorithm, ['DIS', 'KO', 'AAPL', 'AMZN', 'GOOGL', 'XOM',
               'UNH', 'HD', 'PG', 'JNJ', 'MSFT', 'WFC'], 7, ((1 - 0.55) / 12))
            AH(self.algorithm, ['SHV'], 7, 0.55)

    def BondYieldExposure(self):

        self.Yield()
        self.Treasuries()

    def Yield(self):

        self.StaticYield()
        self.TheNameBondV2()
        self.FiveYearTreasury()

    def StaticYield(self):
            AH(self.algorithm, ['IEF', 'TIP', 'LQD', 'HYG'], 7, (0.25 / 4))
            AH(self.algorithm, ['IEF', 'TIP', 'LQD',
               'HYG'], 7, ((0.25 / 4) * 0.275))
            AH(self.algorithm, ['IEI'], 7, ((0.25 / 4) * 0.275))

    def Treasuries(self):
        self.SixtyDayCheck()
        self.TwentyDayCheck()
        self.FortyDayCheck()

    def SixtyDayCheck(self):
        if STD(self.algorithm, 'TLT', 60) < 1:
            AH(self.algorithm, ['TMF', 'SHY'], 7, 0.5)
        else:
            AH(self.algorithm, ['SHY', 'UUP', 'GLD', 'XLP'], 7, 0.5)

    def TwentyDayCheck(self):
        if STD(self.algorithm, 'TLT', 20) < 0.5:
            AH(self.algorithm, ['TMF', 'SHY'], 7, 0.5)
        else:
            AH(self.algorithm, ['SHY', 'UUP', 'GLD', 'XLP'], 7, 0.5)

    def FortyDayCheck(self):
        if STD(self.algorithm, 'TLT', 40) < 0.75:
            AH(self.algorithm, ['TMF', 'SHY'], 7, 0.5)
        else:
            AH(self.algorithm, ['SHY', 'UUP', 'GLD', 'XLP'], 7, 0.5)

    def TheNameBondV2(self):
        AH(self.algorithm, ['SHV', 'TLT', 'HYG',
           'GLD', 'UUP'], 7, (0.275 / 5))

    def FiveYearTreasury(self):
        AH(self.algorithm, ['IEI'], 7, 0.2)

    def Preservation(self):
        self.Trend()
        self.Gold()
        self.InflationSpiralHedgeRemix()

    def Trend(self):
        AH(self.algorithm, ['TLT', 'SPY', 'GLD', 'DBC',
           'UUP', 'SHV'], 7, ((0.4 / 2) * 0.7))
        AH(self.algorithm, ['GLD', 'DBC', 'UUP', 'SHV'],
           7, ((0.4 / 2) * 0.3))

    def InflationSpiralHedgeRemix(self):
        self.ConsumerStaples()
        self.CommodityBasketTrend()
        self.GoldTrend()
        self.ShortBondLogicGroup()

    def ConsumerStaples(self):
        if STD(self.algorithm, 'SPY', 21) > 1.25:
            AH(self.algorithm, ['UUP', 'SHV', 'BTAL',
               'GLD'], 7, ((0.2 / 3) * 0.5))
        else:
            AH(self.algorithm, 'XLP', 7, ((0.2 / 3) * 0.5))

        if STD(self.algorithm, 'SPY', 21) > 1.5:
            AH(self.algorithm, ['UUP', 'SHV', 'BTAL',
               'GLD'], 7, ((0.2 / 3) * 0.35))
        else:
            AH(self.algorithm, 'XLP', 7, ((0.2 / 3) * 0.35))

        if STD(self.algorithm, 'SPY', 21) > 1:
            AH(self.algorithm, ['UUP', 'SHV', 'BTAL',
               'GLD'], 7, ((0.2 / 3) * 0.15))
        else:
            AH(self.algorithm, 'XLP', 7, ((0.2 / 3) * 0.15))

    def CommodityBasketTrend(self):
        AH(self.algorithm, ['SHV', 'UUP', 'DBC'], 7, ((0.4 / 3) * 1))

    def GoldTrend(self):
        AH(self.algorithm, ['SHV', 'UUP', 'GLD'], 7, ((0.4 / 3) * 1))

    def ShortBondLogicGroup(self):
        self.TenDayShortBondsLogic()
        self.TwentyDayShortBondsLogic()
        self.FortyDayShortBondsLogic()

    def TenDayShortBondsLogic(self):
        if MDD(self.algorithm, 'TMV', 10) < 8:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

        if MDD(self.algorithm, 'TMV', 10) < 9:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

        if MDD(self.algorithm, 'TMV', 10) < 7:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

    def TwentyDayShortBondsLogic(self):
        if MDD(self.algorithm, 'TMV', 20) < 10:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

        if MDD(self.algorithm, 'TMV', 20) < 9:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

        if MDD(self.algorithm, 'TMV', 20) < 8:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

    def FortyDayShortBondsLogic(self):
        if MDD(self.algorithm, 'TMV', 40) < 13:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

        if MDD(self.algorithm, 'TMV', 40) < 12:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))

        if MDD(self.algorithm, 'TMV', 40) < 11:
            if STD(self.algorithm, 'TLT', 21) > 1:
                AH(self.algorithm, 'TMV', 7, ((0.2 / 3) * 1))
            else:
                AH(self.algorithm, 'VTIP', 7, ((0.2 / 3) * 1))
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class PHASETESTofInflationSpiralHedgeQuantconnStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.PhaseTestOfInflationSpiralHedge()

    def PhaseTestOfInflationSpiralHedge(self):
        if CumReturn(self.algorithm, 'TBT', 60) >= 0.1:
            AH(self.algorithm, 'TBF', 4, 1)
        else:
            AH(self.algorithm, 'QQQ', 4, 1)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class PSQEquivalentQuantconnectStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        AH(self.algorithm, 'SQQQ', 13, 0.55)
        AH(self.algorithm, 'QQQ', 13, 0.45)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class PUBNEWSCHDSPYMovingAverageComboDereckNHTStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm

    def Execute(self):
        self.NewSCHDSPYMovingAverageCombo()

    def NewSCHDSPYMovingAverageCombo(self):
        if SMADayRet(self.algorithm, 'SCHD', 21) > SMADayRet(self.algorithm, 'SJB', 21):
            AH(self.algorithm, ['RSP', 'SCHD'], 14, 1/2)
        else:
            if RSI(self.algorithm, 'QQQ', 10) < 30:
                AH(self.algorithm, 'XLK', 14, 1)
            else:
                AH(self.algorithm, ['BTAL', 'SJB'], 14, 1/2)

            if EMA(self.algorithm, 'SPY', 8) > SMA(self.algorithm, 'SPY', 200):
                AH(self.algorithm, ['SPLV', 'SSO'], 14, 1/2)
            else:
                if RSI(self.algorithm, 'QQQ', 10) < 30:
                    AH(self.algorithm, 'XLK', 14, 1)
                else:
                    AH(self.algorithm, ['UGL', 'XLE'], 14, 1/2)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat


class ParitySwitchingGoldCommoditiesandEnergytStrategy(YellowCatStrat):

    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm
    def Execute(self):
        if SMA(self.algorithm, 'SPY', 21) > SMA(self.algorithm, 'SPY', 210):
            if RSI(self.algorithm, 'SPY', 10) > 80:
                   AH(self.algorithm, 'VIXM',5, 1)
            else:
                if RSI(self.algorithm, 'SPY', 10) < 30:
                    AH(self.algorithm, 'UPRO',5, 1)
                else:
                    self.ParityPhase4aaVWORecessionVolatilityLowInflation()
        else:
            self.ParityPhase4abBNDRecessionVolatilityHighInflation()

    def ParityPhase4aaVWORecessionVolatilityLowInflation(self):
            Sort(self.algorithm,"SMADayRet",("TMV","TBT","UUP","EDZ","SRTY"),253,True,1,5,1/2)
            Sort(self.algorithm,"RSI",("GSY","TMF","SRTY","IAU","UVXY"),10,True,1,5,1/2)

    def ParityPhase4abBNDRecessionVolatilityHighInflation(self):
            Sort(self.algorithm,"SMADayRet",("UUP","TBT","TMV"),40,True,1,5,1)

    def DereckN_sRiskOffTickets(self):
            AH(self.algorithm,('SHV','XLP','GLD','BND','DBC','TLT','IEF'),5,1/7)
#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat

class TQQQFTLTStrategy(YellowCatStrat):
    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm
    def Execute(self):
        if GetCurrentPrice(self.algorithm,'SPY') > SMA(self.algorithm, 'SPY', 200):
            if RSI(self.algorithm, 'TQQQ', 10) > 78:
                AH(self.algorithm, ['SPXU', 'UVXY', 'SQQQ'], 1, 0.33)
            else:
                if RSI(self.algorithm, 'SPXL', 10) > 79:
                    AH(self.algorithm, ['SPXU', 'UVXY', 'SQQQ'], 1, 0.33)
                else:
                    if CumReturn(self.algorithm, 'TQQQ', 4) > 0.2:
                        if RSI(self.algorithm, 'TQQQ', 10) < 31:
                            AH(self.algorithm, 'TQQQ', 1, 1)
                        else:
                            if RSI(self.algorithm, 'UVXY', 10) > RSI(self.algorithm, 'SQQQ', 10):
                                AH(self.algorithm, ['SPXU', 'UVXY', 'SQQQ'], 1, 0.33)
                            else:
                                AH(self.algorithm, 'SQQQ', 1, 1)
                    else:
                        AH(self.algorithm, 'TQQQ', 1, 1)
        else:
            if RSI(self.algorithm, 'TQQQ', 10) < 31:
                AH(self.algorithm, 'TECL', 1, 1)
            else:
                if RSI(self.algorithm, 'SMH', 10) < 30:
                    AH(self.algorithm, 'SOXL', 1, 1)
                else:
                    if RSI(self.algorithm, 'DIA', 10) < 27:
                        AH(self.algorithm, 'UDOW', 1, 1)
                    else:
                        if RSI(self.algorithm, 'SPY', 14) < 28:
                            AH(self.algorithm, 'UPRO', 1, 1)
                        else:
                            self.Group1()
                            self.Group2()

    def Group1(self):
        if CumReturn(self.algorithm, 'QQQ', 200) < -0.2:
            if GetCurrentPrice(self.algorithm,'QQQ') < SMA(self.algorithm, 'QQQ', 20):
                if CumReturn(self.algorithm, 'QQQ', 60) < -0.12:
                    self.Group5()
                    self.Group6()
                else:
                    if RSI(self.algorithm, 'TLT', 10) > RSI(self.algorithm, 'SQQQ', 10):
                        AH(self.algorithm, 'TQQQ', 1, 0.5)
                    else:
                        AH(self.algorithm, 'SQQQ', 1, 0.5)
            else:
                if RSI(self.algorithm, 'SQQQ', 10) < 31:
                    AH(self.algorithm, 'PSQ', 1, 0.5)
                else:
                    if CumReturn(self.algorithm, 'QQQ', 9) > 0.055:
                        AH(self.algorithm, 'PSQ', 1, 0.5)
                    else:
                        if RSI(self.algorithm, 'TQQQ', 10) > RSI(self.algorithm, 'SOXL', 10):
                            AH(self.algorithm, 'TQQQ', 1, 0.5)
                        else:
                            AH(self.algorithm, 'SOXL', 1, 0.5)

    def Group2(self):
        if GetCurrentPrice(self.algorithm,'QQQ') < SMA(self.algorithm, 'QQQ', 20):
            if CumReturn(self.algorithm, 'QQQ', 60) < -0.12:
                self.Group3()
                self.Group4()
            else:
                if RSI(self.algorithm, 'TLT', 10) > RSI(self.algorithm, 'SQQQ', 10):
                    AH(self.algorithm, 'TQQQ', 1, 0.5)
                else:
                    AH(self.algorithm, 'SQQQ', 1, 0.5)
        else:
            if self.algorithm.RSI('TQQQ', 10) > self.algorithm.RSI('SOXL', 10):
                AH(self.algorithm, 'TQQQ', 1, 0.5)
            else:
                AH(self.algorithm, 'SOXL', 1, 0.5)

    def Group3(self):
        if GetCurrentPrice(self.algorithm,'SPY') > SMA(self.algorithm, 'SPY', 20):
            AH(self.algorithm, 'SPY', 1, 0.25)
        else:
            if RSI(self.algorithm, 'TLT', 10) > RSI(self.algorithm, 'SQQQ', 10):
                AH(self.algorithm, 'QQQ', 1, 0.25)
            else:
                AH(self.algorithm, 'PSQ', 1, 0.25)

    def Group4(self):
        if RSI(self.algorithm, 'TLT', 10) > RSI(self.algorithm, 'SQQQ', 10):
            AH(self.algorithm, 'QQQ', 1, 0.25)
        else:
            AH(self.algorithm, 'PSQ', 1, 0.25)

    def Group5(self):
        if GetCurrentPrice(self.algorithm,'SPY') > SMA(self.algorithm, 'SPY', 20):
            AH(self.algorithm, 'SPY', 1, 0.25)
        else:
            if RSI(self.algorithm, 'TLT', 10) > RSI(self.algorithm, 'SQQQ', 10):
                AH(self.algorithm, 'QQQ', 1, 0.25)
            else:
                AH(self.algorithm, 'PSQ', 1, 0.25)
    def Group6(self):
        if RSI(self.algorithm, 'TLT', 10) > RSI(self.algorithm, 'SQQQ', 10):
            AH(self.algorithm, 'QQQ', 1, 0.25)
        else:
            AH(self.algorithm, 'PSQ', 1, 0.25)

#region imports
from AlgorithmImports import *
#endregion


# Your New Python File
from indicators import *
from project.main import YellowCatStrat

class TQQQorNotStrategy(YellowCatStrat):
    def __init__(self, algorithm):
        super().__init__()
        self.algorithm = algorithm
    def Execute(self):
        if RSI(self.algorithm,'TQQQ',10) > 78:
            AH(self.algorithm,['SPXU','UVXY','SQQQ'],2,1/3)
        else:
            if CumReturn(self.algorithm,'TQQQ',6) < -0.12:
                if CumReturn(self.algorithm,'TQQQ',1) > 0.055:
                    AH(self.algorithm,['SPXU','UVXY','SQQQ'],2,1/3)
                else:
                    if RSI(self.algorithm,'TQQQ',10) < 32:
                        AH(self.algorithm,'TQQQ',2,1)
                    else:
                        if MaxDD(self.algorithm,'TMF',10)<0.07:
                            AH(self.algorithm,'TQQQ',2,1)
                        else:
                            AH(self.algorithm,'BIL',2,1)
            else:
                if MaxDD(self.algorithm,'QQQ',10)>0.06:
                    AH(self.algorithm,'BIL',2,1)
                else:
                    if MaxDD(self.algorithm,'TMF',10)>0.07:
                        AH(self.algorithm,'BIL',2,1)
                    else:
                        if GetCurrentPrice(self.algorithm,'QQQ') > SMA(self.algorithm,'QQQ', 25):
                            AH(self.algorithm,'TQQQ',2,1)
                        else:
                            if RSI(self.algorithm,'SPY',60) > 50:
                                if RSI(self.algorithm,'BND',45) > RSI(self.algorithm,'SPY',45):
                                    AH(self.algorithm,'TQQQ',2,1)
                                else:
                                    AH(self.algorithm,'BIL',2,1)
                            else:
                                if RSI(self.algorithm,'IEF',200) < RSI(self.algorithm,'TLT',200):
                                    if RSI(self.algorithm,'BND',45) > RSI(self.algorithm,'SPY',45):
                                        AH(self.algorithm,'TQQQ',2,1)
                                    else:
                                        AH(self.algorithm,'BIL',2,1)
                                else:
                                    AH(self.algorithm,'BIL',2,1)

from AlgorithmImports import *
from project.main import YellowCatStrat
import math
import pandas as pd
from cmath import sqrt
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Data.Custom import *
from QuantConnect.Python import PythonData
import csv
import io
import time
import json
def RSI(algorithm,equity,period):
    extension = min(period*5,250)
    r_w = RollingWindow[float](extension)
    history = algorithm.History(equity,extension - 1,Resolution.Daily)
    for historical_bar in history:
        r_w.Add(historical_bar.Close)
    while r_w.Count < extension:
        current_price = algorithm.Securities[equity].Price
        r_w.Add(current_price)
    if r_w.IsReady:
        average_gain = 0
        average_loss = 0
        gain = 0
        loss = 0
        for i in range(extension - 1,extension - period -1,-1):
            gain += max(r_w[i-1] - r_w[i],0)
            loss += abs(min(r_w[i-1] - r_w[i],0))
        average_gain = gain/period
        average_loss = loss/period
        for i in range(extension - period - 1,0,-1):
            average_gain = (average_gain*(period-1) + max(r_w[i-1] - r_w[i],0))/period
            average_loss = (average_loss*(period-1) + abs(min(r_w[i-1] - r_w[i],0)))/period
        if average_loss == 0:
            return 100
        else:
            rsi = 100 - (100/(1 + average_gain/average_loss))
            return rsi
    else:
        return None
def CumReturn(algorithm,equity,period):
    history = algorithm.History(equity,period,Resolution.Daily)
    closing_prices = pd.Series([bar.Close for bar in history])
    current_price = algorithm.Securities[equity].Price
    closing_prices = closing_prices.append(pd.Series([current_price]))
    first_price = closing_prices.iloc[0]
    if first_price == 0:
        return None
    else:
        return_val = (current_price/first_price) - 1
        return return_val
def STD(algorithm,equity,period):
    r_w = RollingWindow[float](period + 1)
    r_w_return = RollingWindow[float](period)
    history = algorithm.History(equity,period,Resolution.Daily)
    for historical_bar in history:
        r_w.Add(historical_bar.Close)
    while r_w.Count < period + 1:
        current_price = algorithm.Securities[equity].Price
        r_w.Add(current_price)
    for i in range (period,0,-1):
        daily_return = (r_w[i-1]/r_w[i] - 1)
        r_w_return.Add(daily_return)
    dfstd = pd.DataFrame({'r_w_return':r_w_return})
    if r_w.IsReady:
        std = dfstd['r_w_return'].std()
        if std == 0:
            return 0
        else:
            return std
    else:
        return 0
def MaxDD(algorithm,equity,period):
    history = algorithm.History(equity,period - 1,Resolution.Daily)
    closing_prices = pd.Series([bar.Close for bar in history])
    current_price = algorithm.Securities[equity].Price
    closing_prices = closing_prices.append(pd.Series([current_price]))
    rolling_max = closing_prices.cummax()
    drawdowns = (rolling_max - closing_prices)/rolling_max
    max_dd = drawdowns.min()
    return max_dd
def SMA(algorithm,equity,period):
    r_w = RollingWindow[float](period)
    history = algorithm.History(equity,period - 1,Resolution.Daily)
    for historical_bar in history:
        r_w.Add(historical_bar.Close)
    while r_w.Count < period:
        current_price = algorithm.Securities[equity].Price
        r_w.Add(current_price)
    if r_w.IsReady:
        sma = sum(r_w)/period
        return sma
    else:
        return 0
def IV(algorithm,equity,period):
    r_w = RollingWindow[float](period + 1)
    r_w_return = RollingWindow[float](period)
    history = algorithm.History(equity,period,Resolution.Daily)
    for historical_bar in history:
        r_w.Add(historical_bar.Close)
    while r_w.Count < period + 1:
        current_price = algorithm.Securities[equity].Price
        r_w.Add(current_price)
    for i in range (period,0,-1):
        if r_w[i] == 0:
            return 0
        else:
            daily_return = (r_w[i-1]/r_w[i] - 1)
            r_w_return.Add(daily_return)
    dfinverse = pd.DataFrame({'r_w_return':r_w_return})
    if r_w.IsReady:
        std = dfinverse['r_w_return'].std()
        if std == 0:
            return 0
        else:
            inv_vol = 1/std
            return inv_vol
    else:
        return 0
def SMADayRet(algorithm,equity,period):
    r_w = RollingWindow[float](period + 1)
    r_w_return = RollingWindow[float](period)
    history = algorithm.History(equity,period,Resolution.Daily)
    for historical_bar in history:
        r_w.Add(historical_bar.Close)
    while r_w.Count < period + 1:
        current_price = algorithm.Securities[equity].Price
        r_w.Add(current_price)
    for i in range (period,0,-1):
        if r_w[i] == 0:
            return None
        daily_return = (r_w[i-1]/r_w[i] - 1)
        r_w_return.Add(daily_return)
    if r_w.IsReady:
        smareturn = sum(r_w_return)/period
        return smareturn
    else:
        return 0
def EMA(algorithm,equity,period):
    extension = period + 50
    r_w = RollingWindow[float](extension)
    history = algorithm.History(equity,extension - 1,Resolution.Daily)
    for historical_bar in history:
        r_w.Add(historical_bar.Close)
    while r_w.Count < extension:
        current_price = algorithm.Securities[equity].Price
        r_w.Add(current_price)
    if r_w.IsReady:
        total_price = 0
        for i in range(extension - 1,extension - period - 2,-1):
            total_price += r_w[i]
        average_price = total_price/period
        for i in range(extension - period - 2,-1,-1):
            average_price = r_w[i]*2/(period+1) + average_price*(1-2/(period+1))
        return average_price
    else:
        return None

def Sort(algorithm, sort_type, equities, period, reverse, num_assets, number, multiplier):
    # Update the PT value for the given strategy number
    PT = getattr(algorithm, f"PT{number}") * multiplier

    # Define a dictionary to map sort types to functions
    indicator_functions = {
        'EMA': EMA,
        'RSI': RSI,
        'CumReturn': CumReturn,
        'STD': STD,
        'MaxDD': MaxDD,
        'SMA': SMA,
        'IV': IV,
        'SMADayRet': SMADayRet,
        # Add other indicators here as needed
    }

    # Compute the indicator value for each equity
    returns = {}
    for equity in equities:
        indicator_function = indicator_functions.get(sort_type, None)
        if callable(indicator_function):
            indicator_value = indicator_function(algorithm, equity, period)
            if indicator_value is not None:
                returns[equity] = indicator_value

    # Sort the equities based on the indicator values
    sorted_equities = sorted(returns.items(), key=lambda x: x[1], reverse=reverse)

    # Select the top 'num_assets' from the sorted list
    top_equities = sorted_equities[:num_assets]

    # Get the current HT and HTS attributes for the strategy
    HT = getattr(algorithm, f"HT{number}")
    HTS = getattr(algorithm, f"HTS{number}")

    # Assign each of the top equities to the next available slot in HT and HTS
    for equity, value in top_equities:
        for i in HT.keys():
            if HT[i] == 0:
                HT[i] = PT / num_assets  # Distribute PT evenly among the assets
                HTS[i].append(equity)  # Append the asset symbol
                break  # Move to the next asset after appending

    # Update the HT and HTS attributes for the strategy
    setattr(algorithm, f"HT{number}", HT)
    setattr(algorithm, f"HTS{number}", HTS)


def AH(algorithm,equities,PTnumber,multiplier): #AppendHolding
    if not isinstance(equities,list):
        equities = [equities]
    HT = getattr(algorithm,f"HT{PTnumber}")
    HTS = getattr(algorithm,f"HTS{PTnumber}")
    PT = getattr(algorithm,f"PT{PTnumber}") * multiplier
    
    for equity in equities:
        for i in HT.keys():
            if HT[i] == 0:
                HT[i] = PT
                HTS[i].append(equity)
                break

def GetCurrentPrice(algorithm, symbol):
    """
    Gets the current price of a security.

    :param algorithm: The algorithm instance containing the securities.
    :param symbol: The symbol of the security.
    :return: The current price of the security or None if not available.
    """
    if symbol in algorithm.Securities:
        return algorithm.Securities[symbol].Price
    else:
        algorithm.Debug(f"Symbol {symbol} not found in securities.")
        return None

def AHIV(algorithm, assets, period):
    # Calculate sum_IV_assets
    tickers_IV = [f"IV(algorithm, '{ticker}', {period})" for ticker in assets]
    sum_IV_assets = '+'.join(tickers_IV)

    # Execute the sum_IV_assets calculation
    sum_IV_assets_value = eval(sum_IV_assets)

    # Call the AH function for each asset with the calculated portion
    for ticker in assets:
        IV_value = eval(f"IV(algorithm, '{ticker}', {period})")
        portion = IV_value / sum_IV_assets_value
        AH(algorithm, ticker, 14, portion)

def GroupSort(algorithm, filter_type, def_str_method, window, select_type, num_assets, number, multiplier):
    # Invoke the specified method to get a list of equities and their weights
    equities, weights = def_str_method()

    # Define a dictionary to map filter types to their corresponding functions
    indicator_functions = {
        'EMA': EMA,
        'RSI': RSI,
        'CumReturn': CumReturn,
        'STD': STD,
        'MaxDD': MaxDD,
        'SMA': SMA,
        'IV': IV,
        'SMADayRet': SMADayRet,
    }

    # Ensure the filter type is supported
    if filter_type not in indicator_functions:
        raise ValueError(f"Unsupported filter type: {filter_type}")

    # Calculate the weighted indicator values for each equity
    weighted_indicator_values = {}
    for equity, weight in zip(equities, weights):
        indicator_value = indicator_functions[filter_type](algorithm, equity, window)
        if indicator_value is not None:
            weighted_indicator_values[equity] = weight * indicator_value

    # Determine sorting direction
    reverse = True if select_type == 'Top' else False

    # Sort equities based on the weighted indicator values
    sorted_equities = sorted(weighted_indicator_values.items(), key=lambda x: x[1], reverse=reverse)[:num_assets]

    # Get the current HT and HTS attributes for the strategy
    HT = getattr(algorithm, f"HT{number}")
    HTS = getattr(algorithm, f"HTS{number}")

    # Update HT and HTS based on the sorted equities
    total_weight = sum(weight for _, weight in sorted_equities)
    for equity, _ in sorted_equities:
        for i in HT.keys():
            if HT[i] == 0:
                HT[i] = (weights[equities.index(equity)] / total_weight) * multiplier
                HTS[i].append(equity)
                break

    # Update the HT and HTS attributes for the strategy
    setattr(algorithm, f"HT{number}", HT)
    setattr(algorithm, f"HTS{number}", HTS)
# main.py
from AlgorithmImports import *
from indicators import *
import os
import importlib

class YellowCatStrat(QCAlgorithm):
    def Initialize(self):
        
        self.cash = 100000
        self.buffer_pct = 0.02
        self.SetStartDate(2021,9,20)
        self.SetEndDate(2023,12,23)
        self.SetCash(self.cash)
        self.equities = ['PPLT','GLTR','SUB','SPLV','RSP','SJB','NRGU','NTSX', 'DBMF', 'FAAR', 'COM', 'RLY', 'GAA', 'TRTY','GDMA', 'FTLS', 'MNA', 'VAMO', 'GMOM', 'SHV', 'ICSH', 'CCOR','RPV','QUAL',"SDS",'VCR','UPW', "UYG", "ROM", "RXL", "UCC", "UJB",'TPOR','DIS', 'HYG', 'KO', 'AAPL', 'AMZN', 'GOOGL', 'XOM','UNH', 'HD', 'PG', 'JNJ', 'MSFT', 'WFC','GSY','SRTY','TBT','XENE','ARCT','CRSP','IMRX','NAMS','BPMC','IMUX','HOWL','AUTL','ETNB','SIMO','IEO','ATXS','SERA','VRTX','PNT','FUSN','PYXS','EXAI','ICVX','IOVA','CRBU','ROIV','XLF','CDTX','TRDA','CRVS','AKBA','EDC','SON','XLE','TWM','RWM','URTY','PBR','OIL','ROST','WMS','AAPD','TSLQ','TSLS','AAPB','ALGN','TPL','COIN','VLO','AA','BITI','HIBS','ACLS','EQT','MOS','AR','MU','CZR','UVIX','ENPH','AMEH','ERIC','GNRC','BULZ','VCIT','UDN','SARK','AMD','FNGU','TSLL','AEHR','MSTR','TARK','XLY','QQQE','VOOG','VOOV','VTV','HIBL','XLK','XLP','SVXY','QID','TBF','TSLA','LQD','VTIP','EDV','STIP','SPTL','IEI','USDU','SQQQ','VIXM','SPXU','QQQ','BSV','TQQQ','SPY','DBC','SHV','IAU','VEA','UTSL','UVXY','UPRO','EFA','EEM','TLT','SHY','GLD','SLV','USO','WEAT','CORN','SH','DRN','PDBC','COMT','KOLD','BOIL','ESPO','PEJ','UGL','URE','VXX','UUP','BND','BIL','DUST','JDST','JNUG','GUSH','DBA','DBB','COM','PALL','AGQ','BAL','WOOD','URA','SCO','UCO','DBO','TAGS','CANE','REMX','COPX','IEF','SPDN','CHAD','DRIP','SPUU','INDL','BRZU','ERX','ERY','CWEB','CHAU','KORU','MEXX','EDZ','EURL','YINN','YANG','TNA','TZA','SPXL','SPXS','MIDU','TYD','TYO','TMF','TMV','TECL','TECS','SOXL','SOXS','LABU','LABD','RETL','DPST','DRV','PILL','CURE','FAZ','FAS','EWA','EWGS','EWG','EWP','EWQ','EWU','EWJ','EWI','EWN','ECC','NURE','VNQI','VNQ','VDC','VIS','VGT','VAW','VPU','VOX','VFH','VHT','VDE','SMH','DIA','UDOW','PSQ','SOXX','VTI','COST','UNH','SPHB','BTAL','VIXY','WEBL','WEBS','UBT','PST','TLH','QLD','SQM','SSO','SD','DGRO','SCHD','SGOL','TIP','DUG','EWZ','TBX','VGIT','VGLT','CCOR','LBAY','NRGD','PHDG','SPHD','COWZ','CTA','DBMF','GDMA','VIGI','AGG','NOBL','FAAR','BITO','FTLS','MORT','FNDX','GLL','NTSX','RWL','VLUE','IJR','SPYG','VXUS','AAL','AEP','AFL','C','CMCSA','DUK','EXC','F','GM','GOOGL','INTC','JNJ','KO','MET','NWE','OXY','PFE','RTX','SNY','SO','T','TMUS','VZ','WFC','WMT','AMZN','MSFT','NVDA','TSM','BA','CB','COKE','FDX','GE','LMT','MRK','NVEC','ORCL','PEP','V','DBE','BRK-B','CRUS','INFY','KMLM','NSYS','SCHG','SGML','SLDP','ARKQ','XLU','XLV','ULTA','AAPL','AMZU','BAD','DDM','IYH','JPM','PM','XOM','EUO','YCS','MVV','USD','TMF','SPXL','EPI','IYK','CURE','DIG','XLU']
        self.MKT = self.AddEquity("QQQ",Resolution.Daily).Symbol
        self.mkt = []
        self.benchmarkSymbol = self.AddEquity("QQQ", Resolution.Daily).Symbol
        self.benchmarkPrices = []
        for equity in self.equities:
            self.AddEquity(equity,Resolution.Minute)
            self.Securities[equity].SetDataNormalizationMode(DataNormalizationMode.Adjusted)
        self.AddEquity('BIL',Resolution.Minute)
        self.Securities['BIL'].SetDataNormalizationMode(DataNormalizationMode.TotalReturn)

        self.lastTop6UpdateDay = 0

        self.top_6_days = [0] * 5
        # Base directory for strategies
        strategy_base_dir = "Strategies"
        
        # List of strategy names (you would populate this list dynamically)
        self.strategy_names = [
            "TQQQFTLT",
            "TQQQorNot",
            "OffseasonCocktail15",
            "PHASETESTofInflationSpiralHedgeQuantconn",
            "ParitySwitchingGoldCommoditiesandEnergyt",
            "OverfitunpoquitoQuantconnect",
            "Opus69Quantconnect",
            "Opus14Quantconnect",
            "Opus12Quantconnect",
            "Opus12NotBoringGoldenPonyVolHedgeAAWV16B",
            "OilandVolatilityQuantconnect",
            "PSQEquivalentQuantconnect",
            "PUBNEWSCHDSPYMovingAverageComboDereckNHT",
            # Add other strategy names here...
        ]
        # Dynamically import strategies and create instances
        self.strategies = {}
        for strategy_name in self.strategy_names:
            full_module_name = f"{strategy_base_dir}.{strategy_name}.version1"
            strategy_module = importlib.import_module(full_module_name)
            strategy_class_name = strategy_name + "Strategy"
            strategy_class = getattr(strategy_module, strategy_class_name)
            self.strategies[strategy_name] = strategy_class(self)

        self.PTMaster = 1

        self.strategy_count = 400
        self.initializeStrategyVariables(self.strategy_count)
        self.days_history = 30  # Number of days to keep history for
        self.initializePrevDayVariables(self.strategy_count, self.days_history)

        self.initializePrevDayReturnVariables(self.strategy_count, self.days_history)

        # Initialize PT variables for each strategy
        for i in range(1, self.strategy_count + 1):
            setattr(self, f'PT{i}', 0.2 * self.PTMaster)

        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                self.TimeRules.BeforeMarketClose("SPY",2),
                self.FunctionBeforeMarketClose)

    def initializeStrategyVariables(self, strategy_count):
        for i in range(1, strategy_count + 1):
            setattr(self, f'HT{i}', {str(j).zfill(2): 0 for j in range(1, 10)})
            setattr(self, f'HTS{i}', {str(j).zfill(2): [] for j in range(1, 10)})

    def initializePrevDayVariables(self, strategy_count, days_history):
        for i in range(1, strategy_count + 1):
            for day in range(1, days_history + 1):
                setattr(self, f'prev_day_HT{i}_{day}', {str(j).zfill(2): 0 for j in range(1, 10)})
                setattr(self, f'prev_day_HTS{i}_{day}', {str(j).zfill(2): [] for j in range(1, 10)})

    def initializePrevDayReturnVariables(self, strategy_count, days_history):
        for i in range(1, strategy_count + 1):
            for day in range(1, days_history + 1):
                setattr(self, f'prev_day_return{i}_{day}', 0.0)
 
    def __init__(self):
        super().__init__()

    def CumReturn(self,equity,period):
        history = self.History(equity,period,Resolution.Daily)
        closing_prices = pd.Series([bar.Close for bar in history])
        current_price = self.Securities[equity].Price
        closing_prices = closing_prices.append(pd.Series([current_price]))
        first_price = closing_prices.iloc[0]
        if first_price == 0:
            return None
        else:
            return_val = (current_price/first_price) - 1
            return return_val

    def FunctionBeforeMarketClose(self):
        # Execute all strategies stored in the dictionary
        for strategy_name, strategy in self.strategies.items():
            strategy.Execute()
        self.updatePrevDayVariables()
        #self.StrategyReturn()
        self.CalculateAndLogTopStrategies()
        self.ExecuteTrade()
        self.SetVarToZero(self.strategy_count)

    def OnData(self, data):
        # This function is called every time new data is received
        pass

    def ExecuteTrade(self):
        df_list = []

        # Process each top-performing strategy
        for strategy_number in self.FinalTickers:
            HTS_attr = getattr(self, f'HTS{strategy_number}')
            HT_attr = getattr(self, f'HT{strategy_number}')

            group = {
                'HTS': [HTS_attr[i][0] if len(HTS_attr[i]) == 1 else HTS_attr[i] for i in HTS_attr],
                'HT': [HT_attr[i]/1 for i in HT_attr]
            }
            df = pd.DataFrame(group)
            df_list.append(df)

        # Combine all dataframes
        df_combined = pd.concat(df_list)
        df_combined['HTS'] = df_combined['HTS'].astype(str)
        result = df_combined.groupby(['HTS']).sum().reset_index()
        # Dictionary with pairs
        pairs_dict = {'SOXL':'SOXS','TQQQ':'SQQQ','SPXL':'SPXS','WEBL':'WEBS','TECL':'TECS','UPRO':'SPXU','QQQ':'PSQ','SPY':'SH','TMV':'TMF','HIBL':'HIBS','BITO':'BITI','TSLA':'TSLS','AAPL':'AAPD','ERX':'ERY','BOIL':'KOLD'}
        pairs_dict.update({v: k for k,v in pairs_dict.items()}) #ensure both directions are covered
        # Track selling and buying
        processed_pairs_selling = set()
        processed_pairs_buying = set()
        liquidated_equities = set()
        # Exclude symbols
        exclude_symbols = ['BIL','BSV','SHV','SHY']
        # dictionary
        symbol_dict = dict(zip(result.iloc[:,0],result.iloc[:,1]))
        # Log output
        output = "*****"
        for symbol, percentage in symbol_dict.items():
            output += "{}: {}% - ".format(symbol, round(percentage*100, 2))
        output = output.rstrip(" - ")
        self.Log(output)
        # Symbols to be transformed
        transform_symbols = ['PSQ','SH','USDU','SPXU','UPRO','QLD','QID','TSLS']
        transform_mapping = {'PSQ':'SQQQ','SH':'SPXS','USDU':'UUP','SPXU':'SPXS','UPRO':'SPXL','QLD':'TQQQ','QID':'SQQQ','TSLS':'TSLQ'}
        transform_ratios = {'PSQ':3,'SH':3,'USDU':1,'SPXU':1,'UPRO':1,'QLD':1.5,'QID':1.5,'TSLS':1}
        # Transform symbols
        for symbol in transform_symbols:
            if symbol in symbol_dict:
                new_symbol = transform_mapping[symbol]
                ratio = transform_ratios[symbol]
                new_percentage = symbol_dict[symbol]/ratio 
                # Adjust percentage allocation
                if new_symbol in symbol_dict:
                    new_percentage += symbol_dict[new_symbol]
                symbol_dict[new_symbol] = new_percentage
                # Remove transformed
                symbol_dict.pop(symbol, None)
        # Ensure updated equities list
        updated_equities = set(symbol_dict.keys())
        # Liquidate equities
        for equity in self.equities:
            if equity not in updated_equities and self.Portfolio[equity].HoldStock and equity not in liquidated_equities:
                self.Liquidate(equity)
                liquidated_equities.add(equity)
        # Iterate pairs selling
        for symbol1,symbol2 in pairs_dict.items():
            if symbol1 in symbol_dict and symbol2 in symbol_dict:
                offset_value = abs(symbol_dict[symbol1] - symbol_dict[symbol2])
                if symbol_dict[symbol1] >= symbol_dict[symbol2] and self.Portfolio[symbol2].HoldStock:
                    self.Liquidate(symbol2)
                elif symbol_dict[symbol1] <= symbol_dict[symbol2] and self.Portfolio[symbol1].HoldStock:
                    self.Liquidate(symbol1)
                # Mark processed selling
                processed_pairs_selling.add(symbol1)
                processed_pairs_selling.add(symbol2)
        # Iterate remaining selling
        for symbol,value in symbol_dict.items():
            if symbol not in processed_pairs_selling and not value == 0 and symbol not in exclude_symbols:
                percentage_equity = self.Portfolio[symbol].HoldingsValue/self.Portfolio.TotalPortfolioValue
                if value < percentage_equity and abs(value/percentage_equity - 1) > self.buffer_pct:
                    self.SetHoldings(symbol,value)
        # Iterate pairs buying
        for symbol1,symbol2 in pairs_dict.items():
            if symbol1 in symbol_dict and symbol2 in symbol_dict and symbol1 not in processed_pairs_buying and symbol2 not in processed_pairs_buying:
                offset_value = abs(symbol_dict[symbol1] - symbol_dict[symbol2])
                if offset_value > 0.01:
                    if symbol_dict[symbol1] > symbol_dict[symbol2]:
                        self.SetHoldings(symbol1,offset_value)
                    else:
                        self.SetHoldings(symbol2,offset_value)
                else:
                    if self.Portfolio[symbol1].HoldStock:
                        self.Liquidate(symbol1)
                    if self.Portfolio[symbol2].HoldStock:
                        self.Liquidate(symbol2)
                # Mark as processed buying
                processed_pairs_buying.add(symbol1)
                processed_pairs_buying.add(symbol2)
        # Filter less than 1%
        updated_equities = {symbol for symbol, value in symbol_dict.items() if value >= 0.01}
        # Iterate remaining symbol_dict for buying
        for symbol,value in symbol_dict.items():
            if (symbol in updated_equities and 
                symbol not in processed_pairs_buying and 
                symbol not in exclude_symbols):
                percentage_equity = (self.Portfolio[symbol].HoldingsValue /
                                    self.Portfolio.TotalPortfolioValue)
                if value > percentage_equity and abs(percentage_equity/value - 1) > self.buffer_pct:
                    self.SetHoldings(symbol,value)

    def SetVarToZero(self, strategy_count):

        for i in range(1, strategy_count + 1):
            setattr(self, f'HT{i}', {str(j).zfill(2): 0 for j in range(1, 10)})
            setattr(self, f'HTS{i}', {str(j).zfill(2): [] for j in range(1, 10)})

    def CalculateDailyReturn(self, strategy_number, days, day_number):
        prev_day_HT = getattr(self, f'prev_day_HT{strategy_number}_{day_number}')
        prev_day_HTS = getattr(self, f'prev_day_HTS{strategy_number}_{day_number}')
        PT_value = getattr(self, f'PT{strategy_number}')  # Retrieve PT value for the strategy

        total_return = 0
        for key in prev_day_HTS:
            tickers = prev_day_HTS[key]
            weight = prev_day_HT[key]
            if tickers and weight != 0:
                if isinstance(tickers, list):
                    tickers_return = sum([self.CumReturn(ticker, days) if self.CumReturn(ticker, days) is not None else 0 for ticker in tickers])
                else:
                    tickers_return = self.CumReturn(tickers, days)
                total_return += tickers_return * weight

        # Normalize the return by the strategy's PT value
        return total_return / PT_value if PT_value != 0 else 0

    def StrategyReturn(self):
        strategy_returns = {}
        days_to_calculate = list(range(1, 31))

        # Calculate cumulative returns for each strategy and each day range
        for strategy_number, strategy_name in enumerate(self.strategy_names, start=1):
            strategy_returns[strategy_number] = {days: self.CalculateCumulativeReturn(strategy_number, days) for days in days_to_calculate}

        # Initialize a dictionary to hold the top strategies for each day range
        top_strategies_by_day = {day: [] for day in days_to_calculate}

        # For each day range, determine the top 5 strategies
        for day in days_to_calculate:
            # Create a list of (strategy_number, cumulative_return) for the current day range
            strategy_day_returns = [(number, returns[day]) for number, returns in strategy_returns.items()]
            # Sort the strategies based on their cumulative return for the current day range
            top_strategies = sorted(strategy_day_returns, key=lambda x: x[1], reverse=True)[:5]
            # Store the top strategy numbers and their returns for the current day range
            top_strategies_by_day[day] = top_strategies

        # Now you have top 5 strategies for each day range in top_strategies_by_day
        # You can log this information or use it as needed
        for day, strategies in top_strategies_by_day.items():
            log_msg = f"Best strategies for {day} days: "
            for strategy_number, return_value in strategies:
                strategy_name = self.strategy_names[strategy_number - 1]  # Convert number back to name
                log_msg += f"{strategy_name}: {round(return_value * 100, 2)}%, "
            #self.Log(log_msg.rstrip(", "))


    def updatePrevDayVariables(self):
        self.storeDailyReturns()
        for i in range(1, self.strategy_count + 1):
            # Shift data for each day
            for day in range(self.days_history, 1, -1):
                setattr(self, f'prev_day_HT{i}_{day}', getattr(self, f'prev_day_HT{i}_{day - 1}').copy())
                setattr(self, f'prev_day_HTS{i}_{day}', {k: v.copy() for k, v in getattr(self, f'prev_day_HTS{i}_{day - 1}').items()})

            # Update day 1 with the current day's data
            current_day_HT = getattr(self, f'HT{i}')
            current_day_HTS = getattr(self, f'HTS{i}')
            setattr(self, f'prev_day_HT{i}_1', current_day_HT.copy())
            setattr(self, f'prev_day_HTS{i}_1', {k: v.copy() for k, v in current_day_HTS.items()})

    def storeDailyReturns(self):
        for i in range(1, self.strategy_count + 1):
            current_return = self.CalculateDailyReturn(i, 1, 1)
            for day in range(self.days_history, 1, -1):
                prev_return = getattr(self, f'prev_day_return{i}_{day - 1}')
                setattr(self, f'prev_day_return{i}_{day}', prev_return)

            # Store the current day's return
            setattr(self, f'prev_day_return{i}_1', current_return)

    def CalculateCumulativeReturn(self, strategy_number, days):
        cumulative_return = 0
        for day in range(1, days + 1):
            daily_return = getattr(self, f'prev_day_return{strategy_number}_{day}')
            cumulative_return = (1 + cumulative_return) * (1 + daily_return) - 1

        return cumulative_return

    def GetStrategyHoldings(self, strategy_number):
        HT_attr = getattr(self, f'HT{strategy_number}')
        HTS_attr = getattr(self, f'HTS{strategy_number}')

        holdings_info = ', '.join([f"{ticker}: {round(HT_attr[key] * 100, 2)}%" 
                                   for key, tickers in HTS_attr.items() 
                                   if tickers 
                                   for ticker in (tickers if isinstance(tickers, list) else [tickers])])
        return holdings_info

    def CalculateAndLogTopStrategies(self):
        # Initialize strategy_avg_returns with strategy numbers as keys
        self.strategy_avg_returns = {strategy_number: {} for strategy_number, _ in enumerate(self.strategy_names, start=1)}

        currentDay = self.Time.day  # Example of getting the current day

        # Populate this structure with average returns using strategy numbers
        for day in range(1, 31):
            for strategy_number in range(1, len(self.strategy_names) + 1):
                avg_return = self.CalculateAverageReturn(strategy_number, day)
                self.strategy_avg_returns[strategy_number][day] = avg_return

        # Update top 6 days every 10 days
        if (currentDay - self.lastTop6UpdateDay) >= 10 or self.lastTop6UpdateDay == 0:
            self.lastTop6UpdateDay = currentDay
            self.UpdateTop6Days()

        # Log the top 5 strategies daily
        self.LogTop5Strategies()

    def UpdateTop6Days(self):
        self.top_5_strategies_each_day = {}
        # Gather top 5 strategies for each day based on their average returns
        for day in range(1, 31):
            top_strategies_today = sorted(
                [(strategy_number, self.strategy_names[strategy_number - 1]) for strategy_number in range(1, len(self.strategy_names) + 1)],
                key=lambda x: self.strategy_avg_returns[x[0]][day] if day in self.strategy_avg_returns[x[0]] else float('-inf'), reverse=True)[:5]
            self.top_5_strategies_each_day[day] = top_strategies_today

        # Calculate average returns for the top 5 strategies of each day
        avg_returns_for_top_5_each_day = {
            day: self.CalculateAvgReturnForBestNDay(day, [s[0] for s in self.top_5_strategies_each_day[day]])
            for day in range(1, 31)
        }
            
        # Determine top 6 days based on the calculated average returns
        self.top_6_days = sorted(avg_returns_for_top_5_each_day, key=avg_returns_for_top_5_each_day.get, reverse=True)[:6]

        # Populate self.FinalTickers with unique strategy numbers from top 6 days
        self.FinalTickers = set()
        for day in self.top_6_days:
            for strategy_number, _ in self.top_5_strategies_each_day[day]:
                self.FinalTickers.add(strategy_number)

        # Convert self.FinalTickers to a list if necessary for further processing
        self.FinalTickers = list(self.FinalTickers)

                
    def LogTop5Strategies(self):
        log_msg = "Top 5 Strategies: "
        for day in self.top_6_days:  # Iterate over the top days
            # Extract strategy names or numbers from the tuples for this day
            # If you want to log strategy names:
            strategies_info = [str(self.strategy_names[s[0] - 1]) for s in self.top_5_strategies_each_day.get(day, [])]
            # Or, if you want to log strategy numbers:
            # strategies_info = [str(s[0]) for s in self.top_5_strategies_each_day.get(day, [])]
            
            # Join the strategy information into a string
            strategies_str = ", ".join(strategies_info)
            if strategies_info:  # Check if there are strategies for the day
                log_msg += f"Day {day}: Strategies: {strategies_str}, "
            else:
                log_msg += f"Day {day}: No strategies available, "
        self.Log(log_msg.rstrip(", "))



    def CalculateAvgReturnForBestNDay(self, day, top_strategy_numbers):
        # This dictionary will hold the 10-day average returns for each strategy
        ten_day_avg_returns = {}
        
        # Calculate 10-day average return for each strategy
        for strategy_number in top_strategy_numbers:
            daily_returns = []
            # Assuming you have a way to access daily return for each of the last 10 days
            for day_offset in range(1, 11):
                daily_return = getattr(self, f'prev_day_return{strategy_number}_{day_offset}', 0)
                if daily_return is not None:
                    daily_returns.append(daily_return)
            if daily_returns:
                ten_day_avg_returns[strategy_number] = sum(daily_returns) / len(daily_returns)
        
        # Now, calculate the average of these 10-day average returns for the top strategies
        if ten_day_avg_returns:
            total_return = sum(ten_day_avg_returns.values())
            valid_strategies_count = len(ten_day_avg_returns)
            return total_return / valid_strategies_count
        else:
            self.Log("No valid return data for any strategies.")
            return None


    def CalculateAverageReturn(self, strategy_number, day_range):
        # Use a list comprehension with a conditional to replace None values with 0
        daily_returns = [(self.CalculateDailyReturn(strategy_number, 1, day_number) or 0) for day_number in range(1, day_range + 1)]
        total_return = sum(daily_returns)
        return total_return / day_range