Overall Statistics
Total Trades
298
Average Win
1.71%
Average Loss
-0.50%
Compounding Annual Return
56.107%
Drawdown
46.200%
Expectancy
1.716
Net Profit
494.599%
Sharpe Ratio
1.118
Sortino Ratio
0.96
Probabilistic Sharpe Ratio
45.188%
Loss Rate
39%
Win Rate
61%
Profit-Loss Ratio
3.44
Alpha
0.315
Beta
1.415
Annual Standard Deviation
0.414
Annual Variance
0.171
Information Ratio
1.033
Tracking Error
0.347
Treynor Ratio
0.327
Total Fees
$298.00
Estimated Strategy Capacity
$36000000.00
Lowest Capacity Asset
DOCU WU16SJRONF51
Portfolio Turnover
1.00%
# region imports
from AlgorithmImports import *
# endregion

class AlertMagentaParrot(QCAlgorithm):
    def Initialize(self) -> None:
        self.SetStartDate(2017, 1, 1)
        self.SetEndDate(2020, 12, 31)
        self.SetCash(50000)

        # Add symbols
        self.docu_symbol = self.AddEquity("DOCU", Resolution.Daily).Symbol
        self.amd_symbol = self.AddEquity("AMD", Resolution.Daily).Symbol
        self.nflx_symbol = self.AddEquity("NFLX", Resolution.Daily).Symbol
        self.tsla_symbol = self.AddEquity("TSLA", Resolution.Daily).Symbol
        self.goog_symbol = self.AddEquity("GOOG", Resolution.Daily).Symbol

        # RSI for DOCU
        self.docu_rsi = self.RSI(self.docu_symbol, 3)
        self.docu_periods_above_70 = 0
        self.docu_periods_below_30 = 0

        # RSI for AMD
        self.amd_rsi = self.RSI(self.amd_symbol, 3)
        self.amd_periods_above_70 = 0
        self.amd_periods_below_30 = 0

        # RSI for nflx
        self.nflx_rsi = self.RSI(self.nflx_symbol, 3)
        self.nflx_periods_above_70 = 0
        self.nflx_periods_below_30 = 0

         # RSI for tsla
        self.tsla_rsi = self.RSI(self.tsla_symbol, 3)
        self.tsla_periods_above_70 = 0
        self.tsla_periods_below_30 = 0

         # RSI for GOOG
        self.goog_rsi = self.RSI(self.goog_symbol, 3)
        self.goog_periods_above_70 = 0
        self.goog_periods_below_30 = 0

        self.sma_period = 21
        self.docu_sma_symbol = self.docu_symbol  # SMA based on DOCU, you can change this if needed
        self.amd_sma_symbol = self.amd_symbol # SMA based on amd
        self.nflx_sma_symbol = self.nflx_symbol # SMA based on nflx
        self.tsla_sma_symbol = self.tsla_symbol # sma based on tsla
        self.goog_sma_symbol = self.goog_symbol # sma based on goog

        # SMA runs every day after market open
        self.Schedule.On(self.DateRules.EveryDay(self.docu_sma_symbol),
                          self.TimeRules.AfterMarketOpen(self.docu_sma_symbol, 1),
                          self.Rebalance)

        self.Schedule.On(self.DateRules.EveryDay(self.amd_sma_symbol),
                          self.TimeRules.AfterMarketOpen(self.amd_sma_symbol, 1),
                          self.Rebalance)

        self.Schedule.On(self.DateRules.EveryDay(self.nflx_sma_symbol),
                          self.TimeRules.AfterMarketOpen(self.nflx_sma_symbol, 1),
                          self.Rebalance)
                          
        self.Schedule.On(self.DateRules.EveryDay(self.tsla_sma_symbol),
                          self.TimeRules.AfterMarketOpen(self.tsla_sma_symbol, 1),
                          self.Rebalance)

        self.Schedule.On(self.DateRules.EveryDay(self.goog_sma_symbol),
                          self.TimeRules.AfterMarketOpen(self.goog_sma_symbol, 1),
                          self.Rebalance)

        

    def OnData(self, slice: Slice) -> None:
        # Check if there is enough data to compute SMA
        if self.IsWarmingUp:
            return

        # Check if the symbols are in the slice
        if self.docu_sma_symbol not in slice.Keys or self.docu_symbol not in slice.Keys:
            return
        
        if self.amd_sma_symbol not in slice.Keys or self.amd_symbol not in slice.Keys:
            return

        if self.nflx_sma_symbol not in slice.Keys or self.nflx_symbol not in slice.Keys:
            return

        if self.tsla_sma_symbol not in slice.Keys or self.tsla_symbol not in slice.Keys:
            return

        if self.goog_sma_symbol not in slice.Keys or self.goog_symbol not in slice.Keys:
            return

        # Access historical data for SMA calculation
        docu_history = self.History(self.docu_symbol, self.sma_period, Resolution.Daily)
        amd_history = self.History(self.amd_symbol, self.sma_period, Resolution.Daily)
        nflx_history = self.History(self.nflx_symbol, self.sma_period, Resolution.Daily)
        tsla_history = self.History(self.tsla_symbol, self.sma_period, Resolution.Daily)
        goog_history = self.History(self.goog_symbol, self.sma_period, Resolution.Daily)

        # Calculate SMA for DOCU
        if not docu_history.empty:
            docu_sma = docu_history["close"].mean()
            docu_current_price = slice.Bars[self.docu_symbol].Close

            # Buying and Selling Logic for DOCU (similar logic can be applied to amd)
            if self.docu_rsi.Current.Value > 70:
                self.docu_periods_above_70 += 1
                if self.docu_periods_above_70 == 2 and docu_current_price > docu_sma:
                    self.LimitOrder("DOCU", 100, docu_current_price)
                   
            else:
                self.docu_periods_above_70 = 0

            if self.docu_rsi.Current.Value < 30:
                self.docu_periods_below_30 += 1
                if self.docu_periods_below_30 == 2 and docu_current_price < docu_sma:
                    if self.Portfolio[self.docu_symbol].Quantity >= 100:
                        self.LimitOrder("DOCU", -100, docu_current_price)
                    
            else:
                self.docu_periods_below_30 = 0

        # Calculate SMA for amd (similar logic can be applied to DOCU)
        if not amd_history.empty:
            amd_sma = amd_history["close"].mean()
            amd_current_price = slice.Bars[self.amd_symbol].Close

            # Buying and Selling Logic for amd
            if self.amd_rsi.Current.Value > 70:
                self.amd_periods_above_70 += 1
                if self.amd_periods_above_70 == 2 and amd_current_price > amd_sma:
                    self.LimitOrder("AMD", 40, amd_current_price)
                  
            else:
                self.amd_periods_above_70 = 0

            if self.amd_rsi.Current.Value < 30:
                self.amd_periods_below_30 += 1
                if self.amd_periods_below_30 == 2 and amd_current_price < amd_sma:
                    if self.Portfolio[self.amd_symbol].Quantity >= 40:
                        self.LimitOrder("AMD", -40, amd_current_price)
                   
            else:
                self.amd_periods_below_30 = 0

        # Calculate SMA for nflx(similar logic can be applied to nflx)
        if not nflx_history.empty:
            nflx_sma = nflx_history["close"].mean()
            nflx_current_price = slice.Bars[self.nflx_symbol].Close

            # Buying and Selling Logic for amd
            if self.nflx_rsi.Current.Value > 70:
                self.nflx_periods_above_70 += 1
                if self.nflx_periods_above_70 == 2 and nflx_current_price > nflx_sma:
                    self.LimitOrder("nflx", 10, nflx_current_price)
                   
            else:
                self.nflx_periods_above_70 = 0

            if self.nflx_rsi.Current.Value < 30:
                self.nflx_periods_below_30 += 1
                if self.nflx_periods_below_30 == 2 and nflx_current_price < nflx_sma:
                    if self.Portfolio[self.nflx_symbol].Quantity >= 10:
                        self.LimitOrder("nflx", -10, nflx_current_price)
                  
            else:
                self.nflx_periods_below_30 = 0

        # Calculate SMA for tsla
        if not tsla_history.empty:
            tsla_sma = tsla_history["close"].mean()
            tsla_current_price = slice.Bars[self.tsla_symbol].Close

            # Buying and Selling Logic for tsla (similar logic can be applied to amd)
            if self.tsla_rsi.Current.Value > 70:
                self.tsla_periods_above_70 += 1
                if self.tsla_periods_above_70 == 2 and tsla_current_price > tsla_sma:
                    self.LimitOrder("tsla", 21, tsla_current_price)
                   
            else:
                self.tsla_periods_above_70 = 0

            if self.tsla_rsi.Current.Value < 30:
                self.tsla_periods_below_30 += 1
                if self.tsla_periods_below_30 == 2 and tsla_current_price < tsla_sma:
                    if self.Portfolio[self.tsla_symbol].Quantity >= 21:
                        self.LimitOrder("tsla", -21, tsla_current_price)
                    
            else:
                self.tsla_periods_below_30 = 0

        # Calculate SMA for GOOG
        if not goog_history.empty:
            goog_sma = goog_history["close"].mean()
            goog_current_price = slice.Bars[self.goog_symbol].Close

            # Buying and Selling Logic for goog (similar logic can be applied to amd)
            if self.goog_rsi.Current.Value > 70:
                self.goog_periods_above_70 += 1
                if self.goog_periods_above_70 == 2 and goog_current_price > goog_sma:
                    self.LimitOrder("GOOG", 65, goog_current_price)
                   
            else:
                self.goog_periods_above_70 = 0

            if self.goog_rsi.Current.Value < 30:
                self.goog_periods_below_30 += 1
                if self.goog_periods_below_30 == 2 and goog_current_price < goog_sma:
                    if self.Portfolio[self.goog_symbol].Quantity >= 65:
                        self.LimitOrder("GOOG", -65, goog_current_price)
                    
            else:
                self.goog_periods_below_30 = 0

    def Rebalance(self):
        # Rebalance logic goes here
        pass
        
        if self.docu_rsi.IsReady:
            # The current value of self.rsi is represented by self.rsi.Current.Value
            self.Plot("RelativeStrengthIndex", "rsi", self.docu_rsi.Current.Value)
            # Plot all attributes of self.rsi
            self.Plot("RelativeStrengthIndex", "averagegain", self.docu_rsi.AverageGain.Current.Value)
            self.Plot("RelativeStrengthIndex", "averageloss", self.docu_rsi.AverageLoss.Current.Value)

        if self.amd_rsi.IsReady:
            # The current value of self.rsi is represented by self.rsi.Current.Value
            self.Plot("RelativeStrengthIndex", "rsi", self.amd_rsi.Current.Value)
            # Plot all attributes of self.rsi
            self.Plot("RelativeStrengthIndex", "averagegain", self.amd_rsi.AverageGain.Current.Value)
            self.Plot("RelativeStrengthIndex", "averageloss", self.amd_rsi.AverageLoss.Current.Value)
        
        if self.nflx_rsi.IsReady:
            # The current value of self.rsi is represented by self.rsi.Current.Value
            self.Plot("RelativeStrengthIndex", "rsi", self.nflx_rsi.Current.Value)
            # Plot all attributes of self.rsi
            self.Plot("RelativeStrengthIndex", "averagegain", self.nflx_rsi.AverageGain.Current.Value)
            self.Plot("RelativeStrengthIndex", "averageloss", self.nflx_rsi.AverageLoss.Current.Value)

        if self.tsla_rsi.IsReady:
            # The current value of self.rsi is represented by self.rsi.Current.Value
            self.Plot("RelativeStrengthIndex", "rsi", self.tsla_rsi.Current.Value)
            # Plot all attributes of self.rsi
            self.Plot("RelativeStrengthIndex", "averagegain", self.tsla_rsi.AverageGain.Current.Value)
            self.Plot("RelativeStrengthIndex", "averageloss", self.tsla_rsi.AverageLoss.Current.Value)

        if self.goog_rsi.IsReady:
            # The current value of self.rsi is represented by self.rsi.Current.Value
            self.Plot("RelativeStrengthIndex", "rsi", self.goog_rsi.Current.Value)
            # Plot all attributes of self.rsi
            self.Plot("RelativeStrengthIndex", "averagegain", self.goog_rsi.AverageGain.Current.Value)
            self.Plot("RelativeStrengthIndex", "averageloss", self.goog_rsi.AverageLoss.Current.Value)