{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9d21a51c",
   "metadata": {},
   "source": [
    "<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "658dd5ee",
   "metadata": {},
   "source": [
    "This code implements a binomial model to price American options, considering early exercise features. Using parameters like spot price, strike price, risk-free rate, volatility, time to expiry, and the number of steps, the model constructs a price tree. It then calculates the option value at each node, considering both holding and exercising the option. This approach is practical for valuing American-style options, which can be exercised at any time before expiration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8791fb6f",
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9af5deeb",
   "metadata": {},
   "source": [
    "Define a function to price American options using the binomial tree model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f00b850d",
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "def american_option_pricer(spot, strike, rate, vol, expiry, steps, option_type):\n",
    "    \"\"\"Price an American option using binomial model\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    spot : float\n",
    "        Current spot price of the underlying asset\n",
    "    strike : float\n",
    "        Strike price of the option\n",
    "    rate : float\n",
    "        Risk-free interest rate\n",
    "    vol : float\n",
    "        Volatility of the underlying asset\n",
    "    expiry : float\n",
    "        Time to expiry in years\n",
    "    steps : int\n",
    "        Number of steps in the binomial tree\n",
    "    option_type : str\n",
    "        Type of the option ('call' or 'put')\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    float\n",
    "        Estimated price of the American option\n",
    "    \n",
    "    Notes\n",
    "    -----\n",
    "    This function constructs a binomial tree to \n",
    "    estimate the price of an American option. It \n",
    "    accounts for early exercise features by comparing \n",
    "    the value of holding versus exercising the option \n",
    "    at each node.\n",
    "    \"\"\"\n",
    "\n",
    "    # Calculate the time interval and the up and down factors\n",
    "\n",
    "    dt = expiry / steps\n",
    "    u = np.exp(vol * np.sqrt(dt))\n",
    "    d = 1 / u\n",
    "\n",
    "    # Calculate the risk-neutral probability\n",
    "\n",
    "    p = (np.exp(rate * dt) - d) / (u - d)\n",
    "\n",
    "    # Create the binomial price tree\n",
    "\n",
    "    price_tree = np.zeros((steps + 1, steps + 1))\n",
    "    for i in range(steps + 1):\n",
    "        price_tree[i, -1] = spot * (u ** (steps - i)) * (d**i)\n",
    "\n",
    "    # Calculate the option value at each node\n",
    "\n",
    "    option_tree = np.zeros_like(price_tree)\n",
    "    if option_type.lower() == \"call\":\n",
    "        option_tree[:, -1] = np.maximum(price_tree[:, -1] - strike, 0)\n",
    "    elif option_type.lower() == \"put\":\n",
    "        option_tree[:, -1] = np.maximum(strike - price_tree[:, -1], 0)\n",
    "    else:\n",
    "        raise ValueError(\"Option type must be either 'call' or 'put'.\")\n",
    "\n",
    "    # Traverse the tree backward to find the option price today\n",
    "\n",
    "    for t in range(steps - 1, -1, -1):\n",
    "        for i in range(t + 1):\n",
    "            exercise = 0\n",
    "            if option_type.lower() == \"call\":\n",
    "                exercise = price_tree[i, t] - strike\n",
    "            elif option_type.lower() == \"put\":\n",
    "                exercise = strike - price_tree[i, t]\n",
    "\n",
    "            hold = np.exp(-rate * dt) * (\n",
    "                p * option_tree[i, t + 1] + (1 - p) * option_tree[i + 1, t + 1]\n",
    "            )\n",
    "            option_tree[i, t] = np.maximum(exercise, hold)\n",
    "\n",
    "    return option_tree[0, 0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cba2ebed",
   "metadata": {},
   "source": [
    "Estimate the price of an American Call option using the defined binomial model parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e615d29c",
   "metadata": {},
   "outputs": [],
   "source": [
    "option_price = american_option_pricer(\n",
    "    spot=55.0,\n",
    "    strike=50.0,\n",
    "    rate=0.05,\n",
    "    vol=0.3,\n",
    "    expiry=1.0,\n",
    "    steps=100,\n",
    "    option_type=\"Call\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a87537d8",
   "metadata": {},
   "source": [
    "Print the estimated price of the American Call option"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5118d3b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\n",
    "    f\"The estimated price of the American Call option is: {option_price:.2f}\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16e10849",
   "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"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
