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
0.956
Tracking Error
0.098
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
from AlgorithmImports import *
from datetime import timedelta
#from QuantConnect.Data.Custom.CBOE import *
# endregion

class HyperActiveTanCow(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2023, 2, 22)  # Set Start Date
        self.SetEndDate(2023, 2, 27)
        self.SetCash(100000)  # Set Strategy Cash
        self.equity = self.AddEquity("SPY", Resolution.Minute) # Add the underlying stock: Spy
        self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
        self.symbol = self.equity.Symbol
        #self.SetBenchmark(self.equity)

        #option = self.AddOption("SPY", Resolution.Minute) # Add the option corresponding to underlying stock
        #self.symbol = option.Symbol     #can now symbol back and forth

        self.contract = str()
        self.contractsAdded = set()

        #create array to track n amount of 2min ewo bars
        self.ewoTracker = []

        #this is the array iterator to count each entry space/element
        self.i = -1
        self.needToPop = False
        self.haveHoldings = False
        self.buyBar = 0
        self.buyCallFlag = False

        #Have the algo only look at contracts that are 1 row above or below the strike price and 0 or 1dte
        #option.SetFilter(-1, 1, timedelta(0), timedelta(0))

        #Create two min consolidator, attach event handler for every 2min, then add consolidator to the engines subscription manager for updates
        twoMinConsolidator = TradeBarConsolidator(timedelta(minutes=2))
        twoMinConsolidator.DataConsolidated += self.TwoMinBarHandler
        self.SubscriptionManager.AddConsolidator("SPY", twoMinConsolidator)

        #Create EMA indicators
        self.ema5 = ExponentialMovingAverage(5, 0.33)
        self.ema35 = ExponentialMovingAverage(35, 0.055)

        #Have indicator work w 2min bars
        self.RegisterIndicator("SPY", self.ema5, twoMinConsolidator)
        self.RegisterIndicator("SPY", self.ema35, twoMinConsolidator)

        self.SetWarmUp(timedelta(35))

        #Create a scheduled event that sells all holdings before close of day
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 1), self.ClosePositions)

    def OnData(self, data: Slice):
        #Ensure indicators are warmed up
        if not self.ema5.IsReady and self.ema35.IsReady:
            return
         
        self.Plot("ExponentialMovingAverage", "ema5", self.ema5.Current.Value)
        self.Plot("ExponentialMovingAverage", "ema35", self.ema35.Current.Value)

        #option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type == SecurityType.Option]

        #If two min bar handler flips buy call flag from false to true, then create options chain and call BuyCall()
        #if self.buyCallFlag:
            #for j in data.OptionChains:      #This was from video #12
             #   self.Debug("Recognized")
             #   chains = j.Value
             #   self.BuyCall(chains)
            #self.buyCallFlag = False

        if self.buyCallFlag:
            self.BuyCall(data)

        #if option_invested:
            #monitor premium price to decide when to sell
            #pass

    def TwoMinBarHandler(self, sender, consolidated):
        
        #ema5 - ema35 to get 2minEWO value
        self.twoMinEWO = float(self.ema5.Current.Value - self.ema35.Current.Value)

        #Add current ewo bar to array to track n most recent (still need to implement pop)
        self.ewoTracker.append(self.twoMinEWO)
        self.i += 1

    #Use this block at the end of function call to pop 5th most recent bar to keep storage down
        #if self.i >= 4:
        #    self.needToPop = True 

        #if self.needToPop:
        #    self.ewoTracker.pop(self.i - 4)

    #Use this to constantly print the EWO array in 5 bar intervals
        #if ((self.i+1) % 5 == 0):
            #self.Debug(str(self.ewoTracker[self.i-4]) + ", " + str(self.ewoTracker[self.i-3]) + ", " + str(self.ewoTracker[self.i-2]) + ", " + str(self.ewoTracker[self.i-1]) + ", " + str(self.ewoTracker[self.i]))
            #self.Debug(str(self.Time))
        

    #Deciding Entry (ONLY 2min red to green flips with CALLS)

        #took out the strategy for security purposes
        if (self.i >= 3):
            #took out strategy, feel free to implement some sort of buy condition for testing
              #self.MarketOrder("SPY", 100)
              #Call BuyCall function
              self.buyCallFlag = True
              self.Debug("Buy")
              self.Debug(str(self.Time))
              self.buyBar = self.i
        
    
    #Quick test logic to sell after 10mins of holding the position

        #if it is 5 bars after buying, sell
        #if (self.i == (self.buyBar + 5)):
            #self.MarketOrder("SPY", -100)
            #self.Debug("Sell")
            #self.Debug(str(self.Time))
            #self.buyBar = 0

#Buy Call Function

    #def BuyCall(self, chains):
        #First try, didnt work, got it from TradeOptionsWithMe Video #12
        #self.Debug("Buy Call1")
        #expiry = sorted(chains, key = lambda x: x.Expiry, reverse=True)[0].Expiry
        #calls = [i for i in chains if i.Expiry == expiry and i.Right == OptionRight.Call]
        #call_contracts = sorted(calls, key = lambda x: abs(x.Strike - x.UnderlyingLastPrice))
        #if len(call_contracts) == 0:
        #    return
        #self.call = call_contracts[0]

        #self.Debug(self.call.Expiry)
        #self.Debug(self.call.Strike)

        #quantity = self.Portfolio.TotalPortfolioValue / self.call.AskPrice
        #quantity = int(0.05 * quantity / 100)
        #self.Buy(self.call.Symbol, quantity)
        #self.Debug("Buy Call2")

    #This is from Coding an Options Trading Algoirthm in Python - Code Along
    def BuyCall(self, data):
        if self.contract == str():
            self.contract = self.OptionsFilter(data)
            return
        elif not self.Portfolio.Invested and data.ContainsKey(self.contract):
            quantity = self.Portfolio.TotalPortfolioValue / self.call.AskPrice
            #quantity = 100000 / self.call.AskPrice
            quantity = int(0.05 * quantity / 100)
            self.Buy(self.contract, quantity)

    def OptionsFilter(self, data):
        contracts = self.OptionChainProvider.GetOptionContractList(self.symbol, data.Time)
        self.underlyingPrice = self.Securities[self.symbol].Price
        if contracts is None:
            return
        itm_calls = [i for i in contracts if i.ID.OptionRight == OptionRight.Call and 
                                            i.ID.StrikePrice - self.underlyingPrice > 0 and i.ID.StrikePrice - self.underlyingPrice < 1 and
                                            (i.ID.Date - data.Time).days == 0]
        self.Debug(str(itm_calls))

        if len(itm_calls) > 0:
            self.Debug("Buy Call")
            self.Debug(str(itm_calls))
            return itm_calls[0]

#Liquidate any holdings before close of day

    def ClosePositions(self):
        self.i = -1
        if self.Portfolio.Invested:
            self.Liquidate()

    


#Next step is learning to market buy ATM 0dte options, but not 0dte if after 1pm

#Then tracking the premium and figuring out when to sell based off of percentages
#Then market sell