from AlgorithmImports import *
from QuantConnect import *
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Indicators.CandlestickPatterns import Engulfing
from datetime import timedelta
class Watchlist(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2023, 5, 17) # Start Date
self.SetEndDate(2023, 5, 27) # End Date
self.SetCash(100000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Minute
self.AddUniverse(self.CoarseFilter)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash)
self.previous_day_data = {}
self.SetWarmUp(2, Resolution.Daily)
self.previousBar = None
self.filtered_symbols = set()
self.patterns = {}
self.engulfingNOW = set()
self.consolidatorToSymbol = {}
def CoarseFilter(self, coarse):
CoarseFilterResult = sorted(
[x for x in coarse if x.Price < 30 and x.MarketCap < 1.5e9],
key=lambda x: x.DollarVolume,
reverse=True)[:50]
return [x.Symbol for x in CoarseFilterResult]
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
symbol = security.Symbol
if symbol not in self.patterns:
engulfing = Engulfing() # create new instance of the method
self.patterns[symbol] = engulfing # if pattern occurs, add to class definition
consolidator = QuoteBarConsolidator(1)
consolidator.DataConsolidated += self.consolidation_handler
self.consolidatorToSymbol[consolidator] = symbol
self.SubscriptionManager.AddConsolidator(symbol, consolidator)
self.RegisterIndicator(symbol, engulfing, consolidator)
# stocks are added if there was an engulfing pattern present at all
def consolidation_handler(self, sender, consolidated):
symbol = self.consolidatorToSymbol.get(sender, None)
pattern_value = self.patterns[symbol].Current.Value
if self.patterns[symbol].IsReady:
if self.patterns[symbol].Current.Value != 0:
self.engulfingNOW.add(symbol)
self.Log(f"{symbol} Engulfing value: {pattern_value}")
def OnData(self, data):
for symbol in self.engulfingNOW:
if symbol in data and data[symbol] is not None:
history_daily = self.History(symbol, 15, Resolution.Daily)
history_minute = self.History(symbol, 2, Resolution.Minute)
if not history_daily.empty and 'volume' in history_daily.columns and \
not history_minute.empty and 'close' in history_minute.columns:
volume_ratio = history_daily['volume'].iloc[-1] / history_daily['volume'].iloc[-2]
percent_change = (history_minute['close'].iloc[-1] - history_minute['close'].iloc[-2]) / history_minute['close'].iloc[-2] * 100
# Execute trade logic based on volume and price change criteria
if volume_ratio >= 5 and percent_change >= 20:
self.filtered_symbols.add(symbol)
for symbol in self.filtered_symbols:
self.TradeLogic(symbol)
def TradeLogic(self, symbol):
if not self.Portfolio[symbol].Invested:
self.SetHoldings(symbol, 0.1)
self.Log(f"Buying {symbol.Value} based on conditions.")
else:
self.Log(f"Already invested in {symbol.Value}, skipping.")
holding = self.Portfolio[symbol]
if holding.Invested:
current_price = self.Securities[symbol].Price
stop_loss_price = holding.AveragePrice * 0.95
trailing_stop_price = holding.AveragePrice * 0.9
if current_price < stop_loss_price or current_price < trailing_stop_price:
self.Liquidate(symbol)
self.Debug(f"Liquidated {symbol.Value} due to stop loss or trailing stop criteria.")
Luke
Backtests show no trades taken, cant seem to get the engulfing pattern to work with my dynamic universe.Â
Mia Alissi
Reviewing 'Luke's' Python code reveals a few potential issues that could affect the algorithm's performance or lead to runtime errors:
Missing Import Statement for Engulfing Pattern: The code uses the
Engulfingclass fromQuantConnect.Indicators.CandlestickPatternsbut does not include an import statement for it. This will result in aNameErrorwhen trying to instantiateEngulfing. To fix this, you should add the following import statement at the beginning of your code:Incorrect Use of QuoteBarConsolidator for Engulfing Pattern: The
Engulfingpattern indicator is designed to work withTradeBarobjects, but the code is using aQuoteBarConsolidator. This mismatch can lead to unexpected behavior sinceQuoteBarandTradeBarhave different properties. You should useTradeBarConsolidatorinstead:Potential Issue with Trade Logic Execution: The
TradeLogicmethod checks if the symbol is invested and then attempts to set holdings. However, there's a logic block that seems to be intended for managing stop losses, but it's placed outside any conditional or loop structure, which could lead to syntax errors or unintended behavior. The indentation seems off, and the else statement is empty and not followed by any code. This part of the code needs to be structured properly to ensure the intended logic is executed correctly. A corrected structure might look like this:Ensure the logic for managing stop losses and trailing stops is correctly implemented and only executed when necessary.
Potential Issue with Historical Data Requests: The
OnDatamethod requests historical data every time it's called, which can be very inefficient and may lead to rate limits being hit or excessive delays. It's generally better to request historical data less frequently or to use other techniques to reduce the number of requests, such as caching the results or using scheduled events to update data at specific intervals.Logging and Debugging Information: While not a bug, it's worth noting that extensive logging, such as logging every time an engulfing pattern is found, can slow down backtesting. Use logging judiciously to ensure that it provides value without significantly impacting performance.
These are the primary issues identified in the provided code. Addressing these should help improve the algorithm's correctness and efficiency.
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Mia Alissi
If 'Luke' is experiencing issues with no trades being taken in backtests, especially related to the engulfing pattern not working with a dynamic universe, there are several potential areas to investigate and adjust:
Ensure Engulfing Pattern Indicator is Correctly Registered and Updated:
Engulfingpattern indicator is correctly instantiated and registered for each symbol added to the universe. This seems to be correctly handled in theOnSecuritiesChangedmethod.Engulfingpattern indicator is updated with new data as it arrives. This is typically done through consolidators, which you've set up, but ensure that the data type (QuoteBar vs. TradeBar) matches the expected input for the indicator.Check the Consolidator Period:
QuoteBarConsolidator(1)creates a consolidator with a period of 1 minute. Confirm that this period aligns with the expected timeframe for the engulfing pattern to form. If the engulfing pattern is expected to form over a different period, adjust the consolidator accordingly.Verify the Engulfing Pattern Logic:
consolidation_handlerchecks if theEngulfingpattern'sCurrent.Valueis not 0, which indicates a pattern has been found. Ensure this logic correctly identifies the patterns you're interested in. Remember, an engulfing pattern value of 1 indicates a bullish engulfing, and -1 indicates a bearish engulfing.Review the Trade Execution Conditions:
OnDatamethod, trades are only executed if certain conditions related to volume ratio and percent change are met. Double-check these conditions to ensure they're not too restrictive, preventing trades from being executed.Ensure Symbols are Tradable:
security.IsTradableto check if a security is tradable before attempting to trade it.Debugging and Logging:
TradeLogicmethod. This can help identify where the algorithm might be failing to meet trade criteria or if there are issues with the data.self.engulfingNOWandself.filtered_symbolsto ensure that symbols are being correctly identified and added for trading.Historical Data Requests:
OnDatamethod, as frequent requests can slow down your algorithm. Ensure that these requests are necessary for your trade logic and consider caching results if possible.Warm-Up Period:
Resolution.Daily. Ensure this is sufficient for your indicators to be ready and produce meaningful signals from the start of the algorithm.If after reviewing and adjusting these areas the issue persists, it may be helpful to isolate parts of the algorithm (e.g., testing the engulfing pattern logic independently) to more easily identify where the problem lies.
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Luke
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!