| Overall Statistics |
|
Total Trades 119 Average Win 4.94% Average Loss -2.71% Compounding Annual Return -39.048% Drawdown 53.400% Expectancy -0.342 Net Profit -47.636% Sharpe Ratio -0.737 Probabilistic Sharpe Ratio 0.809% Loss Rate 77% Win Rate 23% Profit-Loss Ratio 1.82 Alpha 0 Beta 0 Annual Standard Deviation 0.338 Annual Variance 0.114 Information Ratio -0.737 Tracking Error 0.338 Treynor Ratio 0 Total Fees $365.97 Estimated Strategy Capacity $10000000.00 Lowest Capacity Asset AAPL R735QTJ8XC9X |
class RetrospectiveBlueWhale(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 1, 1) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
# self.AddEquity("SPY", Resolution.Minute)
self.AddUniverse(self.SelectCoarse, self.SelectFine)
self.UniverseSettings.Resolution = Resolution.Minute
self.leverageNumber = 3
self.UniverseSettings.Leverage = self.leverageNumber
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.SetRiskManagement(TrailingStopRiskManagementModel(0.03))
self.mompLookback = self.GetParameter("momp-lookback")
self.mompEntry = self.GetParameter("momp-entry")
self.mompLookback = int(self.mompLookback)
self.mompEntry = int(self.mompEntry)
self.symbolDataBySymbol = {}
self.coarseNumber = 100
self.fineNumber = 10
self.lastMonth = -1
self.spy = self.AddEquity("SPY", Resolution.Minute).Symbol
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen(self.spy, 30),
self.SetTrades)
def OnData(self, data):
if self.IsWarmingUp:
return
def SetTrades(self):
for symbol, symbolData in self.symbolDataBySymbol.items():
rsi = symbolData.Rsi.Current.Value
momp = symbolData.Momp.Current.Value
ema = symbolData.Ema.Current.Value
#self.Debug(str(symbol) + " " + str(momp))
if momp < (-self.mompEntry) and not self.Portfolio[symbol].IsShort and ema < 9:
if (-self.mompEntry) >= momp >= (-self.mompEntry)-10:
self.SetHoldings([PortfolioTarget(symbol, -(1/self.fineNumber)*(self.leverageNumber-1))])
elif (-self.mompEntry)-10 > momp >= (-self.mompEntry)-20:
self.SetHoldings([PortfolioTarget(symbol, -(1/self.fineNumber)*self.leverageNumber)])
elif momp < (-self.mompEntry)-20:
''' ARMAGEDON '''
self.Liquidate()
self.SetHoldings([PortfolioTarget(symbol, -1.0*self.leverageNumber)])
break
elif momp > self.mompEntry and not self.Portfolio[symbol].IsLong and ema > 9:
if self.mompEntry <= momp <= self.mompEntry+10:
self.SetHoldings([PortfolioTarget(symbol, (1/self.fineNumber)*(self.leverageNumber-1))])
elif self.mompEntry+10 < momp <= self.mompEntry+20:
self.SetHoldings([PortfolioTarget(symbol, (1/self.fineNumber)*self.leverageNumber)])
elif momp > self.mompEntry+20:
''' ARMAGEDON '''
self.Liquidate()
self.SetHoldings([PortfolioTarget(symbol, 1.0*self.leverageNumber)])
break
def OnSecuritiesChanged(self, changes):
added = [x for x in changes.AddedSecurities]
removed = [x for x in changes.RemovedSecurities]
for x in added:
symbol = x.Symbol
if symbol == self.spy:
continue
rsi = self.RSI(symbol, 65, MovingAverageType.Simple, Resolution.Minute)
sma = self.SMA(symbol, 65, Resolution.Minute, Field.Volume)
obv = self.OBV(symbol, Resolution.Minute)
momp = self.MOMP(symbol, self.mompLookback, Resolution.Minute, Field.Volume)
ema = self.EMA(symbol, 14, Resolution.Daily, Field.Close)
#priceRoc = self.ROC(symbol, 14, Resolution.Daily, Field.Close)
history = self.History(symbol, 300, Resolution.Minute)
historyDaily = self.History(symbol, 14, Resolution.Daily)
for tuple in history.loc[symbol].itertuples():
rsi.Update(tuple.Index, tuple.close)
sma.Update(tuple.Index, tuple.volume)
tradebar = TradeBar(tuple.Index, symbol, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume)
obv.Update(tradebar)
momp.Update(tuple.Index, tuple.volume)
for tuple in historyDaily.loc[symbol].itertuples():
ema.Update(tuple.Index, tuple.close)
symbolData = SymbolData(symbol, rsi, sma, momp, ema)
self.symbolDataBySymbol[symbol] = symbolData
def SelectCoarse(self, coarse):
if self.lastMonth == self.Time.month:
return Universe.Unchanged
self.lastMonth = self.Time.month
filteredCoarse = sorted([x for x in coarse if x.Price > 50 and x.DollarVolume > 1000], key = lambda x: x.DollarVolume, reverse = True)
return [x.Symbol for x in filteredCoarse][:self.coarseNumber]
def SelectFine(self, fine):
filteredFine = sorted([x for x in fine], key = lambda x: x.MarketCap, reverse = True)
return [x.Symbol for x in filteredFine][:self.fineNumber]
class SymbolData:
def __init__(self, symbol, rsi, sma, momp, ema):
self.Symbol = symbol
self.Rsi = rsi
self.Sma = sma
self.Momp = momp
self.Ema = ema