Hi there,
I had a discussion similar to this a week earlier, sorry for the repeat.
I am trying to sell cash secured puts to acquire positions at 20% below market price in order to get a fair price, then sell covered calls once I have been exercised on the puts. Ive got the call selling almost there but I cant get it to start of selling puts, and it throws a runtime error. Any ideas?
I can send gratuity via venmo or paypal, just send me your username!
thanks ;)
# 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)
Louis Szeto
Duplicated, you might refer to
😊
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.
Christian Olsen
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!