Overall Statistics
Total Trades
5
Average Win
0.54%
Average Loss
0%
Compounding Annual Return
128.221%
Drawdown
3.100%
Expectancy
0
Net Profit
8.234%
Sharpe Ratio
8.613
Probabilistic Sharpe Ratio
95.161%
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
0.603
Beta
0.193
Annual Standard Deviation
0.135
Annual Variance
0.018
Information Ratio
-6.021
Tracking Error
0.289
Treynor Ratio
6.023
Total Fees
$0.00
class UniverseRollingAlgorithm(QCAlgorithm):
    
    def Initialize(self):       #Initialize Dates, Cash, Equities, Fees, Allocation, Parameters, Indicators, Charts
        
        # Set Start Date, End Date, and Cash
        #-------------------------------------------------------
        self.SetTimeZone(TimeZones.NewYork)     #EDIT: Added Timezon
        self.SetStartDate(2020, 4, 1)   # Set Start Date
        self.SetEndDate(2020, 5, 5)      # Set End Date
        self.SetCash(100000)            # Set Strategy Cash
        #-------------------------------------------------------
        
        # Set Custom Universe
        #-------------------------------------------------------
        self.AddUniverse(self.CoarseSelectionFilter, self.FineSelectionFilter)
        self.UniverseSettings.Resolution = Resolution.Minute    #Needs to change to Resolution.Minute once code works, leaving Daily for now to minimize data
        self.UniverseSettings.SetDataNormalizationMode = DataNormalizationMode.SplitAdjusted
        self.UniverseSettings.FeeModel = ConstantFeeModel(0.0)
        self.UniverseSettings.Leverage = 1
        #-------------------------------------------------------
        
        self.SetBrokerageModel(BrokerageName.Alpaca, AccountType.Cash)      #EDIT: Added Brokerage, appears to have set fees to zero
        
        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(0, 0), self.UniEquityPicks)   #EDIT: Added scheduled event to prevent universe from triggering at minute intervals
        self.init_uni_picks = True      #Initialize flag only true once
        self.uni_picks = False          #second flag to switch on/off
        
        self.EMA_Period_Fast = 20
        self.EMA_Period_Slow = 50

        self.__numberOfSymbols     = 100
        self.__numberOfSymbolsFine = 10
        
        self.indicators = {}
        
        # Define Percentage Allocation
        #-------------------------------------------------------
        self.percentagebuy = 0.1
        #-------------------------------------------------------
        
            
    def CoarseSelectionFilter(self, coarse):
        if self.uni_picks or self.init_uni_picks:
            sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)   # sort descending by daily dollar volume
            return [ x.Symbol for x in sortedByDollarVolume[:self.__numberOfSymbols] ]  # return the symbol objects of the top entries from our sorted collection
        else: 
            return Universe.Unchanged
    
    def FineSelectionFilter(self, fine):  # sort the data by P/E ratio and take the top 'NumberOfSymbolsFine'
        if self.uni_picks or self.init_uni_picks:
            self.init_uni_picks = False   #False for the rest of program operation
            self.uni_picks = False
            sortedByPeRatio = sorted(fine, key=lambda x: x.OperationRatios.OperationMargin.Value, reverse=False)    # sort descending by P/E ratio
            self.universe = [ x.Symbol for x in sortedByPeRatio[:self.__numberOfSymbolsFine] ]  # take the top entries from our sorted collection
            return self.universe
        else: 
            return Universe.Unchanged
    
    def OnSecuritiesChanged(self, changes):
        # Create indicator for each new security
        for security in changes.AddedSecurities:
            self.indicators[security.Symbol] = SymbolData(security.Symbol, self, self.EMA_Period_Fast, self.EMA_Period_Slow)
        
        for security in changes.RemovedSecurities:
            if security.Invested:
                self.Liquidate(security.Symbol, "Universe Removed Security")
            
            if security in self.indicators:
                del self.indicators[security.Symbol]  # UNVERIFIED EDIT - Shifted del command outside of if statement, need to test
                
    def UniEquityPicks(self):
        self.uni_picks = True
    
    def OnData(self, data):         #Entry Point for Data and algorithm - Check Data, Define Buy Quantity, Process Volume, Check Portfolio, Check RSI, Execute Buy/Sell orders, Chart Plots
        for symbol in self.universe:
            
            if not data.ContainsKey(symbol):    #Tested and Valid/Necessary
                continue
            
            if data[symbol] is None:            #Tested and Valid/Necessary
                continue
            
            if not symbol in self.indicators:    #Tested and Valid/Necessary
                continue
            
            # Check for Indicator Readiness within Rolling Window
            #-------------------------------------------------------
            if not (self.indicators[symbol].fast_ema_window.IsReady and self.indicators[symbol].slow_ema_window.IsReady): 
                continue    #return     #EDIT 
            
            #self.Debug("Get Fast EMA = " + str(self.indicators[symbol].get_fast_EMA()) + " window[0] = " + str(self.indicators[symbol].fast_ema_window[0]))
            
            '''
            if self.Time.hour == 10 and self.Time.minute == 0 and self.Time.minute < 2:
                self.Debug("Rolling Fast Index[0] = " + str(symbol) + "-EMA : " + str(self.indicators[symbol].fast_ema_window[0]))
                self.Debug("Rolling Slow Index[0] = " + str(symbol) + "-EMA : " + str(self.indicators[symbol].fast_ema_window[1]))
                self.Debug("Rolling Fast Index[4] = " + str(symbol) + "-EMA : " + str(self.indicators[symbol].fast_ema_window[2]))
                self.Debug("Rolling Slow Index[4] = " + str(symbol) + "-EMA : " + str(self.indicators[symbol].fast_ema_window[3]))
                self.Debug("Rolling Slow Index[4] = " + str(symbol) + "-EMA : " + str(self.indicators[symbol].fast_ema_window[4]))
                self.Debug(" ")
            '''
            #Check time for live debugging
            checkhour = self.Time.hour
            checkminute = self.Time.minute
            
            #EXECUTE TRADING LOGIC HERE - 
            self.buyquantity = round((self.percentagebuy*self.Portfolio.TotalPortfolioValue)/data[symbol].Close)
            
            if (not self.Portfolio[symbol].Invested) and (self.Portfolio.MarginRemaining > 0.9*self.percentagebuy*self.Portfolio.TotalPortfolioValue):
                if (self.indicators[symbol].fast_ema_window[1] >= self.indicators[symbol].slow_ema_window[1]) and (self.indicators[symbol].fast_ema_window[4] < self.indicators[symbol].slow_ema_window[4]):
                    self.MarketOrder(symbol, self.buyquantity)
            
            #if self.Portfolio[symbol].Invested: #Remove if implementing Short Strategies
            if self.indicators[symbol].fast_ema_window[1] <= self.indicators[symbol].slow_ema_window[1] and (self.indicators[symbol].fast_ema_window[4] > self.indicators[symbol].slow_ema_window[4]):
                self.Liquidate(symbol)   #self.MarketOrder(symbol, self.buyquantity)
               
            #elif self.EMA_FastWin[0] < self.EMA_SlowWin[0] and self.EMA_FastWin[1] > self.EMA_SlowWin[1]:
            #    self.Liquidate(security.Key7

