Overall Statistics
Total Trades
343
Average Win
2.96%
Average Loss
-0.76%
Compounding Annual Return
34.822%
Drawdown
14.500%
Expectancy
2.519
Net Profit
2055.308%
Sharpe Ratio
1.683
Probabilistic Sharpe Ratio
97.225%
Loss Rate
28%
Win Rate
72%
Profit-Loss Ratio
3.89
Alpha
0.213
Beta
0.255
Annual Standard Deviation
0.144
Annual Variance
0.021
Information Ratio
0.744
Tracking Error
0.172
Treynor Ratio
0.95
Total Fees
$1715.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
SPDN.SPDN 2S
class AccelDualMomentum(QCAlgorithm):
    def Initialize(self):
        
        self.SetStartDate(2012, 1, 1)  # Set Start Date
        #self.SetEndDate(2022,2,28)  # Set End Date
        self.SetCash(10000)  # Set Strategy Cash
        
        res = Resolution.Minute
   
        #self.QQQ = self.AddEquity('QQQ', res).Symbol
        #self.EEM = self.AddEquity('EEM', res).Symbol
        #self.TLT = self.AddEquity('TLT', res).Symbol
        #self.SPDN = self.AddEquity('SPDN', res).Symbol
        #self.IEF = self.AddEquity('IEF', res).Symbol
        
        self.QQQ = self.AddData(QQQ, "QQQ", Resolution.Daily).Symbol
        self.VEU = self.AddData(VEU, "VEU", Resolution.Daily).Symbol
        self.TLT = self.AddData(TLT, "TLT", Resolution.Daily).Symbol
        self.SPDN = self.AddData(SPDN, "SPDN", Resolution.Daily).Symbol
        self.IEF = self.AddData(IEF, "IEF", Resolution.Daily).Symbol
        
        
        self.indicator = self.AddData(MOMENTUM, "MOMENTUM", Resolution.Daily).Symbol
        
        self.leverage = 1   # Set leverage | A value of 1 indicates no leverage | A value of 2 indicates 100% leverage
        self.Securities["QQQ"].SetLeverage(self.leverage)
        self.Securities["VEU"].SetLeverage(self.leverage)
        self.Securities["TLT"].SetLeverage(self.leverage)
        self.Securities["SPDN"].SetLeverage(self.leverage)
        self.Securities["IEF"].SetLeverage(self.leverage)

        # Set trading frequency
        
        self.monthly = 0 
        self.annual = 0
        self.daily = 1

        self.trading_fee = 5  # Fee per trade
        
        self.trading_day = 21 # Set trading day | Value = 21 is last trading day of month
        self.GetParameter("trading_day") 
        
        self.SetWarmUp(timedelta(126))


    def shiftAssets(self, target):
        if not (self.Portfolio[target].Invested):
            for symbol in self.Portfolio.Keys:
                self.Liquidate(symbol)
            if not self.Portfolio.Invested:
                self.SetHoldings(target, 1*self.leverage)
    
    def getMonthTradingDay(self):
        month_last_day = DateTime(self.Time.year, self.Time.month, DateTime.DaysInMonth(self.Time.year, self.Time.month))
        tradingDays = self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, DateTime(self.Time.year, self.Time.month, 1), month_last_day)
        tradingDays = [day.Date.date() for day in tradingDays]
        return tradingDays[-22 + self.trading_day]
        
    def getYearLastTradingDay(self):
        year_last_day = DateTime(self.Time.year, 12, DateTime.DaysInMonth(self.Time.year, 12))
        tradingDays = self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, DateTime(self.Time.year, 12, 1), year_last_day)
        tradingDays = [day.Date.date() for day in tradingDays]
        return tradingDays [-1]
        
        
    def OnData(self, data):
        if self.IsWarmingUp: return
    
        if (self.daily ==1):
            if data.ContainsKey(self.indicator):
                ticker = data[self.indicator].GetProperty('Indicator')
                if (ticker =="VEU"):
                        self.Securities["VEU"].SetFeeModel(MonthlyCustomFeeModel())
                        #self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen('QQQ', 120), self.shiftAssets(self.EEM))
                        self.shiftAssets(self.VEU)
                elif (ticker =="QQQ"):
                        self.Securities["QQQ"].SetFeeModel(MonthlyCustomFeeModel())
                        #self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen('QQQ', 120), self.shiftAssets(self.QQQ))
                        self.shiftAssets(self.QQQ)
                elif (ticker =="TLT"):
                        self.Securities["TLT"].SetFeeModel(MonthlyCustomFeeModel())
                        #self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen('QQQ', 120), self.shiftAssets(self.TLT))
                        self.shiftAssets(self.TLT)
                elif (ticker =="IEF"):
                        self.Securities["IEF"].SetFeeModel(MonthlyCustomFeeModel())
                        #self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen('QQQ', 120), self.shiftAssets(self.IEF))
                        self.shiftAssets(self.IEF)
                elif (ticker =="SPDN"):
                        self.Securities["SPDN"].SetFeeModel(MonthlyCustomFeeModel())
                        #self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen('QQQ', 120), self.shiftAssets(self.SPDN))
                        self.shiftAssets(self.SPDN)
        # Charts
                
        self.Plot("Margin", "Remaining", self.Portfolio.MarginRemaining)
        self.Plot("Margin", "Used", self.Portfolio.TotalMarginUsed)
        self.Plot("Cash", "Remaining", self.Portfolio.Cash)
        self.Plot("Cash", "Remaining", self.Portfolio.TotalHoldingsValue)
        
        self.Plot("QQQ", "Held", self.Portfolio["QQQ"].Quantity)
        self.Plot("VEU", "Held", self.Portfolio["VEU"].Quantity)
        self.Plot("TLT", "Held", self.Portfolio["TLT"].Quantity)
        self.Plot("IEF", "Held", self.Portfolio["IEF"].Quantity)
        self.Plot("SPDN", "Held", self.Portfolio["SPDN"].Quantity)

        

        
