Overall Statistics
Total Trades
833
Average Win
1.97%
Average Loss
-1.16%
Compounding Annual Return
13.079%
Drawdown
13.200%
Expectancy
0.380
Net Profit
453.308%
Sharpe Ratio
0.998
Probabilistic Sharpe Ratio
49.734%
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
1.69
Alpha
0.124
Beta
0.042
Annual Standard Deviation
0.129
Annual Variance
0.017
Information Ratio
0.123
Tracking Error
0.218
Treynor Ratio
3.03
Total Fees
$10730.59
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from System.Drawing import Color
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *

import numpy as np
import decimal as d
from datetime import timedelta, datetime

class ETFMomentumPython(QCAlgorithm):

    # private String
    #            0      1      2    3      4     5
    vSymbol = ["QQQ", "SPY", None, None, None, "TLT"]
    vArrNone = [None,None,None,None,None,None]
    vMaxRange = (6)
    
    # private MomentumPercent 
    Momentum = [None,None,None,None,None,None]

    # public ExponentialMovingAverage 
    emaFast = [None,None,None,None,None,None]
    emaSlow  = [None,None,None,None,None,None]

    # public AverageTrueRange 
    atr  = [None,None,None,None,None,None]

    # private int 
    momPer = (13)
    emaSlowPer = (195)
    emaFastPer = (55)
    atrPer = (8)

    def Initialize(self):
        self.SetStartDate(2006, 1, 1)  #Set Start Date
        self.SetCash(100000)       #Set Strategy Cash
        
        # Loop from 0 to 4
        for x in range (6):
            if self.vSymbol[x] is not None:
                self.AddEquity(self.vSymbol[x], Resolution.Daily)
                self.Momentum[x]  = self.MOMP(self.vSymbol[x], self.momPer, Resolution.Daily)
                self.emaFast[x] = self.EMA(self.vSymbol[x], self.emaFastPer, Resolution.Daily)
                self.emaSlow[x] = self.EMA(self.vSymbol[x], self.emaSlowPer, Resolution.Daily)
                self.atr[x] = self.ATR(self.vSymbol[x], self.atrPer, MovingAverageType.Exponential)

        self.SetBenchmark("SPY")
        self.SetWarmUp(self.emaSlowPer)
        
        Plot  = self.vArrNone
        # Loop from 0 to 4
        for x in range (6):
            if self.vSymbol[x] is not None:
                Plot[x] = Chart(self.vSymbol[x])
                Plot[x].AddSeries(Series("Buy", SeriesType.Scatter, "1", Color.Green, ScatterMarkerSymbol.Triangle))
                Plot[x].AddSeries(Series("Sell", SeriesType.Scatter, "1", Color.Red, ScatterMarkerSymbol.TriangleDown))
                Plot[x].AddSeries(Series("Price", SeriesType.Line, 0))
                Plot[x].AddSeries(Series("EMASlow", SeriesType.Line, 0))
                Plot[x].AddSeries(Series("EMAFast", SeriesType.Line, 0))
                Plot[x].AddSeries(Series("ATR", SeriesType.Line, 0))
                Plot[x].AddSeries(Series("MOMP", SeriesType.Line, 0))
                self.AddChart(Plot[x])

    def OnData(self, data):
        
        if (self.IsWarmingUp):
            return
                
        vemaSlow = [None,None,None,None,None,None]
        vemaFast = [None,None,None,None,None,None]
        vMom     = [None,None,None,None,None,None]
        vAtr     = [None,None,None,None,None,None]
        vScore   = [(0),(0),(0),(0),(0),(0)]
        vMaxScore   = None
        vMaxSymbol  = (self.vMaxRange-(1))
        vSetSymbol = None
        
        # auto plot our indicators on our symbol chart
        for x in range (self.vMaxRange):
            if self.vSymbol[x] is not None:
                vemaSlow[x] = self.emaSlow[x].Current.Value
                vemaFast[x] = self.emaFast[x].Current.Value
                vMom[x] = self.Momentum[x].Current.Value
                vAtr[x] = self.atr[x].Current.Value

        for x in range (self.vMaxRange):
            if self.vSymbol[x] is not None:
                if (data.ContainsKey(self.vSymbol[x])):
                    self.Plot(self.vSymbol[x], "EMASlow", vemaSlow[x])
                    self.Plot(self.vSymbol[x], "EMAFast", vemaFast[x])
                    #self.Plot(self.vSymbol[x], "ATR", vAtr[x])
                    self.Plot(self.vSymbol[x], "MOMP", vMom[x])
                    try:
                        self.Plot(self.vSymbol[x], "Price", data.Bars[self.vSymbol[x]].Close)
                    except:
                        pass

        for x in range (self.vMaxRange):
            if self.vSymbol[x] is not None:
                if vAtr[x] != 0:
                    vScore[x] = vMom[x]/vAtr[x]        

        for x in range (self.vMaxRange):
            if self.vSymbol[x] is not None:
                if vMaxScore is None:
                    if vScore[x] != 0:
                        vMaxScore = vScore[x]
                        vMaxSymbol = x
                elif vScore[x] > vMaxScore and vScore[x] != 0:
                    vMaxScore = vScore[x]
                    vMaxSymbol = x

        self.Log("{0} {1} {2} = {3}".format(vScore[0], vScore[1], vScore[5], self.vSymbol[vMaxSymbol]))
                    
        for x in range (self.vMaxRange):
            if self.vSymbol[x] is not None:
                if x != vMaxSymbol:
                    if (self.Portfolio[self.vSymbol[x]].Quantity > (0)):
                        self.Liquidate(self.vSymbol[x])
                        self.Plot(self.vSymbol[x], "Sell", -1)

        if (not self.Portfolio.Invested):
            vSetSymbol = None
            try:
                if (data.Bars[self.vSymbol[vMaxSymbol]].Close > vemaFast[vMaxSymbol] or data.Bars[self.vSymbol[vMaxSymbol]].Close > vemaSlow[vMaxSymbol]):
                    vSetSymbol = self.vSymbol[vMaxSymbol]
                    self.SetHoldings(self.vSymbol[vMaxSymbol], (0.99))
                    self.Plot(self.vSymbol[vMaxSymbol], "Buy", 1)

            except:
                vSetSymbol = self.vSymbol[vMaxSymbol]
                self.SetHoldings(self.vSymbol[vMaxSymbol], (0.99))
                self.Plot(self.vSymbol[vMaxSymbol], "Buy", 1)

        else:
            try:
                for x in range (self.vMaxRange):
                    if self.vSymbol[x] is not None:
                        if (self.Portfolio[self.vSymbol[x]].Quantity > (0)):
                            if (data.Bars[self.vSymbol[x]].Close < vemaFast[x] and data.Bars[self.vSymbol[x]].Close < vemaSlow[x]):
                                self.Liquidate(self.vSymbol[x])
                                self.Plot(self.vSymbol[x], "Sell", -1)
            except:
                pass

    def OnOrderEvent(self, orderEvent):
        order = self.Transactions.GetOrderById(orderEvent.OrderId)
        #self.Log("OE: {0}: {1}: {2}".format(self.Time, order.Type, orderEvent))