Overall Statistics
Total Trades
1191
Average Win
0.73%
Average Loss
-0.63%
Compounding Annual Return
10.609%
Drawdown
32.900%
Expectancy
0.066
Net Profit
963.801%
Sharpe Ratio
0.555
Probabilistic Sharpe Ratio
0.341%
Loss Rate
51%
Win Rate
49%
Profit-Loss Ratio
1.15
Alpha
0.039
Beta
0.786
Annual Standard Deviation
0.153
Annual Variance
0.023
Information Ratio
0.284
Tracking Error
0.092
Treynor Ratio
0.108
Total Fees
$1589.49
Estimated Strategy Capacity
$630000000.00
Lowest Capacity Asset
IWM RV0PWMLXVHPH
Portfolio Turnover
4.61%
from AlgorithmImports import *


class MovingAverageStrategy(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2000, 1, 1)
        self.SetCash(30000)
        self.cash=30000
        self.AddEquity("QQQ", Resolution.Daily)
        self.AddEquity("IWM", Resolution.Daily)
        self.AddEquity("SPY", Resolution.Daily)
        self.spyatr = self.ATR("SPY", 10, Resolution.Daily)
        self.qqqatr = self.ATR("QQQ", 10, Resolution.Daily)
        self.iwmatr = self.ATR("IWM", 10, Resolution.Daily)
        self.profit_target = {}
        self.profit_target["SPY"] = 0
        self.profit_target["QQQ"] = 0
        self.profit_target["IWM"] = 0
        self.entry={}
        self.avol = {}
        self.df = pd.DataFrame()
        self.entry["SPY"]=0
        self.entry["QQQ"]=0
        self.entry["IWM"]=0
        


        self.fastMA = {
            "QQQ": self.SMA("QQQ", 4),
            "IWM": self.SMA("IWM", 10),
            "SPY": self.SMA("SPY", 4)
        }

        self.slowMA = {
            "QQQ": self.SMA("QQQ", 90),
            "IWM": self.SMA("IWM", 100),
            "SPY": self.SMA("SPY", 50)
        }

        self.investment = {
            "QQQ": 10000,
            "IWM": 10000,
            "SPY": 10000
        }

        self.SetWarmUp(100)


       

    def OnData(self, data):
        if self.IsWarmingUp:
            return
        # self.Debug(f"value of portfolio: {self.Portfolio.TotalHoldingsValue}")
        # self.df = self.df.append({"PortfolioValue": self.Portfolio.TotalHoldingsValue}, ignore_index=True)
        
        # returns = self.df['PortfolioValue'].pct_change().dropna()
        # rolling_std = returns.tail(20).std()
        # self.volatility = rolling_std * np.sqrt(252)
        # self.Log(f"Portfolio value: {self.Portfolio.TotalHoldingsValue}, Volatility: {self.volatility}")
        # if not self.Portfolio.Invested:
        #         self.df = self.df.append({"PortfolioValue": self.cash}, ignore_index=True)
        # if math.isnan(self.volatility) == False and self.volatility > 0.5:
        #     self.Liquidate()
        
        for symbol in ["QQQ", "IWM", "SPY"]:
          
         history = self.History([symbol], timedelta(days=20), Resolution.Daily)
         if not history.empty:
                # Calculate daily returns
                returns = history['close'].pct_change()[1:]
          

            # Calculate annualized volatility
         volatility = np.std(returns) * np.sqrt(252)
         self.avol[symbol] = round(volatility,2)


        for symbol in ["QQQ", "IWM", "SPY"]:
            if not self.Portfolio[symbol].Invested:
                if (self.fastMA[symbol].Current.Value > self.Securities[symbol].Close and self.Securities[symbol].Close < self.fastMA[symbol].Current.Value and  self.avol[symbol] < 0.5):
                    investment_size = self.investment[symbol] / self.Securities[symbol].Close
                    if (self.avol[symbol] > 0.10 and self.avol[symbol] < 0.45):
                     self.SetHoldings(symbol, 1 / 3)
                     self.entry[symbol]=  self.Securities[symbol].Price
                     self.Log("avol of symbol"+str(symbol)+": "+str(self.avol[symbol]))

        if self.spyatr.IsReady:
            self.Debug("inside spyatr")
            symbol = "SPY"
            entry_price = self.Portfolio[symbol].AveragePrice
            self.profit_target[symbol] =  self.entry[symbol] + 3.5 * self.spyatr.Current.Value

            self.Debug('profit target is ' + str(self.profit_target[symbol]))
            if self.Portfolio[symbol].Invested:
                if self.Securities[symbol].High >= self.profit_target[symbol]:
                
                  #  self.Liquidate(symbol, "profit")
                    self.Debug("liquidated")
                    
                else:
                    if self.Securities[symbol].Close < self.slowMA[symbol].Current.Value and self.slowMA[symbol].Current.Value > self.fastMA[symbol].Current.Value:
                    
                        self.Liquidate(symbol)

            
        if self.qqqatr.IsReady:
            self.Debug("inside qqqatr")
            symbol = "QQQ"
            entry_price = self.Portfolio[symbol].AveragePrice
            self.profit_target[symbol] =  self.entry[symbol] + 3.5 * self.qqqatr.Current.Value
            self.Debug('profit target is ' + str(self.profit_target[symbol]))
            if self.Portfolio[symbol].Invested:
                if self.Securities[symbol].High >= self.profit_target[symbol]:
                
                   # self.Liquidate(symbol, "profit")
                    self.Debug("liquidated")
                else:
                    if self.Securities[symbol].Close < self.slowMA[symbol].Current.Value and self.slowMA[symbol].Current.Value > self.fastMA[symbol].Current.Value:
                    
                        self.Liquidate(symbol)

           

        if self.iwmatr.IsReady:
            self.Debug("inside iwmatr")
            symbol = "IWM"
            entry_price = self.Portfolio[symbol].AveragePrice
            self.profit_target[symbol] =  self.entry[symbol] + 3.5 * self.iwmatr.Current.Value

            self.Debug('profit target is ' + str(self.profit_target[symbol]))
            if self.Portfolio[symbol].Invested:
                if self.Securities[symbol].High >= self.profit_target[symbol]:
                
                  #  self.Liquidate(symbol, "profit")
                    self.Debug("liquidated")
                else:
                    if self.Securities[symbol].Close < self.slowMA[symbol].Current.Value and self.slowMA[symbol].Current.Value > self.fastMA[symbol].Current.Value:
                  
                        self.Liquidate(symbol)
    def OnOrderEvent(self, OrderEvent):
        if OrderEvent.FillQuantity == 0:
            return
       
      #  self.entry[OrderEvent.Symbol] = round(OrderEvent.FillPrice*1, 2);