class SymbolData(object):
    
    rolling_window_length = 5
    
    def __init__(self, symbol, context, fast_ema_period, slow_ema_period):
        
        self.symbol = symbol
        self.fast_ema_period = fast_ema_period
        self.slow_ema_period = slow_ema_period
        self.fast_ema = context.EMA(symbol, self.fast_ema_period, Resolution.Minute)    #, fillDataForward = True, leverage = 1, extendedMarketHours = False)
        self.slow_ema = context.EMA(symbol, self.slow_ema_period, Resolution.Minute)    #, fillDataForward = True, leverage = 1, extendedMarketHours = False)
        self.fast_ema_window = RollingWindow[float](self.rolling_window_length)
        self.slow_ema_window = RollingWindow[float](self.rolling_window_length)
        
        # Warm up EMA indicators
        history = context.History([symbol], slow_ema_period + self.rolling_window_length, Resolution.Minute)
        for time, row in history.loc[symbol].iterrows():
            self.fast_ema.Update(time, row["close"])
            self.slow_ema.Update(time, row["close"])
            
            # Warm up rolling windows
            if self.fast_ema.IsReady:
                self.fast_ema_window.Add(self.fast_ema.Current.Value)
            if self.slow_ema.IsReady:
                self.slow_ema_window.Add(self.slow_ema.Current.Value)
    
    def get_fast_EMA(self):
        return self.fast_ema.Current.Value
        
    def get_slow_EMA(self):
        return self.slow_ema.Current.Value