Overall Statistics |
Total Trades 59 Average Win 1.61% Average Loss -0.48% Compounding Annual Return 45.801% Drawdown 3.100% Expectancy 1.404 Net Profit 20.785% Sharpe Ratio 2.315 Probabilistic Sharpe Ratio 83.185% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 3.36 Alpha 0.369 Beta -0.119 Annual Standard Deviation 0.147 Annual Variance 0.021 Information Ratio 0.465 Tracking Error 0.196 Treynor Ratio -2.861 Total Fees $59.00 Estimated Strategy Capacity $17000000.00 Lowest Capacity Asset SAM R735QTJ8XC9X |
from AlgorithmImports import * from QuantConnect.DataSource import * class QuiverWallStreetBetsDataAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 1, 1) self.SetEndDate(2021, 7, 1) self.SetCash(100000) self.universe_data_by_symbol = {} self.symbol_data_by_symbol = {} self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction) def CoarseSelectionFunction(self, coarse): sorted_by_dollar_volume = sorted(coarse, key=lambda c: c.DollarVolume, reverse=True) selected = sorted_by_dollar_volume[:500] for c in selected: if c.Symbol not in self.universe_data_by_symbol: self.universe_data_by_symbol[c.Symbol] = UniverseData(self, c.Symbol) else: self.universe_data_by_symbol[c.Symbol].Update(self.Time, c.AdjustedPrice) selected = [c for c in selected if self.universe_data_by_symbol[c.Symbol].IsReady] sorted_by_std = sorted(selected, key=lambda c: self.universe_data_by_symbol[c.Symbol].std.Current.Value, reverse=True) return [ x.Symbol for x in sorted_by_std[:3] ] def OnData(self, data): for symbol, symbol_data in self.symbol_data_by_symbol.items(): # Gather WSB mentions data if data.ContainsKey(symbol_data.wsb_symbol): wsb_mentions = data[symbol_data.wsb_symbol].Mentions symbol_data.Update(data.Time, wsb_mentions) # Ensure we have data to place orders if not (data.ContainsKey(symbol) and data[symbol] is not None): continue # Place orders if not data[symbol].IsFillForward and symbol_data.IsReady: target_holding = symbol_data.get_target_holding() / len(self.symbol_data_by_symbol) self.SetHoldings(symbol, target_holding) def OnSecuritiesChanged(self, changes): for security in changes.AddedSecurities: symbol = security.Symbol self.symbol_data_by_symbol[symbol] = SymbolData(self, symbol) for security in changes.RemovedSecurities: symbol = security.Symbol self.Liquidate(symbol) symbol_data = self.symbol_data_by_symbol.pop(symbol, None) if symbol_data: symbol_data.dispose() class UniverseData: def __init__(self, algorithm, symbol, std_period=30): self.std = StandardDeviation(std_period) # Warm up std indicator history = algorithm.History(symbol, std_period, Resolution.Daily) if history.empty or 'close' not in history.columns: return for time, row in history.loc[symbol].iterrows(): self.std.Update(time, row.close) def Update(self, date, price): self.std.Update(date, price) @property def IsReady(self): return self.std.IsReady class SymbolData: def __init__(self, algorithm, symbol): self.algorithm = algorithm self.wsb_symbol = algorithm.AddData(QuiverWallStreetBets, symbol).Symbol self.max = Maximum(7) self.current = Maximum(1) # Warm up max indicator history = algorithm.History(QuiverWallStreetBets, self.wsb_symbol, 14, Resolution.Daily) if history.empty or 'mentions' not in history.columns: return for time, row in history.loc[self.wsb_symbol].iterrows(): self.max.Update(time, row.mentions) self.current.Update(time, row.mentions) def Update(self, time, mentions): self.max.Update(time, mentions) self.current.Update(time, mentions) @property def IsReady(self): return self.max.IsReady def get_target_holding(self): return int(self.current >= self.max) def dispose(self): self.algorithm.RemoveSecurity(self.wsb_symbol)