class QQQ(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/vdn8trsn76505lz/QQQ.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = QQQ()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%Y-%m-%d")
        index.EndTime = index.Time + timedelta(days=1)
        index.Value = data[4]
        index["Open"] = float(data[1])
        index["High"] = float(data[2])
        index["Low"] = float(data[3])
        index["Close"] = float(data[4])
        index["Adj Close"] = float(data[5])

        
        return index
        
class EEM(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/afucxcoaejhk0fu/EEM.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = EEM()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%Y-%m-%d")
        index.EndTime = index.Time + timedelta(days=1)
        index.Value = data[4]
        index["Open"] = float(data[1])
        index["High"] = float(data[2])
        index["Low"] = float(data[3])
        index["Close"] = float(data[4])
        index["Adj Close"] = float(data[5])
        
        return index
        
class TLT(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/9zhb9ec9s9pqulc/TLT.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = TLT()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%Y-%m-%d")
        index.EndTime = index.Time + timedelta(days=1)
        index.Value = data[4]
        index["Open"] = float(data[1])
        index["High"] = float(data[2])
        index["Low"] = float(data[3])
        index["Close"] = float(data[4])
        index["Adj Close"] = float(data[5])
        
        return index
        
class SPDN(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/slxq8xtarpq50rq/SPDN.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = SPDN()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%Y-%m-%d")
        index.EndTime = index.Time + timedelta(days=1)
        index.Value = data[4]
        index["Open"] = float(data[1])
        index["High"] = float(data[2])
        index["Low"] = float(data[3])
        index["Close"] = float(data[4])
        index["Adj Close"] = float(data[5])
        
        return index
        
class IEF(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/fvnu9zai31g5plg/IEF.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = IEF()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%Y-%m-%d")
        index.EndTime = index.Time + timedelta(days=1)
        index.Value = data[4]
        index["Open"] = float(data[1])
        index["High"] = float(data[2])
        index["Low"] = float(data[3])
        index["Close"] = float(data[4])
        index["Adj Close"] = float(data[5])
        
        return index
        
class VINEX(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/3otgob32pyl0hz8/VINEX.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = VINEX()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%d/%m/%Y")
        index.EndTime = index.Time + timedelta(days=1)
        index.Value = data[4]
        index["Open"] = float(data[1])
        index["High"] = float(data[2])
        index["Low"] = float(data[3])
        index["Close"] = float(data[4])
        
        return index

class VEU(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/b0ywadvwclo2xyd/VEU.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = VEU()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%Y-%m-%d")
        index.EndTime = index.Time + timedelta(days=1)
        index.Value = data[4]
        index["Open"] = float(data[1])
        index["High"] = float(data[2])
        index["Low"] = float(data[3])
        index["Close"] = float(data[4])
        
        return index

        
class MOMENTUM(PythonData):
    def GetSource(self, config, date, isLiveMode):
        return SubscriptionDataSource("https://www.dropbox.com/s/c7dh6xdc55i9mmq/Indicator_SHY_XLI_with%20VEU.csv?dl=1", SubscriptionTransportMedium.RemoteFile)
    def Reader(self, config, line, date, isLive):
        
        if not (line.strip() and line[0].isdigit()): 
            return None
        
        index = MOMENTUM()
        index.Symbol = config.Symbol
        data = line.split(',')
        index.Time = datetime.strptime(data[0], "%Y-%m-%d")
        index.EndTime = index.Time + timedelta(days=1)
        index.SetProperty("Indicator", str(data[1]))
        
        return index
        
class MonthlyCustomFeeModel:
    def GetOrderFee(self, parameters):
        self.margin_rate = 0.0  #Set Margin Fee
        self.trading_fee = 5    #Set fee per trade
        fee = self.trading_fee + (parameters.Security.Leverage-1)*parameters.Security.Price*parameters.Order.AbsoluteQuantity*(self.margin_rate/12)
        return OrderFee(CashAmount(fee, 'USD'))