Overall Statistics
Total Trades
77
Average Win
0.72%
Average Loss
-0.39%
Compounding Annual Return
10.218%
Drawdown
1.400%
Expectancy
0.518
Net Profit
6.142%
Sharpe Ratio
1.501
Probabilistic Sharpe Ratio
69.718%
Loss Rate
47%
Win Rate
53%
Profit-Loss Ratio
1.85
Alpha
0.068
Beta
-0.035
Annual Standard Deviation
0.047
Annual Variance
0.002
Information Ratio
0.742
Tracking Error
0.213
Treynor Ratio
-2.02
Total Fees
$117.91
Estimated Strategy Capacity
$150000000.00
Lowest Capacity Asset
QQQ RIWIV7K5Z9LX
#region imports
from AlgorithmImports import *
#endregion
# MACD Signal Delta Percent simplified


class MACDTrendAlgorithm(QCAlgorithm):

    

    def Initialize(self):
        self.SetStartDate(2022, 1, 1)
        self.SetEndDate(2022, 8, 12)
        self.SetCash(100000)
        self.stopBuffer = 0.10
        self.X = self.AddEquity("QQQ", Resolution.Hour).Symbol
        
        #indicator set up
        self.macd = self.MACD(self.X, 12, 26, 9, MovingAverageType.Exponential, Resolution.Hour)
        self.ema =  self.EMA(self.X, 100, Resolution.Hour)

        #indicator previous values setup
        self.macdPrev = None
        self.signalPrev = None
        self.priceHighPrev = None
        self.priceLowPrev = None

        #scheduled events
        self.Schedule.On(self.DateRules.EveryDay(self.X), self.TimeRules.AfterMarketOpen(self.X, 30), self.TradeLock)
        self.Schedule.On(self.DateRules.EveryDay(self.X), self.TimeRules.BeforeMarketClose(self.X, 5), self.EODActivity)
        self.tradeLock = True
        self.SetWarmup(100)
        

    def OnData(self, data):

        if self.IsWarmingUp or not self.ema.IsReady:
            return
        
        if self.macdPrev is None:
            self.macdPrev = 0.1
            self.macdCurr = self.macd.Current.Value
            self.signalPrev = self.macd.Signal.Current.Value
            self.emaPrev = self.ema.Current.Value
            self.priceHighPrev = self.Securities[self.X].High
            self.priceLowPrev = self.Securities[self.X].Low 
            return
            
        
        self.macdCurr = self.macd.Current.Value
        self.signalCurr = self.macd.Signal.Current.Value
        self.emaCurr = self.ema.Current.Value
        self.priceHighCurr = self.Securities[self.X].High
        self.priceLowCurr = self.Securities[self.X].Low
        
        #CRITERIA FOR ENTERING A LONG POSITION
        #1. Price must be above the 100-day EMA
        #2. MACD must be crossing up and over the signal line
        #3. Stop-Loss should be set to bar's low minus 0.XX cents

        #CRITERIA FOR ENTERING A SHORT POSITION
        #1. Price must be below the 100-day EMA
        #2. MACD must be crossing down and over the signal line
        #3. Stop-Loss should be set to bar's high minus 0.XX cents        
        if not self.Portfolio.Invested and self.tradeLock is False:
            
            #LONG TRADE ENTRY
            if self.priceLowPrev > self.emaPrev and self.priceLowCurr > self.emaCurr:
                if self.macdPrev < self.signalPrev and self.macdCurr > self.signalCurr: 
                    self.SetHoldings(self.X, 0.8)
                    self.holdings = self.Portfolio[self.X].Quantity
                    self.StopMarketOrder(self.X, -self.holdings, self.priceLowCurr - self.stopBuffer)
            #SHORT TRADE ENTRY        
            elif self.priceHighPrev < self.emaPrev and self.priceHighCurr < self.emaCurr:
                if self.macdPrev > self.signalPrev and self.macdCurr < self.signalCurr: 
                    self.SetHoldings(self.X, -0.8)
                    self.holdings = self.Portfolio[self.X].Quantity
                    self.StopMarketOrder(self.X, self.holdings, self.priceHighCurr + self.stopBuffer)       
        elif self.Portfolio["QQQ"].IsLong:
            if self.macdPrev > self.signalPrev and self.macdCurr < self.signalCurr: 
                self.Transactions.CancelOpenOrders(self.X)
                self.Liquidate() 
        elif self.Portfolio["QQQ"].IsShort:
            if self.macdPrev < self.signalPrev and self.macdCurr > self.signalCurr: 
                self.Transactions.CancelOpenOrders(self.X)
                self.Liquidate() 
        
        self.macdPrev = self.macd.Current.Value
        self.signalPrev = self.macd.Signal.Current.Value
        self.emaPrev = self.ema.Current.Value
        self.priceLowPrev = self.Securities[self.X].High
        self.priceHighPrev = self.Securities[self.X].Low
                       
    def TradeLock(self):
        self.tradeLock = False

    def EODActivity(self):
        if self.Portfolio.Invested:
            self.Liquidate()
        self.tradeLock = True