Files
strategy-lab/to_explore/pyquantnews/88_QuantLibGreeks.ipynb
David Brazda e3da60c647 daily update
2024-10-21 20:57:56 +02:00

8.1 KiB

No description has been provided for this image

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.

In [ ]:
import numpy as np
import QuantLib as ql
from openbb import obb
import warnings
In [ ]:
warnings.filterwarnings("ignore")
obb.user.preferences.output_type = "dataframe"

Define the stock symbol and fetch option chains and historical prices

In [ ]:
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

In [ ]:
expiration = chains.expiration.unique()[5]
strikes = chains.query("`expiration` == @expiration").strike.to_frame()

Determine the underlying stock price and identify the closest strike price

In [ ]:
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

In [ ]:
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

In [ ]:
spot_handle = ql.QuoteHandle(
    ql.SimpleQuote(underlying_price)
)
In [ ]:
yield_handle = ql.YieldTermStructureHandle(
    ql.FlatForward(
        calculation_date, 
        risk_free_rate, 
        ql.Actual365Fixed()
    )
)
In [ ]:
dividend_handle = ql.YieldTermStructureHandle(
    ql.FlatForward(
        calculation_date, 
        dividend_yield, 
        ql.Actual365Fixed()
    )
)
In [ ]:
volatility_handle = ql.BlackVolTermStructureHandle(
    ql.BlackConstantVol(
        calculation_date, 
        ql.NullCalendar(), 
        volatility, 
        ql.Actual365Fixed()
    )
)

Construct a Black-Scholes-Merton process for option pricing

In [ ]:
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

In [ ]:
engine = ql.BinomialVanillaEngine(bs_process, "crr", steps=1000)

Define the American call option with the calculated strike price and maturity

In [ ]:
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

In [ ]:
call_option.setPricingEngine(engine)

Calculate and return the theta of the call option, normalized by the number of days in a year

In [ ]:
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.