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 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
class WeeklyScreener(QCAlgorithm): MAX_INVESTED_SYMBOLS = 10 TAKE_PROFIT_PERCENTAGE = 0.05 STOP_LOSS_PERCENTAGE = 0.02 Symbols_To_Protect = dict() averages = dict() def Initialize(self): self.SetStartDate(2019, 2, 21) # Set Start Date self.SetCash(100000) # Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) # At each end of week, liquidate self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(15, 45), Action(self.Liquidate)) def OnData(self, data): all_symbols = [ x.Value for x in self.Securities.Keys ] invested_symbols = [ x.Symbol.Value for x in self.Portfolio.Values if x.Invested ] self.Debug("ALL SYMBOLS: " + str(all_symbols)) self.Debug("INVESTED SYMBOLS: " + str(invested_symbols)) # If portfolio already full, return if len(invested_symbols) == self.MAX_INVESTED_SYMBOLS: return # Else get diff between all and invested new_symbols = list(set(all_symbols)-set(invested_symbols)) # If no new symbols, return if len(new_symbols) == 0: return # Add new positions for symbol in new_symbols: # if data.ContainsKey(symbol) is False: continue # if data[symbol] is None: continue # # TODO: If day > wednesday, return # if data[symbol].Time > 3: return # BUY self.SetHoldings(symbol, 1/self.MAX_INVESTED_SYMBOLS) # Handle risk management in OnOrderEvent self.Symbols_To_Protect[symbol] = True # Creates stop losses and take profits for opened long orders def OnOrderEvent(self, orderEvent): order = self.Transactions.GetOrderById(orderEvent.OrderId) # If it's an order to protect and that it's filled if self.Symbols_To_Protect.get(order.Symbol.Value, None) is not None and orderEvent.Status == OrderStatus.Filled: # Remove order from dict del self.Symbols_To_Protect[order.Symbol.Value] # SET TAKE PROFIT take_profit_price = order.Price * (1 + self.TAKE_PROFIT_PERCENTAGE) self.StopMarketOrder(order.Symbol, -order.QuantityFilled, take_profit_price) # SET STOP LOSS stop_loss_price = order.Price * (1 - self.STOP_LOSS_PERCENTAGE) self.StopMarketOrder(order.Symbol, -order.QuantityFilled, stop_loss_price) # this event fires whenever we have changes to our universe def OnSecuritiesChanged(self, changes): self.Debug("Universe change event Added: " + str([s.Symbol.Value for s in changes.AddedSecurities])) 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] = SymbolData(cf.Symbol, self) # Updates the SymbolData object with price and volume avg = self.averages[cf.Symbol] avg.update(cf.EndTime, cf.Price, cf.Volume) # Filter the values of the dict: we only want up-trending securities values = list(filter(lambda x: x.is_uptrend, self.averages.values())) selected_symbols = [ x.symbol for x in values[:self.MAX_INVESTED_SYMBOLS] ] return selected_symbols def FineSelectionFunction(self, fine): selected_symbols = [f.Symbol for f in fine] # self.Debug(str([s.Value for s in selected_symbols])) return selected_symbols class SymbolData: def __init__(self, symbol, algo): self.algo = algo self.symbol = symbol self.priceEMA = ExponentialMovingAverage(10) self.volEMA = ExponentialMovingAverage(10) self.rsi = RelativeStrengthIndex(14) self.macd = MovingAverageConvergenceDivergence(12,26,9) self.priceWin = RollingWindow[float](10) self.is_uptrend = False def update(self, time, price, volume): self.priceWin.Add(price) self.priceEMA.Update(time, price) self.volEMA.Update(time, volume) self.rsi.Update(time, price) self.macd.Update(time, price) if self.rsi.IsReady and self.macd.IsReady and self.priceWin.IsReady: rsi = self.rsi.Current.Value signal = self.macd.Signal.Current.Value macd = self.macd.Current.Value self.is_uptrend = rsi < 60 and rsi > 40 and (signal > macd) and price > self.priceWin[1] # if self.is_uptrend: # self.algo.Debug("---- IS UPTREND ---- " + self.symbol.Value + ": RSI=" + str(rsi) + " MACD=" + str(macd) + " SIGNAL=" + str(signal)) # if self.priceEMA.IsReady and self.volEMA.IsReady and self.priceWin.IsReady: # EMAprice = self.priceEMA.Current.Value # EMAvol = self.volEMA.Current.Value # # current price > 10-days moving average price # # current volume > 10-days moving average volume # # current price > yesterday's close # # current price > 10-days maximum price # self.is_uptrend = price > EMAprice and volume > EMAvol and price > self.priceWin[1] and price > max(self.priceWin)