I have played with the examples in the documentation and I see how to get IV values of a contract within the OnData function. But in this current test project of allocating portfolio based on iv each month, I'm getting 0 returned for every contract. For some reason it is not calculating the IV. The indicator is either None or not Ready, but I don't know why. And neither does Mia.
from AlgorithmImports import *
class MonthlyOptionsAllocation(QCAlgorithm):
def Initialize(self):
# Set start and end dates for backtesting
self.SetStartDate(2015, 1, 1)
self.SetEndDate(2024, 12, 1)
self.SetCash(100000)
self.SetWarmUp(timedelta(days=30)) # for IV indicator calculation
# List of stock tickers
self.tickers = [
"AAPL", "MSFT", "GOOG", "AMZN", "TSLA", "META",
"NFLX", "NVDA", "BABA", "AMD", "SPY", "QQQ",
"INTC", "XOM", "BA", "JPM", "V", "MA", "DIS", "COST"
]
# Add equities and their options
self.symbols = []
for ticker in self.tickers:
equity = self.add_equity(ticker, Resolution.DAILY).Symbol
option = self.add_option(ticker, Resolution.MINUTE).Symbol
self.symbols.append((equity, option))
self._iv = self.iv(self.option)
# Schedule monthly portfolio rebalancing
self.schedule.on(
self.date_rules.month_start(self.tickers[0]),
self.time_rules.at(10, 0),
self.rebalance_portfolio
)
# Keep track of performance metrics
self.sharpe_ratios = {}
def rebalance_portfolio(self):
selected_symbols = []
for equity, option in self.symbols:
history = self.history(equity, 252, Resolution.DAILY)
if len(history) < 252:
continue
daily_returns = history['close'].pct_change().dropna()
if daily_returns.std() == 0:
sharpe_ratio = 0
else:
sharpe_ratio = (252 ** 0.5) * daily_returns.mean() / daily_returns.std()
self.sharpe_ratios[equity] = sharpe_ratio
if sharpe_ratio > 0:
selected_symbols.append(option)
# Allocate capital based on IV
self.set_holdings_based_on_iv(selected_symbols)
def set_holdings_based_on_iv(self, selected_symbols):
"""Allocate weights to selected tickers based on IV."""
total_iv = 0
ivs = {}
for option_symbol in selected_symbols:
chain = self.option_chain_provider.get_option_contract_list(option_symbol, self.Time)
if not chain:
self.debug(f"No chain found for: {option_symbol}")
continue
# Filter for monthly contracts expiring in the current month
monthly_contracts = [
c for c in chain
if c.ID.Date.month == self.Time.month and c.ID.Date.year == self.Time.year
]
if not monthly_contracts:
self.debug(f"No monthly contracts: {option_symbol}")
continue
# Select the ATM contract
underlying_price = self.Securities[option_symbol.Underlying].Price
atm_contract = min(
monthly_contracts,
key=lambda x: abs(x.ID.StrikePrice - underlying_price),
default=None
)
if atm_contract is None:
self.debug(f"No ATM contract found for: {option_symbol}")
continue
# Add the contract and calculate IV
self.AddOptionContract(atm_contract, Resolution.Minute)
iv_indicator = self.iv(atm_contract, option_model=OptionPricingModelType.BLACK_SCHOLES)
if iv_indicator is None or not iv_indicator.IsReady:
self.debug(f"IV indicator not ready for contract: {atm_contract}")
continue
iv = iv_indicator.Current.Value
if iv <= 0:
self.debug(f"Invalid IV value for contract: {atm_contract}")
continue
self.debug(f"Contract {atm_contract} IV: {iv}")
ivs[option_symbol] = iv
total_iv += iv
# Allocate capital proportionally based on IV
if total_iv > 0:
for option_symbol, iv in ivs.items():
weight = iv / total_iv
self.SetHoldings(option_symbol.Underlying, weight)
else:
self.debug("Total implied volatility is zero, no holdings set.")
def OnData(self, data):
"""Handles incoming data."""
pass
Mia Alissi
Sources: Option Indicators Regression Algorithm, Momentum Effect In Country Equity Indexes, 12 Month Cycle In Cross Section Of Stocks Returns, Momentum Effect In Commodities Futures, Basic Template Index Daily Algorithm
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.
Matt
Still trying to figure this out. A contract's IV needs to be warmed up somehow before selecting it or the iv will never be ready. Can't do this with every contract of a symbol can we? Is there no historical IV data somewhere?
Matt
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!