Overall Statistics
Total Trades
159
Average Win
1.21%
Average Loss
-0.76%
Compounding Annual Return
1.293%
Drawdown
18.900%
Expectancy
0.127
Net Profit
6.733%
Sharpe Ratio
0.19
Probabilistic Sharpe Ratio
3.383%
Loss Rate
57%
Win Rate
43%
Profit-Loss Ratio
1.60
Alpha
-0.023
Beta
0.357
Annual Standard Deviation
0.086
Annual Variance
0.007
Information Ratio
-0.834
Tracking Error
0.112
Treynor Ratio
0.046
Total Fees
$599.76
from clr import AddReference
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")

from QuantConnect import *
from QuantConnect.Indicators import *
from QuantConnect.Algorithm.Framework.Alphas import *
from datetime import timedelta

class MomentumBasedTacticalAllocation(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2014, 10, 1) 
        #self.SetEndDate(2010, 8, 1) 
        self.SetCash(100000)   
        self.SetBrokerageModel(BrokerageName.AlphaStreams)

        self.spy = self.AddEquity("SPY", Resolution.Daily)
        self.bnd = self.AddEquity("BND", Resolution.Daily)
        
        self.spyMomentum = self.MOMP("SPY", 50, Resolution.Daily)
        self.bndMomentum = self.MOMP("BND", 50, Resolution.Daily)
        
        self.reference = "SPY"
        self.SetBenchmark("SPY")  
        self.SetWarmUp(50) 

    def Update(self, algorithm, data):

        insights = []

        for symbol, symbolData in self.symbolDataBySymbol.items():
            if symbolData.CanEmit:

                direction = InsightDirection.Flat
                magnitude = symbolData.Return
                if magnitude > 0: direction = InsightDirection.Up
                if magnitude < 0: direction = InsightDirection.Down

                insights.append(Insight.Price(symbol, self.predictionInterval, direction, magnitude, None))
                
        self.EmitInsights(insights)
        return insights

    def OnData(self, data):
        
        # Don't place trades until our indicators are warmed up:
        if self.IsWarmingUp:
            return
        
        #1. If SPY has more upward momentum than BND, then we liquidate our holdings in BND and allocate 100% of our equity to SPY
        if self.spyMomentum.Current.Value > self.bndMomentum.Current.Value:
            self.Liquidate("BND")
            self.SetHoldings("SPY",1)

        #2. Otherwise we liquidate our holdings in SPY and allocate 100% to BND
        else:
            self.Liquidate("SPY")
            self.SetHoldings("BND",1)