{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a60f3e1c",
   "metadata": {},
   "source": [
    "<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40516b4b",
   "metadata": {},
   "source": [
    "This code calculates the implied volatility of an American call option using the QuantLib library. It sets up the necessary financial parameters, including the spot price, risk-free rate, dividend yield, volatility, days to maturity, strike price, and option price. The code establishes the yield term structure, spot price handle, payoff, exercise type, and volatility structure. It then uses the Black-Scholes-Merton process and a binomial pricing engine to compute the implied volatility. This is useful for financial analysts and traders to evaluate the market's expectation of future volatility."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7f49c2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import QuantLib as ql"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a1591ae",
   "metadata": {},
   "source": [
    "Define the financial parameters including spot price, risk-free rate, dividend yield, volatility, days to maturity, strike price, and option price"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3ebda590",
   "metadata": {},
   "outputs": [],
   "source": [
    "spot_price = 188.64\n",
    "risk_free_rate = 0.0525\n",
    "dividend_yield = 0.0052\n",
    "volatility = 0.20\n",
    "days_to_maturity = 148\n",
    "strike_price = 190\n",
    "option_price = 11.05"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b500dd31",
   "metadata": {},
   "source": [
    "Set up the calendar, day count convention, and evaluation date for the option pricing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96d768af",
   "metadata": {},
   "outputs": [],
   "source": [
    "calendar = ql.NullCalendar()\n",
    "day_count = ql.Actual360()\n",
    "today = ql.Date().todaysDate()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d0b1bce",
   "metadata": {},
   "source": [
    "Set the evaluation date to today's date"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d8ade3ec",
   "metadata": {},
   "outputs": [],
   "source": [
    "ql.Settings.instance().evaluationDate = today"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "661ffd5b",
   "metadata": {},
   "source": [
    "Create a flat yield term structure for the risk-free rate and dividend yield"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d310993f",
   "metadata": {},
   "outputs": [],
   "source": [
    "risk_free_ts = ql.YieldTermStructureHandle(\n",
    "    ql.FlatForward(today, risk_free_rate, day_count)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "835e2362",
   "metadata": {},
   "outputs": [],
   "source": [
    "dividend_ts = ql.YieldTermStructureHandle(\n",
    "    ql.FlatForward(today, dividend_yield, day_count)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4e11c17",
   "metadata": {},
   "source": [
    "Set up the handle for the underlying asset's spot price"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "12ff1c7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "471bc5de",
   "metadata": {},
   "source": [
    "Define the expiration date, payoff, and exercise type for the American option"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b8740093",
   "metadata": {},
   "outputs": [],
   "source": [
    "expiration_date = today + ql.Period(days_to_maturity, ql.Days)\n",
    "payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike_price)\n",
    "exercise = ql.AmericanExercise(today, expiration_date)\n",
    "american_option = ql.VanillaOption(payoff, exercise)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d47c67a8",
   "metadata": {},
   "source": [
    "Create the volatility handle for the Black-Scholes-Merton process using a constant volatility model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b53d34fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "volatility_handle = ql.BlackVolTermStructureHandle(\n",
    "    ql.BlackConstantVol(today, calendar, volatility, day_count)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d841ade",
   "metadata": {},
   "source": [
    "Set up the Black-Scholes-Merton process using the spot price, dividend yield, risk-free rate, and volatility"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f7229c5a",
   "metadata": {},
   "outputs": [],
   "source": [
    "bsm_process = ql.BlackScholesMertonProcess(\n",
    "    spot_handle, dividend_ts, risk_free_ts, volatility_handle\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b67dfaa6",
   "metadata": {},
   "source": [
    "Set the pricing engine to a binomial model with 1000 steps and calculate the implied volatility"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "af0d3fd5",
   "metadata": {},
   "outputs": [],
   "source": [
    "engine = ql.BinomialVanillaEngine(bsm_process, \"crr\", 1000)\n",
    "american_option.setPricingEngine(engine)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a48f5bbc",
   "metadata": {},
   "outputs": [],
   "source": [
    "implied_volatility = american_option.impliedVolatility(\n",
    "    option_price, bsm_process, 1e-4, 1000, 1e-8, 4.0\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "779a595f",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"Implied Volatility: {implied_volatility:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "771e5019",
   "metadata": {},
   "source": [
    "<a href=\"https://pyquantnews.com/\">PyQuant News</a> 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 <a href=\"https://gettingstartedwithpythonforquantfinance.com/\">get started with Python for quant finance</a>. For educational purposes. Not investment advise. Use at your own risk."
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
