{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "BzQ2PSUMb1O7" }, "source": [ "# Calculating the Implied Earnings Move Using Options Prices\n", "\n", "Earnings day can be a pivotal moment for a company's share price. The confluence of expectations and reality is a tradable event, drawing crowds to the options market. Observing the surrounding action can provide insight into the consensus view on, and general sentiment of, the company.\n", "\n", "The cost of a straddle - the combined price of an at-the-money call and put - is a common way to gauge the near-term volatility. It's the market's expectation of the price band until expiration. While this includes time value, the isolated price of volatility will generally be higher for the expiry immediately following an earnings release.\n", "\n", "Have a look at companies that trade weekly options and are reporting a on Thursday. If they report after the close, the price of the one-day straddle at the bell will be the purest sample of information.\n", "\n", "The cells below will demonstrate how to get the data from free sources, using the OpenBB Platform." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "da3wLFHJaK1n" }, "outputs": [], "source": [ "# If using in Google Colab, install the OpenBB library.\n", "\n", "#!pip install openbb[\"all\"]\n", "\n", "# Restart the runtime before the next block" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7xcKh78TaTot", "outputId": "1b00dbc7-21cd-421a-b191-b2e8685f491d" }, "outputs": [], "source": [ "from datetime import datetime, timedelta\n", "\n", "from openbb import obb\n", "\n", "obb.user.preferences.output_type = \"dataframe\"" ] }, { "cell_type": "markdown", "metadata": { "id": "WyKBFJg-R_r2" }, "source": [ "If the earnings date falls on an option expiry, contracts expiring that day will not provide exposure to the after-market earnings reports." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 711 }, "id": "49D8bfFFPEwC", "outputId": "b2eebaaa-ef2c-456a-fca2-96f6bee41b2d" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
report_datesymbolnameeps_previouseps_consensusnum_estimatesperiod_endingprevious_report_datereporting_timemarket_cap
1662024-08-28NVDANVIDIA Corporation0.250.5913.02024-072023-08-23after-hours3.160887e+12
02024-09-05AVGOBroadcom Inc.0.950.9510.02024-072023-08-31after-hours7.716866e+11
1672024-08-28CRMSalesforce, Inc.1.631.7316.02024-072023-08-30after-hours2.529962e+11
2612024-08-26PDDPDD Holdings Inc.1.272.662.02024-062023-08-29pre-market2.007811e+11
1682024-08-28RYRoyal Bank Of Canada2.132.143.02024-072023-08-24pre-market1.597315e+11
2622024-08-26BHPBHP Group LimitedNaNNaN1.02024-06NaNafter-hours1.401966e+11
1142024-08-29DELLDell Technologies Inc.1.441.494.02024-072023-08-31after-hours7.922927e+10
1692024-08-28CRWDCrowdStrike Holdings, Inc.0.060.2314.02024-072023-08-30after-hours6.648856e+10
2252024-08-27BMOBank Of Montreal2.081.983.02024-072023-08-29pre-market6.319707e+10
1152024-08-29MRVLMarvell Technology, Inc.0.180.1313.02024-072023-08-24after-hours6.175190e+10
2262024-08-27BNSBank of Nova Scotia (The)1.301.184.02024-072023-08-29pre-market5.855210e+10
1162024-08-29ADSKAutodesk, Inc.1.121.358.02024-072023-08-23after-hours5.444496e+10
1172024-08-29CMCanadian Imperial Bank of Commerce1.141.284.02024-072023-08-31pre-market5.042232e+10
1702024-08-28HPQHP Inc.0.860.864.02024-072023-08-29after-hours3.451380e+10
2272024-08-27HEIHeico Corporation0.770.918.02024-072023-08-28pre-market3.387054e+10
1712024-08-28VEEVVeeva Systems Inc.0.701.0410.02024-072023-08-30after-hours3.256312e+10
1182024-08-29LULUlululemon athletica inc.2.682.9413.02024-072023-08-31after-hours3.184542e+10
882024-09-03ZSZscaler, Inc.-0.17-0.1412.02024-072023-09-05after-hours3.030086e+10
2632024-08-26TCOMTrip.com Group Limited0.600.652.02024-062023-09-04after-hours2.780128e+10
1722024-08-28NTAPNetApp, Inc.0.841.158.02024-072023-08-23after-hours2.745601e+10
\n", "
" ], "text/plain": [ " report_date symbol name eps_previous \\\n", "166 2024-08-28 NVDA NVIDIA Corporation 0.25 \n", "0 2024-09-05 AVGO Broadcom Inc. 0.95 \n", "167 2024-08-28 CRM Salesforce, Inc. 1.63 \n", "261 2024-08-26 PDD PDD Holdings Inc. 1.27 \n", "168 2024-08-28 RY Royal Bank Of Canada 2.13 \n", "262 2024-08-26 BHP BHP Group Limited NaN \n", "114 2024-08-29 DELL Dell Technologies Inc. 1.44 \n", "169 2024-08-28 CRWD CrowdStrike Holdings, Inc. 0.06 \n", "225 2024-08-27 BMO Bank Of Montreal 2.08 \n", "115 2024-08-29 MRVL Marvell Technology, Inc. 0.18 \n", "226 2024-08-27 BNS Bank of Nova Scotia (The) 1.30 \n", "116 2024-08-29 ADSK Autodesk, Inc. 1.12 \n", "117 2024-08-29 CM Canadian Imperial Bank of Commerce 1.14 \n", "170 2024-08-28 HPQ HP Inc. 0.86 \n", "227 2024-08-27 HEI Heico Corporation 0.77 \n", "171 2024-08-28 VEEV Veeva Systems Inc. 0.70 \n", "118 2024-08-29 LULU lululemon athletica inc. 2.68 \n", "88 2024-09-03 ZS Zscaler, Inc. -0.17 \n", "263 2024-08-26 TCOM Trip.com Group Limited 0.60 \n", "172 2024-08-28 NTAP NetApp, Inc. 0.84 \n", "\n", " eps_consensus num_estimates period_ending previous_report_date \\\n", "166 0.59 13.0 2024-07 2023-08-23 \n", "0 0.95 10.0 2024-07 2023-08-31 \n", "167 1.73 16.0 2024-07 2023-08-30 \n", "261 2.66 2.0 2024-06 2023-08-29 \n", "168 2.14 3.0 2024-07 2023-08-24 \n", "262 NaN 1.0 2024-06 NaN \n", "114 1.49 4.0 2024-07 2023-08-31 \n", "169 0.23 14.0 2024-07 2023-08-30 \n", "225 1.98 3.0 2024-07 2023-08-29 \n", "115 0.13 13.0 2024-07 2023-08-24 \n", "226 1.18 4.0 2024-07 2023-08-29 \n", "116 1.35 8.0 2024-07 2023-08-23 \n", "117 1.28 4.0 2024-07 2023-08-31 \n", "170 0.86 4.0 2024-07 2023-08-29 \n", "227 0.91 8.0 2024-07 2023-08-28 \n", "171 1.04 10.0 2024-07 2023-08-30 \n", "118 2.94 13.0 2024-07 2023-08-31 \n", "88 -0.14 12.0 2024-07 2023-09-05 \n", "263 0.65 2.0 2024-06 2023-09-04 \n", "172 1.15 8.0 2024-07 2023-08-23 \n", "\n", " reporting_time market_cap \n", "166 after-hours 3.160887e+12 \n", "0 after-hours 7.716866e+11 \n", "167 after-hours 2.529962e+11 \n", "261 pre-market 2.007811e+11 \n", "168 pre-market 1.597315e+11 \n", "262 after-hours 1.401966e+11 \n", "114 after-hours 7.922927e+10 \n", "169 after-hours 6.648856e+10 \n", "225 pre-market 6.319707e+10 \n", "115 after-hours 6.175190e+10 \n", "226 pre-market 5.855210e+10 \n", "116 after-hours 5.444496e+10 \n", "117 pre-market 5.042232e+10 \n", "170 after-hours 3.451380e+10 \n", "227 pre-market 3.387054e+10 \n", "171 after-hours 3.256312e+10 \n", "118 after-hours 3.184542e+10 \n", "88 after-hours 3.030086e+10 \n", "263 after-hours 2.780128e+10 \n", "172 after-hours 2.745601e+10 " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Lookup some upcoming earnings dates and sort them by market cap.\n", "\n", "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", ")\n", "\n", "earnings_calendar.sort_values(by=[\"market_cap\", \"num_estimates\"], ascending=False).head(\n", " 20\n", ")" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "IzmLloIfTQJo", "outputId": "1c08fa80-eaf2-4548-8c27-70c82fac79ea" }, "outputs": [ { "data": { "text/plain": [ "'Last Price: $124.7001'" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "['2024-08-23', '2024-08-30', '2024-09-06']" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Get the options chains data.\n", "\n", "symbol = \"NVDA\" # This will not be evergreen, change the symbol based on a stock above.\n", "\n", "obb.user.preferences.output_type = \"OBBject\" # To use the built-in options chains methods, we need to set the output type to OBBject.\n", "\n", "options = obb.derivatives.options.chains(symbol, provider=\"cboe\")\n", "\n", "last_price = options.results.underlying_price[0]\n", "\n", "display(f\"Last Price: ${last_price}\")\n", "\n", "display(options.results.expirations[:3])" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cost of Straddle: $14.65\n", "Cost as a % of Share Price: 11.7482%\n", "Upper Breakeven Price: $139.65\n", "Lower Breakeven Price: $109.35\n", "Implied Daily Move: 1.3982%\n", "\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Long Straddle
SymbolNVDA
Underlying Price124.7001
Expiration2024-08-30
DTE8
Strike 1125.0
Strike 2124.0
Strike 1 Premium7.55
Strike 2 Premium7.1
Cost14.65
Cost Percent11.7482
Breakeven Upper139.65
Breakeven Upper Percent11.9887
Breakeven Lower109.35
Breakeven Lower Percent-12.3096
Max Profitinf
Max Loss-14.65
Payoff Ratioinf
\n", "
" ], "text/plain": [ " Long Straddle\n", "Symbol NVDA\n", "Underlying Price 124.7001\n", "Expiration 2024-08-30\n", "DTE 8\n", "Strike 1 125.0\n", "Strike 2 124.0\n", "Strike 1 Premium 7.55\n", "Strike 2 Premium 7.1\n", "Cost 14.65\n", "Cost Percent 11.7482\n", "Breakeven Upper 139.65\n", "Breakeven Upper Percent 11.9887\n", "Breakeven Lower 109.35\n", "Breakeven Lower Percent -12.3096\n", "Max Profit inf\n", "Max Loss -14.65\n", "Payoff Ratio inf" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Use the straddle method of the results object to get the straddle data and then calculate the implied move.\n", "\n", "straddle = options.results.straddle(days=options.results.expirations[1])\n", "straddle_price = straddle.loc[\"Cost\"].values[0]\n", "days = straddle.loc[\"DTE\"].values[0]\n", "upper_price = straddle.loc[\"Breakeven Upper\"].values[0]\n", "lower_price = straddle.loc[\"Breakeven Lower\"].values[0]\n", "\n", "implied_move = ((1 + straddle_price / last_price) ** (1 / days) - 1) * 100\n", "\n", "display(\n", " f\"Cost of Straddle: ${round(straddle_price, 2)}\"\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", " f\"\\nImplied Daily Move: {round(implied_move, 4)}%\\n\"\n", ")\n", "\n", "display(straddle)" ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3", "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.12.4" } }, "nbformat": 4, "nbformat_minor": 0 }