from AlgorithmImports import *
from QuantConnect import *
from QuantConnect.Indicators.CandlestickPatterns import Engulfing
from datetime import timedelta
class Watchlist(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2023, 1, 1) # Start Date
self.SetEndDate(2023, 12, 30) # End Date
self.SetCash(100000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Minute
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash)
self.previous_day_data = {}
self.SetWarmUp(31, Resolution.Minute)
self.previousBar = None
self.filtered_symbols = set()
self.patterns = {}
self.engulfingNOW = set()
self.consolidatorToSymbol = {}
self.ExtendedMarketHours = True
self.manualSymbols = [
'AISP', 'APLT', 'ATCH', 'AXTI', 'BDRX', 'BIVI', 'BMR', 'BRTX', 'CAMP', 'CDIO',
'CHGG', 'CISS', 'CMND', 'CNXA', 'CPOP', 'DBGI', 'DTSS', 'DWAC', 'DXF', 'EJH',
'ENPH', 'ENVB', 'FDMT', 'G47724128', 'GXAI', 'HCTI', 'HOLO', 'IINN', 'INBS',
'JANX', 'JXJT', 'LRHC', 'LUNR', 'MINM', 'MNY', 'NNOX', 'NRSN', 'OCEA', 'OCG',
'PRSO', 'RVSN', 'SYRA', 'TENX', 'TMF', 'TOP', 'TSLA', 'UAVS', 'VANI', 'VCIG',
'VTYX', 'ZJYL'
]
for symbol_str in self.manualSymbols:
symbol = self.AddEquity(symbol_str, Resolution.Minute).Symbol
engulfing = Engulfing() # create new instance of the method
self.patterns[symbol] = engulfing # if pattern occurs, add to class definition
consolidator = TradeBarConsolidator(timedelta(minutes=1))
consolidator.DataConsolidated += self.consolidation_handler
self.consolidatorToSymbol[consolidator] = symbol
self.SubscriptionManager.AddConsolidator(symbol, consolidator)
self.RegisterIndicator(symbol, engulfing, consolidator)
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):
# First, check for engulfing patterns and add qualifying symbols to self.filtered_symbols
for symbol in self.engulfingNOW:
if symbol in data:
history_daily = self.History(symbol, 15, Resolution.Daily)
history_minute = self.History(symbol, 2, Resolution.Minute)
if len(history_minute) >= 2 and len(history_daily) >= 2 and not history_daily.empty and not history_minute.empty:
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 >= 10:
self.filtered_symbols.add(symbol)
# Then, iterate over self.filtered_symbols to execute trading logic
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
backtest not taking trades from universe, any ideas?Â
Mia Alissi
Reviewing 'Luke's' Python code reveals several issues that need to be addressed for the algorithm to function correctly:
Indentation Error in
OnData
Method: TheTradeLogic
method is defined inside theOnData
method, which is incorrect. Python functions should not be nested in this manner unlessTradeLogic
is meant to be a local function, which does not seem to be the intention here. To fix this, ensure thatTradeLogic
is defined at the class level, not inside another method.Missing
self
in Method Calls: TheOnData
method is not correctly defined as an instance method of the class. It lacks theself
parameter that is required for instance methods in Python classes. It should be defined asdef OnData(self, data):
.Incorrect Use of
else
Without anif
Statement: In theTradeLogic
method, there's anelse:
statement that is not directly following anif
orelif
statement. This is likely due to the incorrect indentation of the code block that follows. Theelse
statement should be part of anif-else
construct.Potential Logical Error in Trade Logic: The
TradeLogic
method checks if the portfolio is already invested in a symbol and, if not, buys shares. However, the logic for selling shares (based on stop loss or trailing stop criteria) seems to be executed regardless of whether the initialif not self.Portfolio[symbol].Invested:
condition is true. This could lead to attempts to sell shares that were not bought by this algorithm, especially if theelse
block is meant to contain additional logic that is currently missing due to the indentation issue.Missing Logging in
consolidation_handler
: While theconsolidation_handler
method correctly identifies engulfing patterns and adds symbols toself.engulfingNOW
, there is no logging or further action taken within this method to indicate what happens when an engulfing pattern is found. This might be intentional, but it could also be an oversight if the intention was to log or act on these patterns immediately.Use of
self.ExtendedMarketHours
Without Effect: Theself.ExtendedMarketHours = True
line appears to set a variable that is never used. If the intention was to enable extended market hours for data subscriptions, this should be done through theAddEquity
method by passingextendedMarketHours=True
as an argument.Potential Misuse of Historical Data: In the
OnData
method, historical data is requested every time data is received. This can be very inefficient and lead to performance issues. It's generally better to request historical data once during initialization or sparingly to update internal state, rather than repeatedly in the main data handling loop.Missing
self.Log
orself.Debug
Statements for Debugging: There are noself.Log
orself.Debug
statements in theOnData
method or theTradeLogic
method to provide feedback about the algorithm's decisions or state. Adding logging can greatly aid in debugging and understanding the algorithm's behavior during backtesting.To improve the code, 'Luke' should address these issues by correcting the method definitions, ensuring proper use of control structures, and optimizing the use of historical data requests.
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 his algorithm not taking trades from the universe, there are several potential causes and solutions to investigate:
Universe Selection Logic: Ensure that the universe selection logic is correctly implemented and actually adding symbols to the universe. If the universe selection criteria are too strict or if there's a logical error, it might result in an empty universe or one that doesn't include the intended symbols.
Data Subscription: After symbols are added to the universe, make sure that the algorithm is subscribing to their data. In LEAN, adding a symbol to the universe automatically subscribes to its data, but if there's custom logic handling subscriptions, verify that it's working as intended.
Market Hours: Check if the symbols in the universe are within their trading hours when the algorithm attempts to trade them. If trading outside of market hours without enabling extended market hours, orders won't be filled.
Cash and Portfolio Constraints: Ensure that the algorithm has enough cash to make trades. Also, check for any portfolio constraints that might prevent trading, such as maximum leverage or position size limits.
Order Logic: Review the order execution logic. Ensure that the algorithm is correctly generating orders based on the universe selection. This includes verifying that the conditions for placing orders (e.g., based on indicators or price movements) are being met.
Order Types and Prices: If using limit orders, ensure that the limit prices are reasonable given the current market prices. Orders with prices far from the market won't be filled.
Error Handling: Implement error handling and logging to catch and log any issues that occur during universe selection or order placement. This can provide insights into why trades are not being executed.
Debugging and Logging: Use
self.Debug
orself.Log
statements to output information about the universe selection process, the symbols currently in the universe, and any orders being placed. This can help identify where the process is breaking down.Backtest Settings: Verify that the backtest period covers dates when the selected symbols were actively trading. Also, ensure that the starting cash is sufficient and that the backtest settings match the intended trading conditions.
Algorithm Framework: If using the QuantConnect Algorithm Framework, ensure that the Alpha Model is generating insights for the symbols in the universe and that the Portfolio Construction Model is converting these insights into portfolio targets.
By systematically reviewing these areas, 'Luke' can identify and resolve the issue preventing his algorithm from taking trades from the universe.
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!