I'm sure I am missing something basic, but I am having trouble with an apparent mismatch between the stock prices returned by QuantBook.history and the option strike prices returned by QuantBook.GetOptionHistory. When I request options with strikes 1 above and 1 below the underlying price it returns strikes that are both on one side of the underlying price returned by the history method. This is the case even though the returned data indicates the same update time.
def option_universe_filter(universe):
return universe.include_weeklys().strikes(-1, 1)
def get_option_info(qb, stock, option, open_date):
open_start_time = datetime.datetime.combine(open_date, datetime.time(15, 40, 0))
open_end_time = open_start_time + datetime.timedelta(minutes=1)
stock_history_minute = qb.history(stock.symbol, start=open_start_time, end=open_end_time, resolution=Resolution.MINUTE, flatten=True)
open_underlying_price = stock_history_minute.iloc[-1].close
print(f'Price of {stock.symbol} at {stock_history_minute.index[-1][-1]} = {open_underlying_price}')
option.set_filter(option_universe_filter)
option_history_minute = qb.GetOptionHistory(option.symbol, start=open_start_time, end=open_end_time, resolution=Resolution.MINUTE).GetAllData()
strike_prices = set([i[1] for i in option_history_minute.index if i[1]!=''])
update_time = set([i[-1] for i in option_history_minute.index if i[-1]!='']).pop()
assert update_time == stock_history_minute.index[-1][-1]
strike_prices = sorted(strike_prices)
print(f'Nearest strikes at {update_time} according to GetOptionHistory: {strike_prices}')
qb = QuantBook()
stock = qb.add_equity('AAPL')
option = qb.add_option('AAPL')
date = datetime.date(2024, 9, 13)
get_option_info(qb, stock, option, date)Price of AAPL at 2024-09-13 15:41:00 = 221.459315075
Nearest strikes at 2024-09-13 15:41:00 according to GetOptionHistory: [222.5, 225.0]
Mia Alissi
Here's a detailed explanation and best practice for your situation, Luke:
Why Can
strikes(-1, 1)Return Both Strikes on the Same Side of the Underlying?In QuantConnect, the
strikes(-1, 1)filter does not select “the nearest strike below and above the current underlying price.” Instead, it selects strikes by index in the provider's discrete, sorted list of available strikes, which may be in steps (e.g., $2.5, $5, etc.).Example:
If the underlying is $221.46, and available strikes are [222.5, 225.0]:
This explains your result:
The underlying price is between two listed strikes, and the filter simply takes the nearest available strikes by index, which may both be above (or below) the spot price.
How To List Strikes, and Select Nearest Above/Below Manually
If you require strikes exactly straddling the spot price (one below and one above), you'll need to manually query the available strikes and select the closest ones on each side. Here's how:
Code Example:
To List All Available Strikes:
Summary for the Future:
strikes(min, max)indexes a discrete list—results depend on the available contracts, not on arithmetic distance from the spot..get_strikes()onOptionHistoryor inspect the chain in OnData.Remember: "strikes(-1, 1) selects by index, not by price—be aware of available contracts and increment steps!"
Let me know if you'd like a version in your current QuantBook style, or if you want further explanations!
Sources: Universes - QuantConnect.com, Long Call Backspread - QuantConnect.com, US Equity Option Universe - QuantConnect.com, Short Call Backspread - QuantConnect.com
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.
Luke Buerer
“If the underlying spot price is between contract increments, both nearest contracts may land above (or below) the spot.”
This is basically always false. There will always be available contracts above and below the spot price, and the increment of the option is unlikely to change for options near the spot price, so I fail to see how this would ever happen.
Also, the Quantconnect documentation directly contradicts your first claim about how the strike function works:
"strikes(min_strike: int, max_strike: int)
Selects contracts that are within m_strike strikes below the underlying price and max_strike strikes above the underlying price."
I don't see how I would interpret that as meaning anything other than strike(-1, 1) will return the nearest strike below and above the current underlying price.
If any non-bot wants to provide some insight, it'd be very appreciated.
Luke Buerer
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!