# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from datetime import timedelta
class CoveredCallOptionsAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2016, 1, 1)
self.SetEndDate(2019, 3, 1)
self.SetCash(1000000)
equity = self.AddEquity("FB", Resolution.Minute)
equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.underlying = equity.Symbol
# use the underlying equity as the benchmark
self.SetBenchmark(self.underlying)
# Initialize the call contract
self.call = str()
def OnData(self,slice):
if not self.Portfolio[self.underlying].Invested:
self.MarketOrder(self.underlying, 900) # 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.Sell(self.call, 0) # short the call option
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))
Hi everyone, I cloned the covered call algo, however, I cannot get it to work with 5 or more stocks. I would really appriacite some help. Thank you!
Halldor Andersen
Hi Dat.
You can extend this algorithm to work with more than five securities by using a for loop:
# In Initialize self.tickers = ["AAPL","IBM","CAT","BA","INTC","NVDA"] for ticker in self.tickers: equity = self.AddEquity(ticker, Resolution.Minute) equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
And in the method OnData():
# In OnData() for underlying in self.tickers: self.underlying = underlying if not 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.Sell(self.call, 1) # short the call option self.call = str()
I've attached a backtest where I've made adjustments to the code according to the highlights above. Notice that the algorithm sells a call option for all six stocks on market open.
Dat Do
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!