{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cc262707",
   "metadata": {},
   "source": [
    "<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7482284",
   "metadata": {},
   "source": [
    "This code retrieves financial data and calculates the cost and implications of an options straddle strategy for a given stock. It fetches the earnings calendar, stock price, and options chain for a specific symbol. It then identifies the at-the-money (ATM) call and put options expiring shortly after the earnings report. The cost of the straddle and the implied daily price movement are calculated and printed. This is useful for traders and investors to understand potential price movements around earnings announcements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5c23a683",
   "metadata": {},
   "outputs": [],
   "source": [
    "from datetime import datetime, timedelta\n",
    "import pandas as pd\n",
    "from openbb import obb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5b896a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "obb.user.preferences.output_type = \"dataframe\"\n",
    "obb.user.credentials.nasdaq_api_key = \"PLACE_HOLDER\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f4b030b",
   "metadata": {},
   "source": [
    "Retrieve earnings calendar data from OpenBB for the next 14 days from today"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a37bb2a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "earnings_calendar = obb.equity.calendar.earnings(\n",
    "    start_date=(datetime.now() + timedelta(days=1)).date(),\n",
    "    end_date=(datetime.now() + timedelta(days=14)).date(),\n",
    "    provider=\"nasdaq\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b97c34f",
   "metadata": {},
   "source": [
    "Define the symbol for Costco (COST) and fetch the latest stock price"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "759c836d",
   "metadata": {},
   "outputs": [],
   "source": [
    "symbol = \"COST\"\n",
    "last_price = (\n",
    "    obb\n",
    "    .equity\n",
    "    .price\n",
    "    .quote(symbol, provider=\"yfinance\")\n",
    "    .T\n",
    "    .loc[\"last_price\", 0]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "128df5e6",
   "metadata": {},
   "source": [
    "Retrieve options chains for the specified symbol from OpenBB"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28c03abc",
   "metadata": {},
   "outputs": [],
   "source": [
    "options = obb.derivatives.options.chains(symbol, provider=\"cboe\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db27ab8f",
   "metadata": {},
   "source": [
    "Filter options chain for contracts expiring on the specified date (shortly after earnings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "74cf187a",
   "metadata": {},
   "outputs": [],
   "source": [
    "expiration = datetime(2024, 3, 8).date()\n",
    "chain = options.query(\"`expiration` == @expiration\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41460a1e",
   "metadata": {},
   "source": [
    "Extract strike prices and identify the ATM strike for calls and puts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5ed6ce2b",
   "metadata": {},
   "outputs": [],
   "source": [
    "strikes = chain.strike.to_frame()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d20e86f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "call_strike = (\n",
    "    strikes\n",
    "    .loc[strikes.query(\"`strike` > @last_price\").idxmin()][\"strike\"]\n",
    "    .iloc[0]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2f6265e",
   "metadata": {},
   "outputs": [],
   "source": [
    "atm_call = chain.query(\"`strike` == @call_strike and `option_type` == 'call'\")\n",
    "atm_put = chain.query(\"`strike` == @call_strike and `option_type` == 'put'\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56a532be",
   "metadata": {},
   "source": [
    "Concatenate ATM call and put options and calculate the total ask price for the straddle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5732e3c",
   "metadata": {},
   "outputs": [],
   "source": [
    "atm = pd.concat([atm_call, atm_put])\n",
    "straddle_price = round(atm.ask.sum(), 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "986e2637",
   "metadata": {},
   "source": [
    "Calculate the implied daily price movement based on the straddle price and time to expiration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff7156bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "days = (atm.expiration.iloc[0] - datetime.now().date()).days + 1\n",
    "implied_move = ((1 + straddle_price / last_price) ** (1 / days) - 1) * 100"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3fc92d6c",
   "metadata": {},
   "source": [
    "Calculate the upper and lower breakeven prices for the straddle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3d711b56",
   "metadata": {},
   "outputs": [],
   "source": [
    "upper_price = round((last_price * (1 + (straddle_price / last_price))), 2)\n",
    "lower_price = round((last_price * (1 - (straddle_price / last_price))), 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e54c3cc",
   "metadata": {},
   "source": [
    "Print the calculated straddle cost, its percentage of the share price, breakeven prices, and implied daily move"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "59a33449",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\n",
    "    f\"Cost of Straddle: ${straddle_price}\"\n",
    "    f\"\\nCost as a % of Share Price: {round((straddle_price / last_price) * 100, 4)}%\"\n",
    "    f\"\\nUpper Breakeven Price: ${upper_price}\"\n",
    "    f\"\\nLower Breakeven Price: ${lower_price}\\n\"\n",
    "    f\"\\nImplied Daily Move: {round(implied_move, 4)}%\\n\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78bbd8f9",
   "metadata": {},
   "source": [
    "Output the number of days until the specified options expiration date"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe3d43ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "days"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b250a148",
   "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
}
