Overall Statistics |
Total Trades 7 Average Win 0.58% Average Loss 0% Compounding Annual Return 48.493% Drawdown 1.500% Expectancy 0 Net Profit 3.415% Sharpe Ratio 3.821 Probabilistic Sharpe Ratio 78.916% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0.087 Annual Variance 0.007 Information Ratio 3.821 Tracking Error 0.087 Treynor Ratio 0 Total Fees $7.00 Estimated Strategy Capacity $430000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X |
from AlgorithmImports import * #endregion import numpy as np import pandas as pd class GapAndGoAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2023, 1, 1) # Set start date self.SetEndDate(2023, 1, 31) # Set end date self.SetCash(100000) # Set strategy cash # Add SPY to the universe and request daily data for it self.AddEquity("SPY", Resolution.Daily) # Use universe selection to select a universe of stocks that are gapping up self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) self.SelectionCount = 10 self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) # Set brokerage model self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen("SPY", 30), self.GapAndGo) # Schedule GapAndGo function to run after market open def CoarseSelectionFunction(self, coarse): # Select only stocks with a price above $5 and a daily dollar volume above $10,000,000 selected = [x.Symbol for x in coarse if x.Price > 5 and x.DollarVolume > 10000000] return selected def FineSelectionFunction(self, fine): # Select stocks that gapped up at least 1% and have positive earnings and revenue growth fine = [x for x in fine if hasattr(x.EarningReports, 'BasicEPSGrowth') and x.EarningReports.BasicEPSGrowth.OneYear > 0 and x.FinancialStatements.RevenueGrowth.OneYear > 0] fine = [x for x in fine if (x.Open - x.Close[-2])/x.Close[-2] > 0.01] fine = sorted(fine, key=lambda x: (x.Volume, x.Price), reverse=True)[:self.SelectionCount] return [x.Symbol for x in fine] def GapAndGo(self): # Loop over all securities in the portfolio for security in self.Portfolio.Values: # Check if the security is currently tradable if not self.Securities[security.Symbol].IsTradable: continue # Get daily historical data for the last 2 days history = self.History([security.Symbol], 2, Resolution.Daily) # Get opening and closing prices for the last 2 days opens = history.loc[security.Symbol].open.values closes = history.loc[security.Symbol].close.values # Check if the open price today is greater than the close price of yesterday if opens[-1] > closes[-2]: # Calculate the percentage change between the two days pct_change = (closes[-1] - closes[-2]) / closes[-2] # If the percentage change is greater than 1% (i.e., a gap), execute a trade if pct_change > 0.01: # Calculate the stop loss and take profit levels based on the current price current_price = self.Securities[security.Symbol].Price stop_loss = np.array([current_price * 0.98]).item() take_profit = np.array([current_price * 1.02]).item() quantity = 100 # Place the market order with stop loss and take profit levels #, False, None, stop_loss, take_profit self.ticket = self.MarketOrder(security.Symbol, quantity) self.LimitOrder(security.Symbol, -quantity, self.ticket.AverageFillPrice* 1.02) self.StopMarketOrder(security.Symbol, -quantity, self.ticket.AverageFillPrice* 0.98) def OnOrderEvent(self, orderEvent): order = self.Transactions.GetOrderById(orderEvent.OrderId) if order.Status == OrderStatus.Filled: if order.Type == OrderType.Limit or order.Type == OrderType.StopMarket: self.Transactions.CancelOpenOrders(order.Symbol)