Overall Statistics
Total Trades
95
Average Win
7.26%
Average Loss
-3.77%
Compounding Annual Return
12.095%
Drawdown
24.900%
Expectancy
0.866
Net Profit
293.950%
Sharpe Ratio
0.696
Probabilistic Sharpe Ratio
12.490%
Loss Rate
36%
Win Rate
64%
Profit-Loss Ratio
1.92
Alpha
0.108
Beta
-0.024
Annual Standard Deviation
0.151
Annual Variance
0.023
Information Ratio
0.082
Tracking Error
0.234
Treynor Ratio
-4.405
Total Fees
$2066.69
class DualMomentum(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2008, 1, 1)  # Set Start Date
        self.SetEndDate(2020, 1, 1)    # Set Start Date       
        self.SetCash(100000)           # Set Strategy Cash
        self.us = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.worldExUS =  self.AddEquity("VEU", Resolution.Daily).Symbol
        self.tbill = self.AddEquity("SHV", Resolution.Daily).Symbol #SHY 
        self.agg = self.AddEquity("BND", Resolution.Daily).Symbol # AGG 
        self.leverage = 1.3
        self.Schedule.On(self.DateRules.MonthStart("SPY"),self.TimeRules.AfterMarketOpen("SPY"), self.rebalance)
        self.currentLong = self.us
        self.returnWindowLength = 100
   
    def Returns(self, symbol, period):
        closingBars = self.History(symbol, TimeSpan.FromDays(period),Resolution.Daily).close
        return (closingBars[-1] - closingBars[0])/closingBars[-1]
       
    def rebalance(self):
        if self.Returns(self.us,self.returnWindowLength) < self.Returns(self.tbill,self.returnWindowLength):
            self.currentLong =  self.agg
        elif self.Returns(self.us,self.returnWindowLength) > self.Returns(self.worldExUS,self.returnWindowLength):
            self.currentLong=self.us
        else:
            self.currentLong = self.worldExUS
        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 OnData(self, data):
        pass