Overall Statistics |
Total Trades 1412 Average Win 2.34% Average Loss -2.67% Compounding Annual Return -40.017% Drawdown 93.600% Expectancy -0.007 Net Profit -63.359% Sharpe Ratio 0.278 Probabilistic Sharpe Ratio 9.747% Loss Rate 47% Win Rate 53% Profit-Loss Ratio 0.88 Alpha 0.114 Beta 1.201 Annual Standard Deviation 1.155 Annual Variance 1.335 Information Ratio 0.132 Tracking Error 1.128 Treynor Ratio 0.267 Total Fees $112228.26 Estimated Strategy Capacity $2000000.00 Lowest Capacity Asset ONON XRV6S79HAOO5 |
class PensiveRedOrangeCaribou(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) # Set Start Date self.SetCash(1000000) # Set Strategy Cash self.AddUniverse(self.CoarseSelectionFilter) self.UniverseSettings.Resolution = Resolution.Minute self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw self.symbol_data_by_symbol={} def CoarseSelectionFilter(self, coarse): sortedByDollarVolume = sorted(coarse, key=lambda c: c.DollarVolume, reverse=True) return [ x.Symbol for x in sortedByDollarVolume if x.Price > 10 and x.HasFundamentalData][:500] def OnSecuritiesChanged(self, changes): for security in changes.RemovedSecurities: symbol = security.Symbol if security.Invested: self.Liquidate(symbol) symbol_data = self.symbol_data_by_symbol.pop(symbol, None) if symbol_data: symbol_data.dispose() for security in changes.AddedSecurities: symbol = security.Symbol self.symbol_data_by_symbol[symbol] = SymbolData(self, symbol) def OnData(self, data): bestGain = None bestGainValue = 0 numPositions = 0 for symbol, symbol_data in self.symbol_data_by_symbol.items(): if not (data.ContainsKey(symbol) and data[symbol] is not None and symbol_data.openingBar is not None and symbol_data.fhmin is not None): return if (self.Time.hour==12 and self.Time.minute ==0): if (self.Portfolio[symbol].Invested): numPositions = numPositions +1 if (bestGainValue == 0): bestGainValue = symbol_data.percentChange bestGain = symbol else: if (bestGainValue < symbol_data.percentChange): bestGainValue = symbol_data.percentChange bestGain = symbol for symbol, symbol_data in self.symbol_data_by_symbol.items(): if not (data.ContainsKey(symbol) and data[symbol] is not None and symbol_data.openingBar is not None and symbol_data.fhmin is not None): return # if current price greater than open at 1% - open long position if not self.Portfolio[symbol].Invested: if (self.Time.hour==12 and self.Time.minute ==0): if (data[symbol].Close > symbol_data.openingBar.Open*(1+3/100) and not symbol_data.wastrade and symbol == bestGain): self.SetHoldings(symbol, 1/(numPositions+1)) symbol_data.wastrade = True else: # modify if (self.Time.hour==12 and self.Time.minute ==0): self.SetHoldings(symbol, 1/(numPositions+1)) # close if current price less than 1HMin. if ((self.Time.hour==10 and self.Time.minute >=30) or (self.Time.hour>10)): if (data[symbol].Low < symbol_data.fhmin): self.Liquidate(symbol) class SymbolData: openingBar = None def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.fhmin = None self.wastrade = False self.percentChange = None # Setup minute consolidator self.five_minute_consolidator = TradeBarConsolidator(timedelta(minutes=5)) self.five_minute_consolidator.DataConsolidated += self.five_minute_consolidation_handler algorithm.SubscriptionManager.AddConsolidator(symbol, self.five_minute_consolidator) def five_minute_consolidation_handler(self, sender, bar): if bar.Time.hour == 9 and bar.Time.minute == 30: self.openingBar = bar self.fhmin = bar.Low self.wastrade = False else: if (bar.Time.hour == 9 and bar.Time.minute >30) or (bar.Time.hour==10 and bar.Time.minute <=30): if (self.fhmin!= None and bar.Low < self.fhmin): self.fhmin = bar.Low if (bar.Time.hour == 11 and bar.Time.minute ==30): if (self.openingBar!=None): self.percentChange = bar.Close/self.openingBar.Open-1 def dispose(self): self.algorithm.SubscriptionManager.RemoveConsolidator(self.symbol, self.five_minute_consolidator)