Hello everyone,
I took a look into options on Quantconnect and found the introductory tutorials really helpful. All of these examples trade only options for one symbol though. I'd like to try something with multiple symbols but I don't know how to do that with the Slice class. Could someone maybe post any such algorithm? A simple one like the first example just with two or three symbols would do. Thank you in advance.
Kind regards,
Christian
Jing Wu
You can add multiple options with a list of underlying tickers and save the option symbols in a new list.
for ticker in ["IBM", "AAPL"]:
option = self.AddOption(ticker)
self.symbols.append(option.Symbol)
option.SetFilter(-2, +2, timedelta(0), timedelta(180))
In OnData(self, slice), you can get the option chain for the specified symbol with
for symbol in self.symbols:
for kvp in slice.OptionChains:
if kvp.Key == symbol:
chain = kvp.Value
Christian Lauer
Thank you very much for your answer, Jing! I have another question: How do I access the prices of the options in my portfolio? Let's say I'd like to sell the options bought by your algorithm when their current price is 10 percent higher than the price they were bought for.
Kind regards,
Christian
Jing Wu
We have quoteBar(with bid/ask) data for options. There are a few methods to get the option contract price:
contract = contracts[0] contract_symbol = contracts[0].Symbol
1) self.Securities[contract_symbol].Price returns the mid-price = (bid+ask)/2
2) contracts.AskPrice / contracts.BidPrice returns the ask/bid price.
3) The order is filled based on bid/ask price. If you are selling a stock, you are going to get the bid price, if you are buying a stock you are going to get the ask price.
You can get the order filling price with
ticket = self.MarketOrder(symbol, 1) fill_price = ticket.AverageFillPrice
Then you can place a limit sell order to sell the contract when their current price is 10 percent higher than the price they were bought for.
self.LimitOrder(contract_symbol, -1, fill_price*1.1)
For details about limit orders, please refer to this algorithm
Christian Lauer
Hello Jing,
thank you very much for your answer! It's working now. I have another question concerning the algorithm you posted: You use the line
if self.Portfolio.Invested: return
If I remove this. There are multiple trades for the same symbol. Why is that? Shouldn't
if not self.Portfolio[symbol].Invested:
prevent the algorithm from odering if the option for that symbol is already in the portfolio? I need to remove the first line but I only want each option once, so I need to fix this.
Kind regards,
Christian
Jing Wu
"if self.Portfolio.Invested: return" means if there are any positions in your portfolio invested, the code after this line will not be executed in the current time slice.
"if not self.Portfolio[symbol].Invested" specified the symbol, it returns the boolean value to decide if there are holdings for this symbol in the portfolio.
To just show you a simple example. I added this line "if self.Portfolio.Invested: return" so the code for option contract selection part won't be executed each minute to speed up the algorithm.
Christian Lauer
Hello Jing,
thank you for your answer. My issue is that I want to have each option only once in my portfolio. When removing the line "if self.Portfolio.Invested: return" like in the attached backtest, this is not the case anymore. I thought to achieve this by using "if not self.Portfolio[symbol].Invested" which should be false so that the following code should not be executed if already invested in that stock but apparantly this is not the case. So what do I have to change?
Jing Wu
You can get a list of all option holdings in the portfolio and check if the underlying asset of the invested contract equals the symbol. Please see the attached algorithm
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option] for symbol in self.symbols: invested = [option for option in option_invested if option.Underlying == symbol.Underlying] if len(invested) > 0: return for kvp in slice.OptionChains: ####
Christian Lauer
Hello Jing,
thank you for your help again!
if len(invested) > 0: return
works fine to avoid selling the same option twice. Now I need a buying condition too. I think here something like
if self.Portfolio[contract_symbol].Invested:
is also not working properly. (When checking the logs of my algorithm it should log every invested symbol every minute which it is not doing.) Which line should be used instead?
Also I wonder whether it's possible to create only one option chain for all symbols and then invest in the first ten or something after it's been sorted by certain criteria. How would I have to modify my algorithm in order to do that?
Kind regards,
Christian
Jing Wu
1) After you trade the option contract for a specified symbol, In the next time step, you filtered the contract again. "contracts" might change in the next time step, then "contract_symbol" might change as well. If you use "self.Portfolio[contract_symbol].Invested", you can not guarantee "contract_symbol" here is still the contract when you place the order with "self.MarketOrder(contract_symbol, -1)". You can save the contract you've already invested in a dictionary (keyed by the underlying symbol) once you place the order over it and use this symbol to decide "if self.Portfolio[contract_symbol].Invested". Otherwise, contract_symbol might change over time because you filtered the contract at each time step.
# check this part of your code, contract_symbol might change over time contracts = sorted(sorted(sorted(contracts_iv, key = lambda x: -x.AskPrice/(x.AskPrice+ max(20*chain.Underlying.Price - (chain.Underlying.Price - x.Strike), 10*x.Strike))), key = lambda x: x.Expiry, reverse=True), key = lambda x: x.Right, reverse=True) if len(contracts) == 0: continue contract_symbol = contracts[0].Symbol symbol = contracts[0].Symbol if self.Portfolio[contract_symbol].Invested: self.Debug()
self.Portfolio[contrat_symbol].IsLong and self.Portfolio[contrat_symbol].IsShort can help you decide if it is a long or short position in your portfolio.
2) You can save option contracts for all the underlying symbols in a list and sort them by your criteria.
all_contracts = [] for i in self.symbols: # get a list of contracts for the specified underlying asset chain = slice.OptionChains.GetValue(i) if chain is None: return all_contracts += chain
Jing Wu
"self.SetFilter(minStrike, maxStrike, minExpiry, maxExpiry)" does not include the weekly contracts. To add the weekly contracts, you can use
option.SetFilter(self.UniverseFunc) def UniverseFunc(self, universe): return universe.IncludeWeeklys().Strikes(-3, 3).Expiration(timedelta(0), timedelta(180))
Please see this example
For option data in Data Explorer, each file contains the price data for a single contract in a single day. For example
20180904_ibm_minute_quote_american_call_1000000_20181221.csv
It is the quote data on 20180904 for the IBM call option contract with the strike 100 and the expiry 12/21/2018.
Christian Lauer
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!