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.")