Overall Statistics |
Total Trades 56 Average Win 0% Average Loss 0.00% Compounding Annual Return -0.383% Drawdown 0.100% Expectancy -1 Net Profit -0.057% Sharpe Ratio -10.721 Probabilistic Sharpe Ratio 0% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.003 Beta -0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -3.25 Tracking Error 0.234 Treynor Ratio 32.246 Total Fees $56.00 Estimated Strategy Capacity $130000.00 Lowest Capacity Asset AGFY XLIR2IEBJNFP |
# region imports from AlgorithmImports import * # endregion # Import statistics import statistics # Import datetime import datetime class VirtualGreenHornet(QCAlgorithm): def Initialize(self): # Set Start Date self.SetStartDate(2022, 10, 1) # Set End Date # self.SetEndDate(2022, 10, 5) # Set Strategy Cash self.SetCash(100000) # Add universe self.AddUniverse(self.Coarse, self.Fine) # Add SPY self.SPY_symbol = self.AddEquity("SPY", Resolution.Minute, extendedMarketHours = True).Symbol # Universe extended hours self.UniverseSettings.ExtendedMarketHours = True # Universe resolution self.UniverseSettings.Resolution = Resolution.Minute # # # Storage # # # # Symbols storage self.symbols_list = [] # Consolidator dictionary self.consolidator_dictionary = {} # 9:30 am price self.day_starting_price = {} # Volume self.day_candles = {} # List to store stocks that pass scanning component self.list_1 = [] # Counter self.counter = 0 # 5-minute consolidator dictionary self.five_minute_consolidator_dictionary = {} # 5-minute bar dictionary self.five_minute_bar_dictionary = {} # Counter 2 self.counter_2 = 0 # 10-minute consolidator dictionary self.ten_minute_consolidator_dictionary = {} # 5-minute bar dictionary self.ten_minute_bar_dictionary = {} # Counter 3 self.counter_3 = 0 # List 2 self.list_2 = [] # RSI storage self.RSI_storage = {} # RSI values storage self.RSI_values = {} # Warm up self.warm_up = False # # # End storage # # # # Schedule 1 self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 1), self.MinuteAfterMarketOpen) # Schedule 2 self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 5), self.LiquidateHoldings) def Coarse(self, coarse): # Return list return_list = [] # # List list_one = [x.Symbol for x in coarse if x.HasFundamentalData and x.Price > 0.4] # # History history = self.History(list_one, 90, Resolution.Daily) # # Loop for symbol in list_one: # Check if has history if str(symbol) in history.index: # Loc symbol_history = history.loc[symbol] # If length equal to 90 if len(symbol_history) == 90: # Average volume average_volume = symbol_history["volume"].mean() # If average volume above 500,000 if average_volume > 500000: # Add to return list return_list.append(symbol) # Return return return_list def Fine(self, fine): # Return return [x.Symbol for x in fine if x.CompanyReference.PrimaryExchangeID == "NAS"] def OnSecuritiesChanged(self, changes): # Symbols symbols = [x.Symbol for x in changes.AddedSecurities] # 6-period rsi random_rsi = RelativeStrengthIndex(6) # Warm up period warm_up_period = random_rsi.WarmUpPeriod * 5 # History history = self.History(symbols, warm_up_period, Resolution.Minute) # Warm up set to False self.warm_up = False problem = [] # Loop added for symbol in symbols: # Check if symbol is SPY if symbol != self.SPY_symbol: # If symbol has historical data if str(symbol) in history.index: # Loc symbol_history = history.loc[symbol] # If length == requested if len(symbol_history) == warm_up_period: # Add to symbols list self.symbols_list.append(symbol) # Consolidator self.consolidator_dictionary[symbol] = TradeBarConsolidator(timedelta(minutes = 15)) # Consolidated handler self.consolidator_dictionary[symbol].DataConsolidated += self.consolidation_handler # Register the consolidator for automatic updates self.SubscriptionManager.AddConsolidator(symbol, self.consolidator_dictionary[symbol]) # Consolidator self.five_minute_consolidator_dictionary[symbol] = TradeBarConsolidator(timedelta(minutes = 5)) # Consolidated handler self.five_minute_consolidator_dictionary[symbol].DataConsolidated += self.five_minute_consolidation_handler # Register the consolidator for automatic updates self.SubscriptionManager.AddConsolidator(symbol, self.five_minute_consolidator_dictionary[symbol]) # 10-minute consolidator self.ten_minute_consolidator_dictionary[symbol] = TradeBarConsolidator(timedelta(minutes = 10)) # Consolidated handler self.ten_minute_consolidator_dictionary[symbol].DataConsolidated += self.ten_minute_consolidation_handler # Register the consolidator for automatic updates self.SubscriptionManager.AddConsolidator(symbol, self.ten_minute_consolidator_dictionary[symbol]) # RSI self.RSI_storage[symbol] = RelativeStrengthIndex(6) # Register self.RegisterIndicator(symbol = symbol, indicator = self.RSI_storage[symbol], consolidator = self.five_minute_consolidator_dictionary[symbol]) # Loop for time, row in symbol_history.iterrows(): # Try try: # Create candlestick bar = TradeBar(time - datetime.timedelta(minutes = 1), symbol, row.open, row.high, row.low, row.close, row.volume, datetime.timedelta(minutes = 1)) # Update self.five_minute_consolidator_dictionary[symbol].Update(bar) # Except except: # Symbol if symbol not in problem: # Add problem.append(symbol) # Warm up set to True self.warm_up = True # Loop for symbol in problem: # Unregister consolidator self.SubscriptionManager.RemoveConsolidator(symbol, self.consolidator_dictionary[symbol]) # Remove consolidator self.consolidator_dictionary.pop(symbol) # Remove self.symbols_list.remove(symbol) # Unregister consolidator self.SubscriptionManager.RemoveConsolidator(symbol, self.five_minute_consolidator_dictionary[symbol]) # Remove consolidator self.five_minute_consolidator_dictionary.pop(symbol) # Unregister consolidator self.SubscriptionManager.RemoveConsolidator(symbol, self.ten_minute_consolidator_dictionary[symbol]) # Remove consolidator self.ten_minute_consolidator_dictionary.pop(symbol) # RSI self.RSI_storage.pop(symbol) # Loop removed for security in changes.RemovedSecurities: # Symbol symbol = security.Symbol # If symbol in symbols list if symbol in self.symbols_list: # Unregister consolidator self.SubscriptionManager.RemoveConsolidator(symbol, self.consolidator_dictionary[symbol]) # Remove consolidator self.consolidator_dictionary.pop(symbol) # Remove self.symbols_list.remove(symbol) # Unregister consolidator self.SubscriptionManager.RemoveConsolidator(symbol, self.five_minute_consolidator_dictionary[symbol]) # Remove consolidator self.five_minute_consolidator_dictionary.pop(symbol) # Unregister consolidator self.SubscriptionManager.RemoveConsolidator(symbol, self.ten_minute_consolidator_dictionary[symbol]) # Remove consolidator self.ten_minute_consolidator_dictionary.pop(symbol) # RSI self.RSI_storage.pop(symbol) def MinuteAfterMarketOpen(self): # History history = self.History(self.symbols_list, 1, Resolution.Daily) # Loop for symbol in self.symbols_list: # If symbol has data if str(symbol) in history.index: # If price not more than 60% from yesterday close if self.Securities[symbol].Open < history.loc[symbol]["close"][-1] * 1.6: # Add to day starting price self.day_starting_price[symbol] = self.Securities[symbol].Open # Add to day candles self.day_candles[symbol] = [] # Add to 5-minute bar storage self.five_minute_bar_dictionary[symbol] = [] # Add to 10-minute bar storage self.ten_minute_bar_dictionary[symbol] = [] # Add to RSI values self.RSI_values[symbol] = [] def consolidation_handler(self, sender, bar): # Current time current_time = datetime.time(self.Time.hour, self.Time.minute) # 11 am eleven = datetime.time(11, 00) # 3:55 pm three = datetime.time(15, 55) # If symbol in day volume if bar.Symbol in self.day_candles: # Add self.day_candles[bar.Symbol].append(bar) # Add to counter self.counter += 1 # If counter equal to number of stocks in algo if self.counter == len(self.consolidator_dictionary): # Reset self.counter = 0 # If time is 11 if current_time >= eleven and current_time <= three: # History symbols list history_symbols_list = [] # Loop for symbol in self.day_starting_price: # If price greater than 5% from opening price if self.Securities[symbol].Close > self.day_starting_price[symbol] * 1.05: # Add history_symbols_list.append(symbol) # If length if len(history_symbols_list) > 0: # Get history history = self.History(history_symbols_list[-1], 5, Resolution.Daily) # Get timestamp timestamp = history.index[-1][-1] - timedelta(days = 1) # Start datetime start_datetime = datetime.datetime(timestamp.year, timestamp.month, timestamp.day, 9, 30) # End datetime end_datetime = datetime.datetime(timestamp.year, timestamp.month, timestamp.day, self.Time.hour, self.Time.minute) # Get history history = self.History(history_symbols_list, start_datetime, end_datetime, Resolution.Minute) # Loop for symbol in history_symbols_list: # If symbol in history if str(symbol) in history.index: # Get current volume current_volume = sum([x.Volume for x in self.day_candles[symbol]]) # If current volume greater than 300,000 if current_volume > 300000: # Symbol history symbol_history = history.loc[symbol] # Previous day volume previous_volume = symbol_history["volume"].sum() # If current volume 5 times previous volume if current_volume > previous_volume * 5: # If not in list 1 if symbol not in self.list_1: # Add self.list_1.append(symbol) def five_minute_consolidation_handler(self, sender, bar): # If not warm up if self.warm_up == True: # Add self.counter_2 += 1 # If symbol in 5-minute bar dictionary if bar.Symbol in self.five_minute_bar_dictionary: # Add self.five_minute_bar_dictionary[bar.Symbol].append(bar) # If symbol in RSI values storage if bar.Symbol in self.RSI_values: # Add self.RSI_values[bar.Symbol].append(self.RSI_storage[bar.Symbol].Current.Value) # If counter equal length if self.counter_2 == len(self.consolidator_dictionary): # Reset self.counter_2 = 0 # If length of list 2 above 0 if len(self.list_2) > 0: # Loop for symbol in self.list_2: # If not invested if not self.Portfolio[symbol].Invested: # Past 3 RSI past_3_RSI = self.RSI_values[symbol][-3:] # If max above 70 if max(past_3_RSI) > 70: # If current bar is red if self.five_minute_bar_dictionary[symbol][-1].Close < self.five_minute_bar_dictionary[symbol][-1].Open: # If 2 bars prior is green if self.five_minute_bar_dictionary[symbol][-3].Open < self.five_minute_bar_dictionary[symbol][-3].Close: # If current bar bigger than previous if abs(self.five_minute_bar_dictionary[symbol][-1].Close - self.five_minute_bar_dictionary[symbol][-1].Open) > abs(self.five_minute_bar_dictionary[symbol][-2].Close - self.five_minute_bar_dictionary[symbol][-2].Open): # If 2 bars prior bigger than previous if abs(self.five_minute_bar_dictionary[symbol][-3].Close - self.five_minute_bar_dictionary[symbol][-3].Open) > abs(self.five_minute_bar_dictionary[symbol][-2].Close - self.five_minute_bar_dictionary[symbol][-2].Open): # Short self.MarketOrder(symbol, -1) def ten_minute_consolidation_handler(self, sender, bar): # Add self.counter_3 += 1 # If symbol in 10-minute bar dictionary if bar.Symbol in self.ten_minute_bar_dictionary: # Add self.ten_minute_bar_dictionary[bar.Symbol].append(bar) # If counter equal length if self.counter_3 == len(self.consolidator_dictionary): # Reset self.counter_3 = 0 # If length of list 1 above 0 if len(self.list_1) > 0: # Loop for symbol in self.list_1: # Bars bars = self.ten_minute_bar_dictionary[symbol] # Recent bar value recent_bar_value = bars[-1].Close - bars[-1].Open # List new_list = [(x.Close - x.Open) for x in bars] # Reverse new_list.reverse() # Bars reverse bars.reverse() # If red if recent_bar_value < 0: # Loop for value in new_list: # If value greater than 0 if value > 0: # Get value as direcional change directional_change = bars[new_list.index(value)].Close # Get highest close highest_close = max([x.Close for x in bars]) # Get open open_price = self.day_starting_price[symbol] # Difference difference = highest_close - open_price # 40% of difference fourty_percent = difference * 0.4 # If current close - directional change more than 40% of difference if self.ten_minute_bar_dictionary[symbol][-1].Close - directional_change > fourty_percent: # Add to list 2 self.list_2.append(symbol) # If green elif recent_bar_value > 0: # Loop for value in new_list: # If value less than 0 if value < 0: # Get value as direcional change directional_change = bars[new_list.index(value)].Close # Get highest close highest_close = max([x.Close for x in bars]) # Get open open_price = self.day_starting_price[symbol] # Difference difference = highest_close - open_price # 40% of difference fourty_percent = difference * 0.4 # If current close - directional change more than 40% of difference if self.ten_minute_bar_dictionary[symbol][-1].Close - directional_change > fourty_percent: # Add to list 2 self.list_2.append(symbol) def LiquidateHoldings(self): # Sell everything self.Liquidate() # Remove self.list_1.clear() # Remove self.day_starting_price.clear() # Remove self.day_candles.clear() # Remove self.five_minute_bar_dictionary.clear() # Remove self.ten_minute_bar_dictionary.clear() # Remove self.list_2.clear() # Remove self.RSI_values.clear() def OnData(self, data: Slice): pass