Overall Statistics
Total Trades
105
Average Win
10.58%
Average Loss
-4.74%
Compounding Annual Return
20.184%
Drawdown
30.700%
Expectancy
1.115
Net Profit
1108.535%
Sharpe Ratio
0.991
Probabilistic Sharpe Ratio
35.925%
Loss Rate
35%
Win Rate
65%
Profit-Loss Ratio
2.24
Alpha
0.141
Beta
0.465
Annual Standard Deviation
0.185
Annual Variance
0.034
Information Ratio
0.483
Tracking Error
0.192
Treynor Ratio
0.395
Total Fees
$2393.02
# Dual Momentum Technology ETF by Vladimir

class DualMomentum(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2007, 6, 1)    
        # self.SetEndDate(2020, 12, 15)
        self.cap = 100000
        self.SetCash(self.cap)         
        self.ASSETS = [self.AddEquity(ticker, Resolution.Minute).Symbol for ticker in ['QQQ','FDN','SHV','TLT']]
        self.MKT = self.AddEquity('SPY', Resolution.Daily).Symbol
        self.leverage = 1.0
        self.currentLong = self.ASSETS[0]
        self.mom = 126
        self.excl = 5
        self.spy = []
        self.SetWarmUp(self.mom + self.excl)
        
        self.Schedule.On(self.DateRules.MonthStart('SPY'),self.TimeRules.AfterMarketOpen('SPY', 65), 
            self.rebalance)
        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose('SPY', 0), 
            self.record_vars)
            
   
    def Momentum(self, symbol, period, excl):
        
        prices = self.History(symbol, TimeSpan.FromDays(period + excl),Resolution.Daily).close
        return prices[-excl] / prices[0]
        
       
    def rebalance(self):
        
        if self.Momentum(self.ASSETS[0], self.mom, self.excl) < self.Momentum(self.ASSETS[2], self.mom, self.excl):
            self.currentLong = self.ASSETS[3]
            
        elif self.Momentum(self.ASSETS[0],self.mom, self.excl) > self.Momentum(self.ASSETS[1],self.mom, self.excl):
            self.currentLong=self.ASSETS[0]
            
        else:
            self.currentLong = self.ASSETS[1]
            
        stocksInvested = [x.Key for x in self.Portfolio if x.Value.Invested]
        
        if not stocksInvested: 
            self.SetHoldings(self.currentLong, self.leverage)
            
        elif self.currentLong != stocksInvested[0]:
            self.SetHoldings(self.currentLong, self.leverage, True)


    def record_vars(self): 
    
        hist = self.History(self.MKT, 2, Resolution.Daily)['close'].unstack(level= 0).dropna() 
        self.spy.append(hist[self.MKT].iloc[-1])
        spy_perf = self.spy[-1] / self.spy[0] * self.cap
        self.Plot('Strategy Equity', 'SPY', spy_perf)
        
        account_leverage = self.Portfolio.TotalHoldingsValue / self.Portfolio.TotalPortfolioValue
        self.Plot('Holdings', 'leverage', round(account_leverage, 2))