Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 1.96 Tracking Error 0.354 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
class MuscularFluorescentPinkSardine(QCAlgorithm): def Initialize(self): self.UniverseSettings.Resolution = Resolution.Minute self.SetStartDate(2022, 4, 28) self.SetEndDate(2022, 5, 8) self.SetWarmUp(timedelta(days = 301)) self.SetCash(100000) self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetBenchmark("SPY") self.stopLossPercentLong = .997 self.takeProfitPercentLong = 1.004 self.timeCheck = False self.coarse_count = 10 self.averages = { } # this add universe method accepts two parameters: # - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol> self.AddUniverse(self.CoarseSelectionFunction) self.symbolData = {} for ticker in self.ActiveSecurities: symbol = ticker.Symbol self.symbolData[symbol] = SymbolData(self, symbol) everyday = self.DateRules.EveryDay() self.Schedule.On(everyday, self.TimeRules.At(15, 55), self.Liquidate) self.Schedule.On(everyday, self.TimeRules.At(15, 30) , self.timeCheckNight) self.Schedule.On(everyday, self.TimeRules.At(9, 45), self.timeCheckMorning) def CoarseSelectionFunction(self, coarse): # We are going to use a dictionary to refer the object that will keep the moving averages for cf in coarse: if cf.Symbol not in self.averages: self.averages[cf.Symbol] = DataSymbol(cf.Symbol) # Updates the SymbolData object with current EOD price avg = self.averages[cf.Symbol] avg.update(cf.EndTime, cf.AdjustedPrice) # Filter the values of the dict: we only want up-trending securities values = list(filter(lambda x: x.is_uptrend, self.averages.values())) # Sorts the values of the dict: we want those with greater difference between the moving averages values.sort(key=lambda x: x.scale, reverse=True) for x in values[:self.coarse_count]: self.Log('symbol: ' + str(x.symbol.Value) + ' scale: ' + str(x.scale)) # we need to return only the symbol objects return [ x.symbol for x in values[:self.coarse_count] ] def OnSecuritiesChanged(self, changes): for ticker in changes.AddedSecurities: symbol = ticker.Symbol if symbol not in self.symbolData: self.symbolData[symbol] = SymbolData(self, symbol) def timeCheckMorning(self): self.timeCheck = True def timeCheckNight(self): self.timeCheck = False def OnEndOfDay(self): for data in self.symbolData.values(): data.longTrade = True data.shortTrade = True def OnData(self, slice): if not all([data.IsReady for data in self.symbolData.values()]): return for symbol, data in self.symbolData.items(): price = self.Securities[symbol].Price data.tradeBuffer += 1 if price > (data.sma3high.Current.Value): if data.sma5 > data.sma60: if data.longTrade: if data.tradeBuffer > 60: if self.timeCheck: marketorderticket = self.SetHoldings(symbol, 0.05) data.stopmarketorderticket = self.StopMarketOrder(symbol, -self.Portfolio[symbol].Quantity, price * self.stopLossPercentLong) data.limitorderticket = self.LimitOrder(symbol, -self.Portfolio[symbol].Quantity, price * self.takeProfitPercentLong) data.longTrade = False def OnSecuritiesChanged(self, changes): for ticker in changes.AddedSecurities: symbol = ticker.Symbol if symbol not in self.symbolData: self.symbolData[symbol] = SymbolData(self, symbol) def OnOrderEvent(self, orderEvent): data = self.symbolData.get(orderEvent.Symbol, None) if not data or orderEvent.Status != OrderStatus.Filled: return for symbol, data in self.symbolData.items(): price = self.Securities[symbol].Price if orderEvent.Status != OrderStatus.Filled: return if data.stopmarketorderticket != None and data.stopmarketorderticket.OrderId == orderEvent.OrderId: data.limitorderticket.Cancel() data.longTrade = True data.tradeBuffer = 0 if data.limitorderticket != None and data.limitorderticket.OrderId == orderEvent.OrderId: data.stopmarketorderticket.Cancel() data.longTrade = True data.tradeBuffer = 0 class SymbolData: def __init__(self, algorithm, symbol): #algorithm.Securities[symbol].SetLeverage(2.0) oneDayConsolidator = TradeBarConsolidator(timedelta(minutes = 390)) self.subscribe = algorithm.SubscriptionManager.AddConsolidator(symbol, oneDayConsolidator) self.sma3high = SimpleMovingAverage(3) self.sma3low = SimpleMovingAverage(3) self.Registersma3high = algorithm.RegisterIndicator(symbol, self.sma3high, oneDayConsolidator, Field.High) self.Registersma3low = algorithm.RegisterIndicator(symbol, self.sma3low, oneDayConsolidator, Field.Low) self.sma200day = SimpleMovingAverage(200) self.Registersma30day = algorithm.RegisterIndicator(symbol, self.sma200day, oneDayConsolidator) self.sma5 = algorithm.SMA(symbol, 5, Resolution.Minute, Field.Volume) self.sma60 = algorithm.SMA(symbol, 60, Resolution.Minute, Field.Volume) self.window10min = RollingWindow[TradeBar](10) self.tradeBuffer = 60 self.longTrade = True self.stopmarketorderticket = None self.limitorderticket = None self.stopmarketorderticketshort = None self.limitorderticketshort = None @property def IsReady(self): return all ([window10min.IsReady for window10 in self.window10min.values()]) class DataSymbol(object): def __init__(self, unisymbol): self.symbol = unisymbol self.tolerance = 1.01 self.fast = ExponentialMovingAverage(3900) self.slow = ExponentialMovingAverage(117000) self.is_uptrend = False self.scale = 0 def update(self, time, value): if self.fast.Update(time, value) and self.slow.Update(time, value): fast = self.fast.Current.Value slow = self.slow.Current.Value self.is_uptrend = fast > slow * self.tolerance if self.is_uptrend: self.scale = (fast - slow) / ((fast + slow) / 2.0)