Hi there,

I had a recent discussion earlier, and got some help, but wasn't able to complete the whole goal afterwards.

I spliced the call sales into a long term P/B strategy, but am having trouble adding the put sales in too. Goal is to sell cash secured puts until eventually they get filled, then start selling covered calls on those shares. Is there any way to add them in and sell them at 20% below market price?

I will send you some cash via venmo or paypal as gratuity, just leave your username in there.

 

Thanks for any and all help :)

# Fundemental Data and Technical indicators

from AlgorithmImports import *

class VerticalQuantumInterceptor(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2022, 1, 1)
        self.SetEndDate(2022, 6, 16)
        self.SetCash(100000)        
        resolution = Resolution.Daily        
        self.UniverseSettings.Resolution = resolution  
        self.AddUniverse(self.CoarseSelection, self.FineSelection)
        self.symbols = [self.AddEquity(x, resolution).Symbol
            for x in ["X", "F", "JPM", "LKQ", "ALLY"]]
       
        self.tickers = ["X", "F", "JPM", "LKQ", "ALLY"]
        for ticker in self.tickers:
            equity = self.AddEquity(ticker, Resolution.Daily)
            equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
        

        self.stocks = []
        self.macd = {}
        self.call = str()
        
        for sec in self.symbols:    
            self.macd[sec] = self.MACD(sec, 12, 26, 9, Resolution.Daily)

           
    
    def CoarseSelection(self, coarse):
        selected = [x for x in coarse if (x.HasFundamentalData) and (float(x.Price) > 10)]
        static = [x.Symbol for x in selected if (x.Symbol in self.symbols)]
        self.Plot("Universe", "static", len(static))

        return static

    
    def FineSelection(self, fine):        
        pb_ratio_filter = [x.Symbol for x in fine if x.ValuationRatios.PBRatio > 0  and (x.ValuationRatios.PBRatio < 1)]
        self.stocks = pb_ratio_filter
        self.Plot("Universe", "pb_ratio_filter", len(pb_ratio_filter))

        return self.stocks
    
    def UniverseFunc(self, universe):
        put = put.SetFilter(-2, 2, timedelta(0), timedelta(182))
        call = call.SetFilter(-2, 2, timedelta(0), timedelta(182))
        return call, put
   
    def OnData(self, data):
        selected = []


        for sec in self.stocks:
            if self.macd[sec].Current.Value > self.macd[sec].Signal.Current.Value:
                selected.append(sec)

        self.Plot("Universe", "macd_filter", len(selected))  

        for sec in self.Portfolio.Keys:
            if sec not in selected:
                #self.SetHoldings(sec, 0 )
                self.Log("Potential Downturn")
                    
        for sec in selected:
            wt = 1.0/len(selected) if len(selected) > 0 else 0
            if self.Portfolio[sec].Quantity == 0:
                self.SetHoldings(sec, .05 )

        
        for underlying in self.tickers:
            self.underlying = underlying
            if  self.Portfolio[self.underlying].Invested:
              #  self.SetHoldings(self.underlying, 0.05)  # long the underlying stock
            
              if not (self.Securities.ContainsKey(self.call) and self.Portfolio[self.underlying].Invested):
                self.call = self.AddContract(slice) # Add the call option contract (subscribe the contract data)
    
              if self.Securities.ContainsKey(self.call) and not self.Portfolio[self.call].Invested:
                self.SetHoldings(self.call, -.005) # short the call option
                self.call = str()

            


        #############################################
        

    def AddContract(self,slice):
        filtered_contracts = self.InitialFilter(-3, 3, 0, 30)
        if len(filtered_contracts) == 0: return str()
        else:
            call = [x for x in filtered_contracts if x.ID.OptionRight == OptionRight.Call] 
            # sorted the contracts according to their expiration dates and choose the ATM options
            contracts = sorted(sorted(call, key = lambda x: abs(self.Securities[self.underlying].Price- x.ID.StrikePrice)), 
                                            key = lambda x: x.ID.Date, reverse=True)
            if len(contracts) > 0:
                self.AddOptionContract(contracts[0], Resolution.Minute)
                return contracts[0]
            else:
                return str()
###############################################################
        
            
 
    def InitialFilter(self, min_strike_rank, max_strike_rank, min_expiry, max_expiry):
        
        ''' This method is an initial filter of option contracts 
            according to the range of strike price and the expiration date '''
            
        contracts = self.OptionChainProvider.GetOptionContractList(self.underlying, self.Time.date())
        if len(contracts) == 0 : return []
        # fitler the contracts based on the expiry range
        contract_list = [i for i in contracts if min_expiry < (i.ID.Date.date() - self.Time.date()).days < max_expiry]
        # find the strike price of ATM option
        atm_strike = sorted(contract_list,
                            key = lambda x: abs(x.ID.StrikePrice - self.Securities[self.underlying].Price))[0].ID.StrikePrice
        strike_list = sorted(set([i.ID.StrikePrice for i in contract_list]))
        # find the index of ATM strike in the sorted strike list
        atm_strike_rank = strike_list.index(atm_strike)
        try: 
            strikes = strike_list[(atm_strike_rank + min_strike_rank):(atm_strike_rank + max_strike_rank)]
        except:
            strikes = strike_list
        filtered_contracts = [i for i in contract_list if i.ID.StrikePrice in strikes]

        return filtered_contracts 
    #########################################
       
    def OnOrderEvent(self, orderEvent):
        self.Log(str(orderEvent))
    
    def TradeOptions(self,slice):
        for underlying in self.tickers:
            self.underlying = underlying
            
            optionchain = self.OptionChainProvider.GetOptionContractList(self.underlying, self.Time.date())
            put = [x for x in optionchain if x.Right == OptionRight.Put]
            price = optionchain.Underlying.Price
            contracts = [x for x in put if price - x.Strike > 0]
            contracts = sorted(contracts, key = lambda x: x.Expiry, reverse = True)
            if len(contracts) == 0: 
                continue
            symbol = contracts[0].Symbol
            self.Sell(symbol, 1)