8.1 KiB
This code calculates the theta (time decay) of an American call option on Apple Inc. (AAPL) stock using QuantLib and OpenBB libraries. It fetches option chains and historical prices, determines the closest strike price, and computes volatility. The code then sets up the market data, constructs a Black-Scholes-Merton process, and uses a binomial pricing engine to price the option. Finally, it computes and returns the theta of the call option, which measures the sensitivity of the option's price to the passage of time.
import numpy as np import QuantLib as ql from openbb import obb import warnings
warnings.filterwarnings("ignore") obb.user.preferences.output_type = "dataframe"
Define the stock symbol and fetch option chains and historical prices
symbol = "AAPL" chains = obb.derivatives.options.chains(symbol=symbol) prices = obb.equity.price.historical(symbol=symbol, provider="yfinance")
Select an expiration date and fetch associated strike prices
expiration = chains.expiration.unique()[5] strikes = chains.query("`expiration` == @expiration").strike.to_frame()
Determine the underlying stock price and identify the closest strike price
underlying_price = prices.close.iat[-1] strike_price = ( strikes .loc[ (strikes-underlying_price) .abs() .sort_values("strike") .index[0] ].strike )
Calculate volatility, maturity, dividend yield, and risk-free rate
volatility = prices.close.pct_change().std() * np.sqrt(252) maturity = ql.Date( expiration.day, expiration.month, expiration.year, ) dividend_yield = 0.0056 risk_free_rate = 0.05 calculation_date = ql.Date.todaysDate() ql.Settings.instance().evaluationDate = calculation_date
Set up the market data including spot price, yield term structure, dividend yield, and volatility
spot_handle = ql.QuoteHandle( ql.SimpleQuote(underlying_price) )
yield_handle = ql.YieldTermStructureHandle( ql.FlatForward( calculation_date, risk_free_rate, ql.Actual365Fixed() ) )
dividend_handle = ql.YieldTermStructureHandle( ql.FlatForward( calculation_date, dividend_yield, ql.Actual365Fixed() ) )
volatility_handle = ql.BlackVolTermStructureHandle( ql.BlackConstantVol( calculation_date, ql.NullCalendar(), volatility, ql.Actual365Fixed() ) )
Construct a Black-Scholes-Merton process for option pricing
bs_process = ql.BlackScholesMertonProcess( spot_handle, dividend_handle, yield_handle, volatility_handle )
Set up the pricing engine using a binomial tree model with 1000 steps
engine = ql.BinomialVanillaEngine(bs_process, "crr", steps=1000)
Define the American call option with the calculated strike price and maturity
exercise = ql.AmericanExercise(calculation_date, maturity) call_option = ql.VanillaOption( ql.PlainVanillaPayoff(ql.Option.Call, strike_price), exercise )
Assign the pricing engine to the call option
call_option.setPricingEngine(engine)
Calculate and return the theta of the call option, normalized by the number of days in a year
call_theta = call_option.theta() / 365 call_theta
PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk.
