Overall Statistics
Total Trades
2
Average Win
0%
Average Loss
-0.62%
Compounding Annual Return
-67.657%
Drawdown
0.800%
Expectancy
-1
Net Profit
-0.617%
Sharpe Ratio
-7.813
Probabilistic Sharpe Ratio
0%
Loss Rate
100%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
-0.108
Beta
0.591
Annual Standard Deviation
0.069
Annual Variance
0.005
Information Ratio
4.002
Tracking Error
0.048
Treynor Ratio
-0.914
Total Fees
$6.63
from Risk.MaximumDrawdownPercentPerSecurity import MaximumDrawdownPercentPerSecurity
class TransdimensionalParticleThrustAssembly(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2020, 10, 29) # Set Start Date
        self.SetEndDate(2020, 10, 30) # Set End Date
        self.SetCash(100000) # Set Strategy Cash
        self.AddEquity("SPY", Resolution.Minute) # Add SPY to set scheduled events
        self.UniverseSettings.Resolution = Resolution.Minute # Setting Universe
        self.SetUniverseSelection(FineFundamentalUniverseSelectionModel(self.CoarseSelectionFunction, self.FineSelectionFunction, None, None)) # self.SetUniverseSelection(QC500UniverseSelectionModel())
        self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.2))
        # self.__numberOfSymbols = 100
        # self.__numberOfSymbolsFine = 5
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 2), self.Rebalance) # Our Scheduled Events
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 30), self.OnMarketClose)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday) , self.TimeRules.BeforeMarketClose("SPY", 35), self.GetTopPerformers)
        self.previousClose = {} # Dictionary to keep track of previous close for each symbol
        self.performance = {} # Dictionary to keep track of weekly cumulative performance for each symbol
        self.top = [] # list for top performers of week
        self.cashused = 10000
        
    def OnData(self, data): # OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        #Arguments: data: Slice object keyed by symbol containing the stock data
        pass
        #for sec in self.Portfolio:
            #if sec.UnrealizedProfitPercent < .2:
                #self.Liquidate()
    
    def CoarseSelectionFunction(self, coarse): # Picks up securities Universe.  Constructed at midnight of night before.
        return [x.Symbol for x in coarse if 20 > x.Price]
    
    def FineSelectionFunction(self, fine): # Picks up securities from Coarse > Universe.  Constructed at midnight of night before.
        return [x.Symbol for x in fine if x.MarketCap > 5000000000]
        
    def OnSecuritiesChanged(self, changes): # Picks up securities from the Fine > Coarse > Universe.  Constructed at midnight of night before.
        for security in changes.AddedSecurities: # AddedSecurities are those populated by Fine > Coarse > Universe
            symbol = security.Symbol
            if symbol not in self.previousClose: # Make a history call for symbol to get last closing price
                history = self.History(symbol, 1, Resolution.Daily)
                if not history.empty:
                    history = history.close.unstack(0)[symbol]
                    if not history.empty:
                        self.previousClose[symbol] = history[0]
        for security in changes.RemovedSecurities: # Remove symbols from previous close as they are removed from the universe
            symbol = security.Symbol
            self.previousClose.pop(symbol, None)
                
    def Rebalance(self):
        percentChange = {} # Dictionary to keep track of percent change from last close
        for symbol, previousClose in self.previousClose.items(): # Populate Dictionary
            if self.CurrentSlice.ContainsKey(symbol):
                price = self.CurrentSlice[symbol].Close
                change = price/previousClose # (price - previousClose)/previousClose
                percentChange[symbol] = change
        symbols = list(percentChange.keys()) # Symbols under consideration
        sortedSymbols = sorted([x for x in symbols if percentChange[x] > 1.1], key=lambda x : percentChange[x], reverse = True) # Sort symbols by percent change
        selected = sortedSymbols[:1] # Get top xx symbols
        for symbol in selected:
            #self.StopMarketOrder(symbol, -self.cashused/price, price*1.2) # Stop loss 20% higher than purchase price
            price = self.Securities[symbol].Price
            self.MarketOrder(symbol, self.cashused/price)
    
    def OnMarketClose(self):
        for kvp in self.Portfolio: # Store cumulative performance for symbols in portfolio
            symbol = kvp.Key
            holding = kvp.Value
            if holding.Invested:
                if symbol not in self.performance:
                    self.performance[symbol] = holding.UnrealizedProfitPercent
                else:
                    self.performance[symbol] = self.performance[symbol] + holding.UnrealizedProfitPercent
        self.Liquidate() # Liquidate portfolio
        for symbol in self.previousClose: # Store new previous close values
            if self.CurrentSlice.ContainsKey(symbol):
                self.previousClose[symbol] = self.CurrentSlice[symbol].Close
    
    def GetTopPerformers(self):
        symbols = list(self.performance.keys()) # Symbols under consideration
        sortedSymbols = sorted(symbols, key=lambda x: self.performance[x], reverse=True) # Symbols sorted by performance
        self.top = sortedSymbols[:10] # Top 10 performers
        self.performance = {} # Reset performances
        
        #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 'NumberOfSymbols' top entries from our sorted collection
        #c_filter = sorted([x for x in coarse if x.HasFundamentalData and 13 > x.Price > 1], key=lambda x: x.DollarVolume, reverse=True)[:self.numberOfSymbolsCoarse]
        
        #sortedByPeRatio = sorted(fine, key=lambda x: x.ValuationRatios.PERatio, reverse=True) #Sort descending by P/E ratio
        #return [x.Symbol for x in sortedByPeRatio[:self.__numberOfSymbolsFine]] #Take the top 'NumberOfSymbolsFine' entries from our sorted collection
        
        #f_filter = [x for x in fine if x.MarketCap < 5000000000]
        #return [x.Symbol for x in f_filter]
        
        # https://www.quantconnect.com/forum/discussion/7328/noob-question-how-to-do-qc500-intraday-universe-selection-for-top-gainers-since-previous-close/p1
        # https://www.quantconnect.com/forum/discussion/1031/algorithm-for-scanning-premarket-stocks-unusual-volume-and-volatility
        # https://www.quantconnect.com/forum/discussion/7519/filter-for-equities-up-10-on-the-day/p1
        # https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/Alphas/SykesShortMicroCapAlpha.py
        # https://www.quantconnect.com/tutorials/strategy-library/small-capitalization-stocks-premium-anomaly
        # https://www.quantconnect.com/forum/discussion/2317/migrating-from-quantopian-to-quantconnect/p2
        # https://www.quantconnect.com/forum/discussion/7364/fading-the-gap-for-different-stocks/p1