from datetime import timedelta
class OptionsAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 1, 1)
self.SetEndDate(2020, 12, 1)
self.SetCash(20000)
self.syl = 'SPY'
equity = self.AddEquity(self.syl, Resolution.Minute)
equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.macd = self.MACD(self.syl, 12, 26, 9, MovingAverageType.Exponential, Resolution.Daily)
self.rsi = self.RSI("SPY", 14)
self.underlyingsymbol = equity.Symbol
# use the underlying equity as the benchmark
self.SetBenchmark(equity.Symbol)
def OnData(self,slice):
if not self.rsi.IsReady:
return
if self.rsi.Current.Value < 25 and self.Portfolio.Invested <= 0:
if self.macd.IsReady:
if self.Portfolio[self.contract].Quantity == 0 and self.macd.Current.Value > self.macd.Signal.Current.Value and self.macd.Current.Value < 0:
self.BuyCall()
if self.rsi.Current.Value > 50 and self.Portfolio.Invested >= 1:
if self.Portfolio[self.contract].Quantity > 0 and self.macd.Current.Value > self.macd.Signal.Current.Value and self.macd.Current.Value > 0:
if self.Portfolio.Invested:
self.Liquidate()
def BuyCall(self):
contracts = self.OptionChainProvider.GetOptionContractList(self.underlyingsymbol, self.Time.date())
if len(contracts) == 0: return
filtered_contracts = self.InitialFilter(self.underlyingsymbol, contracts, -3, 3, 0, 30)
call = [x for x in filtered_contracts if x.ID.OptionRight == 1]
# sorted the contracts according to their expiration dates and choose the ATM options
contracts = sorted(sorted(call, key = lambda x: abs(self.Securities[self.syl].Price - x.ID.StrikePrice)),
key = lambda x: x.ID.Date, reverse=True)
self.contract = contracts[0]
self.AddOptionContract(self.contract, Resolution.Minute)
self.Buy(self.contract, 1)
def InitialFilter(self, underlyingsymbol, symbol_list, 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 '''
if len(symbol_list) == 0 : return
# fitler the contracts based on the expiry range
contract_list = [i for i in symbol_list 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[underlyingsymbol].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:
min_strike = strike_list[atm_strike_rank + min_strike_rank]
max_strike = strike_list[atm_strike_rank + max_strike_rank]
except:
min_strike = strike_list[0]
max_strike = strike_list[-1]
filtered_contracts = [i for i in contract_list if i.ID.StrikePrice >= min_strike and i.ID.StrikePrice <= max_strike]
return filtered_contracts
I am trying to buy ATM call options for "SPY" for essentially the nearest options chain date and then sell the purchased contract. My conditions that need to be met are as follows:
Buy Call option:
RSI < 25
MACD signal crossover (current value > signal value) and current value is (-) or < 0
*Another condition i want to add is MACD difference (between the current value and signal value) set to 0.4 or greater (from histogram)
if these conditions are met, buy call option ATM strike, current "bid" price (1 contract).
Once invested, look to sell using the following conditions:
Sell purchased option contract:
RSI > 50
MACD current value is (+) or > 0
if these conditions are met, sell the purcahsed contract at current "bid" price
Would greatly appreciate any help, what i have so far above are pieces from other code that i have seen. But the code isn't running - type and attribute errors.
Also, in the end i'm not looking for an active trading platform.. more looking for a "notification" algo so i can further investigate the opportunity.
Shile Wen
Hi James!
Welcome to the platform. For new users, I suggest checking out our BootCamp along with our free Udemy course to get familiar with the platform.
Best,
Shile Wen
James Goldberg
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!