Hello, trying to get a simple options algorthm to run and I'm having a hard time. Goal is to seach for options contracts for QQQ that are 6-13 days out and within 2 of the strike price. When Fast EMA > Slow EMA then it should buy the options contract that is smaller than the strike price but closest to the strike price. Cant get it to buy one.
import clr
clr.AddReference("System")
clr.AddReference("QuantConnect.Algorithm")
clr.AddReference("QuantConnect.Indicators")
clr.AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
### <summary>
### In this example we look at the canonical 15/30 day moving average cross. This algorithm
### will go long when the 15 crosses above the 30 and will liquidate when the 15 crosses
### back below the 30.
### </summary>
### <meta name="tag" content="indicators" />
### <meta name="tag" content="indicator classes" />
### <meta name="tag" content="moving average cross" />
### <meta name="tag" content="strategy example" />
class MovingAverageCrossAlgorithm(QCAlgorithm):
def Initialize(self):
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
self.SetStartDate(2021,1,1) #Set Start Date
self.SetEndDate(2021,5,15) #Set End Date
self.SetCash(100000) #Set Strategy Cash
# Find more symbols here: http://quantconnect.com/data
self.AddEquity("QQQ")
option = self.AddOption("QQQ", Resolution.Minute) # Add the option corresponding to underlying stock
self.symbol = option.Symbol
option.SetFilter(-2, +2, timedelta(6), timedelta(13))
# create a 15 day exponential moving average
self.fast = self.EMA("QQQ", 50, Resolution.Minute)
# create a 30 day exponential moving average
self.slow = self.EMA("QQQ", 200, Resolution.Minute)
self.MarketTicket = None
self.previous = None
def OnData(self, data):
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.'''
# a couple things to notice in this method:
# 1. We never need to 'update' our indicators with the data, the engine takes care of this for us
# 2. We can use indicators directly in math expressions
# 3. We can easily plot many indicators at the same time
# wait for our slow ema to fully initialize
if not self.slow.IsReady:
return
# only once per day
if self.previous is not None and self.previous.date() == self.Time.date():
return
# define a small tolerance on our checks to avoid bouncing
tolerance = 0.00015
QQQprice = self.Securities["QQQ"].Price # Gives close price of QQQ
QQQopen = self.Securities["QQQ"].Open # Gives last open price of QQQ
holdings = self.Portfolio["QQQ"].Quantity
# we only want to go long if we're currently short or flat
if holdings <= 0:
# if the fast is greater than the slow, we'll go long
if self.fast.Current.Value > self.slow.Current.Value *(1 + tolerance):
call = [x for x in optionchain if x.Right == 0]
contracts = [x for x in call if x.UnderlyingLastPrice - x.Strike < 0]
#call = [x for x in optionchain if chain.Right == 0]
#contracts = [x for x in call if call.UnderlyingLastPrice - x.Strike < 0]
# if found, trade it
symbol = contracts[0].Symbol
self.MarketTicket = self.MarketOrder(symbol, 1)
# we only want to liquidate if we're currently long
# if the fast is less than the slow we'll liquidate our long
if holdings > 0 and self.fast.Current.Value < self.slow.Current.Value:
self.Log("SELL >> {0}".format(self.Securities["QQQ"].Price))
self.Liquidate("QQQ")
self.previous = self.Time
Derek Melchin
Hi David,
The algorithm above uses the `optionchain` variable without defining it. To resolve the issue, we just need to adjust how we select the contract to trade. To purchase the call option with its strike right below the price of QQQ, we can use:
for symbol, chain in data.OptionChains.items(): contracts = [c for c in chain if c.Right == OptionRight.Call and c.UnderlyingLastPrice > c.Strike] if len(contracts) == 0: continue sorted_contracts = sorted(contracts, key=lambda x: x.Strike, reverse=True) contract = sorted_contracts[0].Symbol self.MarketTicket = self.MarketOrder(contract, 1)
See the attached backtest for reference.
Best,
Derek Melchin
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.
David Eldringhoff
Hey Derek,
Thanks for that explanation and the working backrest. I see what my error is now with the code. Quick follow up question. I’m going to add this to an existing algorithm. Since I don’t want to just liquidate all my equity is because the options would be a very small percentage of the overall portfolio. Can I use code such as self.portfolio invested QQQ? Will these options be considered QQQ? Or do I need to code something specific to pull the name of the type of call contract I own?
David Eldringhoff
Also, let’s say I wanted to buy a put instead . That one line that states Optionright.call, that just needs to be changed to optionright.put?
Derek Melchin
Hi David,
To determine if we are invested in QQQ options, we should use the contract Symbol instead of 'QQQ'.
See the attached backtest for reference.
>That one line that states Optionright.call, that just needs to be changed to optionright.put?
Yes, that's correct. To select put contracts, we should use
Best,
Derek Melchin
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.
Laurent Crouzet
Hi David Eldringhoff
This strategy is rather weird: it asks to trade options contracts for QQQ that are 6-13 days out, but if you do not ask to get the WEEKLY expirations in addition to monthly expirations… no option can be traded for several weeks a month just because no one satisfy the "maximum 13-days before expiration date" filter.
Being able to trade the options with weekly expirations would probably be useful to avoid this strange behavior.
Best regards,
Laurent
David Eldringhoff
Thank you very much, both of you! I’m currently double backing to Some adjustments on my main algorithm. I want to add some options trading as a small portion of my portfolio to this other algorithm in the next couple weeks. So I am working on just trying to figure some of these options trading issues out.
I couldn’t recognize that this was only pulling monthly expirations. I don’t see where it dictates that in the algorithm. Yes, I was looking for short term entry and exits and wanted a closer expiration on a weekly basis.
David Eldringhoff
I did notice there were gaps in the trading… just couldn’t figure it out haha
Laurent Crouzet
Actually, David Eldringhoff, you did not really “ask to exclude the weekly expirations”… but that is how QC is built.
See the documentation here:
As explained in the docs, you have to specifically request the Weekly options to get them in addition to monthly ones:
“The data defaults to monthly expiration contracts. If you'd like weekly expirations as well, you must add it to your filter in the SetFilter method.”
For instance:
By the way, Derek Melchin, there seems to be a typo in the documentation of the Python codes for weekly options, as there are semicolons in the 2 Python versions, and even if I am far from being an expert in Python… I have regularly seen experts stating that semicolon should not be used in Python codes.
Derek Melchin
Hi Laurent,
Thank you. We'll be sure to remove the semicolons in the new version of the documentation.
Best,
Derek Melchin
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.
Vladimir
Derek, Laurent,
→ experts stating that semicolon should not be used in Python codes
I have been using semicolons in my Python codes for over 6 years and have never had a problem.
Laurent Crouzet
Vladimir You are right: it is possible to use semicolons in Python.
However, semicolons are deemed not to be pythonic (even if I am not an expert in Python myself, I do try to follow the “best practices”)
David Eldringhoff
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!