{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "01-quickstart-notice",
   "metadata": {},
   "source": [
    "*OptionSpace example notebook. Copyright (c) 2026 Options Universe Inc. (d/b/a OptionSpace). All rights reserved.*\n",
    "\n",
    "*This notebook is part of the OptionSpace documentation. You may run it, and copy and adapt its code into your own programs, only for use with OptionSpace data under your account and the [OptionSpace Terms of Service](https://optionspace.ai/terms). Please do not publish or redistribute this notebook, or use its code with data that does not come from OptionSpace without our written permission. It needs an OptionSpace account and API key. Nothing in it is investment advice.*"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-00",
   "metadata": {},
   "source": [
    "# Quickstart\n",
    "\n",
    "Your first five minutes with OptionSpace from Python: connect with your saved\n",
    "key, see what your plan includes, list the symbols, plot one fitted volatility\n",
    "smile and load one option chain as a pandas DataFrame.\n",
    "\n",
    "**Before you start.** Follow [Getting started](https://optionspace.ai/docs.html#install)\n",
    "once (Windows, macOS or Linux). Then, in a terminal, inside that research folder:\n",
    "\n",
    "```bash\n",
    "uv add notebook\n",
    "uv run jupyter notebook\n",
    "```\n",
    "\n",
    "`uv run optionspace login` (from Getting started) asks for your API key once (the\n",
    "input is hidden) and keeps it in your computer's credential store. The examples use SPY on 10 April 2025;\n",
    "change the inputs in step 4 to any symbol and past session your plan covers."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-01",
   "metadata": {},
   "source": [
    "**Usage.** Your daily allowance is counted in credits. `client.prices()` lists\n",
    "what each call costs, a research call says what it cost in `result['credits']`,\n",
    "and `client.entitlements()` shows what you have used today."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-02",
   "metadata": {},
   "source": [
    "## 1. Connect\n",
    "\n",
    "`osp.Client()` uses the key you saved with `uv run optionspace login`. If\n",
    "you prefer an environment variable, set `OPTIONSPACE_API_KEY` in the terminal\n",
    "you start Jupyter from. **Never paste your key into a notebook cell**: notebooks\n",
    "get shared, and a key in a cell travels with them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-03",
   "metadata": {},
   "outputs": [],
   "source": [
    "import optionspace as osp\n",
    "\n",
    "client = osp.Client()\n",
    "print(\"optionspace\", osp.__version__, \"| key from:\", client.credential_source)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-04",
   "metadata": {},
   "source": [
    "## 2. Check your access\n",
    "\n",
    "`entitlements()` shows your plan, your daily limits and what you have used\n",
    "today."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-05",
   "metadata": {},
   "outputs": [],
   "source": [
    "access = client.entitlements()\n",
    "for field in (\"tier\", \"status\", \"limits\", \"usage\"):\n",
    "    print(f\"{field:>8}: {access.get(field)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-06",
   "metadata": {},
   "source": [
    "## 3. List the symbols\n",
    "\n",
    "One row per symbol, with the first and last session it covers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-07",
   "metadata": {},
   "outputs": [],
   "source": [
    "symbols = client.symbols()\n",
    "print(len(symbols), \"symbols\")\n",
    "symbols.head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-08",
   "metadata": {},
   "source": [
    "## 4. Fetch one fitted smile\n",
    "\n",
    "Pick a symbol, a past session and a listed expiry. `expirations()` lists the\n",
    "expiries that were trading that day, so you never have to guess one.\n",
    "`snapshot=\"EOD\"` asks for the last snapshot at or before the close; the time it\n",
    "resolved to comes back with the data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-09",
   "metadata": {},
   "outputs": [],
   "source": [
    "SYMBOL, DATE, EXPIRY = \"SPY\", \"2025-04-10\", \"2025-04-17\"\n",
    "\n",
    "client.expirations(SYMBOL, DATE).head(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-10",
   "metadata": {},
   "outputs": [],
   "source": [
    "smile = client.smile(SYMBOL, DATE, expiration=EXPIRY, snapshot=\"EOD\")\n",
    "\n",
    "summary = {k: smile.attrs.get(k) for k in (\"symbol\", \"data_date\", \"snapshot_time\", \"expiration\",\n",
    "                                         \"dte\", \"forward\", \"atm_vol\")}\n",
    "print(summary)\n",
    "columns = [c for c in (\"strike\", \"put_call\", \"fitted_vol\", \"iv_bid\", \"iv_ask\", \"delta\",\n",
    "                       \"is_wing_extrapolated\") if c in smile.columns]\n",
    "smile[columns].head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-11",
   "metadata": {},
   "source": [
    "Volatilities are decimals: `0.20` means 20%. `is_wing_extrapolated` is `True`\n",
    "where a strike lies outside the range the fit was made on, so the value there\n",
    "is an extension of the curve rather than a fit to quotes.\n",
    "\n",
    "## 5. Plot it\n",
    "\n",
    "`charts.smile_chart` draws exactly what the API returned: the fitted curve,\n",
    "the bid and ask volatilities at each strike, and where the curve is extended\n",
    "beyond the fitted range. Redrawing a chart makes no new request."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-12",
   "metadata": {},
   "outputs": [],
   "source": [
    "from optionspace import charts\n",
    "\n",
    "fig = charts.smile_chart(smile)\n",
    "fig.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-13",
   "metadata": {},
   "source": [
    "To keep a copy you can open later in any browser:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-14",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig.write_html(\"spy-smile.html\", include_plotlyjs=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-15",
   "metadata": {},
   "source": [
    "## 6. Load one option chain as a DataFrame\n",
    "\n",
    "`chain()` returns every fitted option at one snapshot. Filtering to one expiry\n",
    "keeps this first pull small; drop `expiration=` for the whole chain (notebook 2\n",
    "does that)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-16",
   "metadata": {},
   "outputs": [],
   "source": [
    "chain = client.chain(SYMBOL, DATE, \"EOD\", expiration=EXPIRY)\n",
    "print(chain.shape, \"| snapshot\", chain.attrs.get(\"snapshot_time\"))\n",
    "chain.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01-quickstart-17",
   "metadata": {},
   "outputs": [],
   "source": [
    "calls = chain[chain[\"put_call\"] == \"call\"]\n",
    "wanted = [\"strike\", \"fitted_vol\", \"fitted_price\", \"delta\", \"gamma\", \"vega\", \"theta_1d\"]\n",
    "calls[[c for c in wanted if c in calls.columns]].head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01-quickstart-18",
   "metadata": {},
   "source": [
    "## Next\n",
    "\n",
    "- Notebook 2: a whole chain, the listed expiries and the term structure on a past date.\n",
    "- Notebook 3: ATM volatility through the day, over several weeks.\n",
    "- Notebook 4: earnings research.\n",
    "\n",
    "Every field is described in the field reference at\n",
    "https://optionspace.ai/docs-api.html#fields. Questions or problems:\n",
    "info@optionspace.ai (never include your API key)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  },
  "optionspace": {
   "requests": "About 5 requests",
   "summary": "Sign in, check your access, list the symbols, plot one fitted smile and load one option chain as a DataFrame.",
   "title": "Quickstart"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
