| Overall Statistics |
|
Total Trades 4486 Average Win 4.20% Average Loss -3.36% Compounding Annual Return 268.850% Drawdown 56.700% Expectancy 0.121 Net Profit 36676.994% Sharpe Ratio 3.044 Probabilistic Sharpe Ratio 87.254% Loss Rate 50% Win Rate 50% Profit-Loss Ratio 1.25 Alpha 2.826 Beta -0.18 Annual Standard Deviation 0.92 Annual Variance 0.847 Information Ratio 2.839 Tracking Error 0.939 Treynor Ratio -15.559 Total Fees $0.00 Estimated Strategy Capacity $910000.00 Lowest Capacity Asset WVVI R735QTJ8XC9X |
import pandas as pd
from io import StringIO
class ShortGappers(QCAlgorithm):
estimated_capacity = None
gapper_data = None
premarket_high = {}
traded_today = set()
def Initialize(self):
self.gapper_data = pd.read_csv(StringIO(self.Download("https://raw.githubusercontent.com/lieblius/financial-data/main/gappers.csv")), index_col='Date')
self.estimated_capacity = int(self.GetParameter("estimated-capacity"))
self.SetStartDate(2016, 10, 26)
self.SetEndDate(2021, 5, 4)
self.SetCash(1000)
self.SetExecution(ImmediateExecutionModel())
self.UniverseSettings.Resolution = Resolution.Minute
self.SetSecurityInitializer(self.CustomSecurityInitializer)
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 30) , self.ClosePositions)
self.AddUniverseSelection(ScheduledUniverseSelectionModel(
self.DateRules.EveryDay(),
self.TimeRules.At(00, 00),
self.SelectSymbols
))
def CustomSecurityInitializer(self, security):
security.SetDataNormalizationMode(DataNormalizationMode.Raw)
security.SetFeeModel(ConstantFeeModel(0))
security.SetSlippageModel(ConstantSlippageModel(0))
security.SetFillModel(ImmediateFillModel())
def OnData(self, data):
if 9 <= self.Time.hour < 12 :
if self.Time.hour == 9 and self.Time.minute < 30:
return
for security in self.ActiveSecurities:
equity = security.Value
symbol = equity.Symbol
symbol_string = symbol.Value
if not equity.HasData:
continue
if equity.Invested:
continue
if symbol_string not in self.premarket_high:
continue
if symbol_string in self.traded_today:
continue
if symbol_string == 'BRPA':
continue
current_price = data[symbol].Close
if current_price >= self.premarket_high[symbol_string]:
continue
quantity = (min(self.Portfolio.TotalPortfolioValue, self.estimated_capacity) / 4 / current_price)
self.traded_today.add(symbol_string)
self.MarketOrder(symbol, -quantity)
self.StopMarketOrder(symbol, quantity, round(self.premarket_high[symbol_string], 2))
def ClosePositions(self):
self.premarket_high = {}
self.traded_today = set()
self.Liquidate()
self.Transactions.CancelOpenOrders()
def SelectSymbols(self, dateTime):
min_gap = float(self.GetParameter("min-gap-pct"))
min_pmh_price = float(self.GetParameter("min-premarkethigh-price"))
max_daily_trades = int(self.GetParameter("max-daily-trades"))
symbols = []
date = str(dateTime.date())
if date in self.gapper_data.index:
gappers = self.gapper_data.loc[date]
gappers = self.gapper_data.loc[str(date)]
if isinstance(gappers, pd.Series):
symbol = gappers['Symbol']
if gappers['GAP%'] >= min_gap and gappers['Premarket High'] >= min_pmh_price:# \
# and gappers['Outstanding Shares'] <= 20000000 and gappers['Market Cap'] <= 20000000:
self.premarket_high[symbol] = gappers['Premarket High']
symbols.append(Symbol.Create(symbol, SecurityType.Equity, Market.USA))
elif len(gappers) <= max_daily_trades:
for i in range(len(gappers)):
symbol = gappers.iloc[i]['Symbol']
if gappers.iloc[i]['GAP%'] >= min_gap and gappers.iloc[i]['Premarket High'] >= min_pmh_price:# \
# and gappers.iloc[i]['Outstanding Shares'] <= 20000000 and gappers.iloc[i]['Market Cap'] <= 20000000:
self.premarket_high[symbol] = gappers.iloc[i]['Premarket High']
symbols.append(Symbol.Create(symbol, SecurityType.Equity, Market.USA))
else:
top_list = []
for i in range(len(gappers)):
symbol = gappers.iloc[i]['Symbol']
if gappers.iloc[i]['GAP%'] >= min_gap and gappers.iloc[i]['Premarket High'] >= min_pmh_price:# \
# and gappers.iloc[i]['Outstanding Shares'] <= 20000000 and gappers.iloc[i]['Market Cap'] <= 20000000:
top_list.append(gappers.iloc[i])
top_list = sorted(top_list, key=lambda g: g['GAP%'], reverse=True)[:max_daily_trades]
for gapper in top_list:
symbol = gapper['Symbol']
self.premarket_high[symbol] = gapper['Premarket High']
symbols.append(Symbol.Create(symbol, SecurityType.Equity, Market.USA))
return symbols