{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Visualizzazione Interattiva delle Greche\n", "\n", "**Companion notebook per \"Trading con le Opzioni - Strategie Operative\"** \n", "di Pierpaolo Marturano (Core Matrix S.r.l.)\n", "\n", "Questo notebook permette di visualizzare come cambiano le greche al variare di:\n", "- Prezzo del sottostante\n", "- Tempo a scadenza\n", "- Volatilità implicita\n", "\n", "Requisiti: `numpy`, `scipy`, `matplotlib`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from scipy.stats import norm\n", "import matplotlib.pyplot as plt\n", "\n", "# Importa il modulo greche (deve essere nella stessa cartella)\n", "from greche import delta, gamma, theta, vega, vanna, volga, charm, bs_price\n", "\n", "plt.style.use('seaborn-v0_8-whitegrid')\n", "plt.rcParams['figure.dpi'] = 100\n", "plt.rcParams['font.size'] = 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Parametri di Base\n", "\n", "Modifica questi parametri per esplorare diversi scenari:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# === PARAMETRI DA MODIFICARE ===\n", "S = 5500 # Prezzo attuale del sottostante (SPX)\n", "K = 5500 # Strike price\n", "T = 45 / 365 # Tempo a scadenza (45 giorni)\n", "r = 0.045 # Tasso risk-free (4.5%)\n", "sigma = 0.16 # Volatilità implicita (16%)\n", "\n", "print(f\"Sottostante: ${S}\")\n", "print(f\"Strike: ${K}\")\n", "print(f\"DTE: {T*365:.0f} giorni\")\n", "print(f\"IV: {sigma*100:.1f}%\")\n", "print(f\"Risk-free: {r*100:.1f}%\")\n", "print(f\"\\nPrezzo Call: ${bs_price(S, K, T, r, sigma, 'call'):.2f}\")\n", "print(f\"Prezzo Put: ${bs_price(S, K, T, r, sigma, 'put'):.2f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Delta al variare del prezzo del sottostante" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "S_range = np.linspace(S * 0.85, S * 1.15, 200)\n", "\n", "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n", "\n", "# Delta per diverse scadenze\n", "ax = axes[0]\n", "for dte in [7, 21, 45, 90, 180]:\n", " T_i = dte / 365\n", " delta_vals = [delta(s, K, T_i, r, sigma, 'call') for s in S_range]\n", " ax.plot(S_range, delta_vals, linewidth=2, label=f'{dte} DTE')\n", "\n", "ax.axhline(y=0.5, color='gray', linestyle='--', alpha=0.5)\n", "ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", "ax.set_title('Delta Call per Scadenza', fontweight='bold')\n", "ax.set_xlabel('Prezzo Sottostante ($)')\n", "ax.set_ylabel('Delta')\n", "ax.legend()\n", "ax.set_ylim(-0.05, 1.05)\n", "\n", "# Delta per diverse IV\n", "ax = axes[1]\n", "for iv in [0.10, 0.16, 0.25, 0.35, 0.50]:\n", " delta_vals = [delta(s, K, T, r, iv, 'call') for s in S_range]\n", " ax.plot(S_range, delta_vals, linewidth=2, label=f'IV={iv*100:.0f}%')\n", "\n", "ax.axhline(y=0.5, color='gray', linestyle='--', alpha=0.5)\n", "ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", "ax.set_title('Delta Call per Volatilità', fontweight='bold')\n", "ax.set_xlabel('Prezzo Sottostante ($)')\n", "ax.set_ylabel('Delta')\n", "ax.legend()\n", "ax.set_ylim(-0.05, 1.05)\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "print(\"Osservazione: con meno DTE o meno IV, il delta diventa più 'binario' (0 o 1).\")\n", "print(\"Questo spiega perché le 0DTE hanno un gamma esplosivo.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Gamma: dove è massimo?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n", "\n", "# Gamma per diverse scadenze\n", "ax = axes[0]\n", "for dte in [1, 7, 21, 45, 90]:\n", " T_i = dte / 365\n", " gamma_vals = [gamma(s, K, T_i, r, sigma) for s in S_range]\n", " ax.plot(S_range, gamma_vals, linewidth=2, label=f'{dte} DTE')\n", "\n", "ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", "ax.set_title('Gamma per Scadenza', fontweight='bold')\n", "ax.set_xlabel('Prezzo Sottostante ($)')\n", "ax.set_ylabel('Gamma')\n", "ax.legend()\n", "\n", "# Gamma ATM nel tempo\n", "ax = axes[1]\n", "dte_range = np.linspace(1, 90, 200)\n", "gamma_atm = [gamma(S, K, d/365, r, sigma) for d in dte_range]\n", "\n", "ax.plot(dte_range, gamma_atm, linewidth=2.5, color='#ef4444')\n", "ax.set_title('Gamma ATM nel tempo (esplode vicino a scadenza)', fontweight='bold')\n", "ax.set_xlabel('Giorni a Scadenza')\n", "ax.set_ylabel('Gamma')\n", "ax.invert_xaxis()\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "print(f\"Gamma a 45 DTE: {gamma(S, K, 45/365, r, sigma):.6f}\")\n", "print(f\"Gamma a 7 DTE: {gamma(S, K, 7/365, r, sigma):.6f}\")\n", "print(f\"Gamma a 1 DTE: {gamma(S, K, 1/365, r, sigma):.6f}\")\n", "print(f\"\\nIl gamma a 1 DTE è {gamma(S, K, 1/365, r, sigma) / gamma(S, K, 45/365, r, sigma):.1f}x quello a 45 DTE!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Theta: il decadimento temporale" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n", "\n", "# Theta per moneyness\n", "ax = axes[0]\n", "for dte in [7, 21, 45, 90]:\n", " T_i = dte / 365\n", " theta_vals = [theta(s, K, T_i, r, sigma, 'call') for s in S_range]\n", " ax.plot(S_range, theta_vals, linewidth=2, label=f'{dte} DTE')\n", "\n", "ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", "ax.axhline(y=0, color='gray', linestyle='-', alpha=0.3)\n", "ax.set_title('Theta Call per Scadenza ($/giorno)', fontweight='bold')\n", "ax.set_xlabel('Prezzo Sottostante ($)')\n", "ax.set_ylabel('Theta ($/giorno)')\n", "ax.legend()\n", "\n", "# Decadimento del prezzo nel tempo\n", "ax = axes[1]\n", "dte_range = np.linspace(90, 0.5, 200)\n", "prices_time = [bs_price(S, K, d/365, r, sigma, 'call') for d in dte_range]\n", "\n", "ax.plot(dte_range, prices_time, linewidth=2.5, color='#0d5c4d')\n", "ax.fill_between(dte_range, prices_time, alpha=0.1, color='#0d5c4d')\n", "ax.set_title('Prezzo ATM Call nel tempo (theta decay)', fontweight='bold')\n", "ax.set_xlabel('Giorni a Scadenza')\n", "ax.set_ylabel('Prezzo ($)')\n", "ax.invert_xaxis()\n", "\n", "# Evidenzia l'accelerazione negli ultimi 21 giorni\n", "ax.axvline(x=21, color='#ef4444', linestyle='--', alpha=0.7, label='21 DTE')\n", "ax.legend()\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "print(\"Il theta accelera negli ultimi 21 giorni → ecco perché il ciclo 45-21 DTE è ottimale.\")\n", "print(f\"Theta ATM a 45 DTE: ${theta(S, K, 45/365, r, sigma, 'call'):.2f}/giorno\")\n", "print(f\"Theta ATM a 7 DTE: ${theta(S, K, 7/365, r, sigma, 'call'):.2f}/giorno\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Vega: sensibilità alla volatilità" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n", "\n", "# Vega per scadenza\n", "ax = axes[0]\n", "for dte in [7, 21, 45, 90, 180]:\n", " T_i = dte / 365\n", " vega_vals = [vega(s, K, T_i, r, sigma) for s in S_range]\n", " ax.plot(S_range, vega_vals, linewidth=2, label=f'{dte} DTE')\n", "\n", "ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", "ax.set_title('Vega per Scadenza ($/1% IV)', fontweight='bold')\n", "ax.set_xlabel('Prezzo Sottostante ($)')\n", "ax.set_ylabel('Vega ($/1% IV)')\n", "ax.legend()\n", "\n", "# Vega ATM nel tempo\n", "ax = axes[1]\n", "dte_range = np.linspace(1, 180, 200)\n", "vega_time = [vega(S, K, d/365, r, sigma) for d in dte_range]\n", "\n", "ax.plot(dte_range, vega_time, linewidth=2.5, color='#3b82f6')\n", "ax.set_title('Vega ATM nel tempo', fontweight='bold')\n", "ax.set_xlabel('Giorni a Scadenza')\n", "ax.set_ylabel('Vega ($/1% IV)')\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "print(\"Il Vega cresce con la scadenza → le LEAPS sono più sensibili alla IV.\")\n", "print(f\"Vega ATM 7 DTE: ${vega(S, K, 7/365, r, sigma):.2f} per 1% IV\")\n", "print(f\"Vega ATM 45 DTE: ${vega(S, K, 45/365, r, sigma):.2f} per 1% IV\")\n", "print(f\"Vega ATM 180 DTE: ${vega(S, K, 180/365, r, sigma):.2f} per 1% IV\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. Greche di Secondo Ordine: Vanna e Charm" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n", "\n", "# Vanna\n", "ax = axes[0]\n", "for dte in [7, 21, 45, 90]:\n", " T_i = dte / 365\n", " vanna_vals = [vanna(s, K, T_i, r, sigma) for s in S_range]\n", " ax.plot(S_range, vanna_vals, linewidth=2, label=f'{dte} DTE')\n", "\n", "ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", "ax.axhline(y=0, color='gray', linestyle='-', alpha=0.3)\n", "ax.set_title('Vanna (dDelta/dSigma)', fontweight='bold')\n", "ax.set_xlabel('Prezzo Sottostante ($)')\n", "ax.set_ylabel('Vanna')\n", "ax.legend()\n", "\n", "# Charm (delta decay)\n", "ax = axes[1]\n", "for dte in [7, 21, 45, 90]:\n", " T_i = dte / 365\n", " charm_vals = [charm(s, K, T_i, r, sigma, 'call') for s in S_range]\n", " ax.plot(S_range, charm_vals, linewidth=2, label=f'{dte} DTE')\n", "\n", "ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", "ax.axhline(y=0, color='gray', linestyle='-', alpha=0.3)\n", "ax.set_title('Charm (variazione giornaliera del Delta)', fontweight='bold')\n", "ax.set_xlabel('Prezzo Sottostante ($)')\n", "ax.set_ylabel('Charm (/giorno)')\n", "ax.legend()\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "print(\"Vanna: spiega come i flussi dei dealer muovono il mercato vicino a scadenza.\")\n", "print(\"Charm: mostra quanto il delta 'scivola' ogni giorno senza movimento di prezzo.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Dashboard Completa: tutte le greche a colpo d'occhio" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(2, 3, figsize=(16, 10))\n", "fig.suptitle(f'Dashboard Greche — Call {K} Strike, {T*365:.0f} DTE, IV={sigma*100:.0f}%',\n", " fontweight='bold', fontsize=13)\n", "\n", "greeks_funcs = [\n", " ('Delta', lambda s: delta(s, K, T, r, sigma, 'call')),\n", " ('Gamma', lambda s: gamma(s, K, T, r, sigma)),\n", " ('Theta ($/day)', lambda s: theta(s, K, T, r, sigma, 'call')),\n", " ('Vega ($/1%)', lambda s: vega(s, K, T, r, sigma)),\n", " ('Vanna', lambda s: vanna(s, K, T, r, sigma)),\n", " ('Volga', lambda s: volga(s, K, T, r, sigma)),\n", "]\n", "\n", "colors = ['#10b981', '#ef4444', '#f59e0b', '#3b82f6', '#8b5cf6', '#ec4899']\n", "\n", "for ax, (name, func), color in zip(axes.flat, greeks_funcs, colors):\n", " vals = [func(s) for s in S_range]\n", " ax.plot(S_range, vals, linewidth=2, color=color)\n", " ax.axvline(x=K, color='gray', linestyle=':', alpha=0.5)\n", " ax.axhline(y=0, color='gray', linestyle='-', alpha=0.2)\n", " ax.set_title(name, fontweight='bold')\n", " ax.set_xlabel('Prezzo ($)')\n", " ax.grid(True, alpha=0.3)\n", "\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 8. Esercizio: confronta Call e Put\n", "\n", "Modifica il codice qui sotto per confrontare le greche di call e put sullo stesso strike:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ESERCIZIO: prova a cambiare K, T, sigma e osserva come cambia il profilo\n", "K_test = 5500\n", "T_test = 30 / 365\n", "sigma_test = 0.20\n", "\n", "fig, axes = plt.subplots(1, 3, figsize=(15, 4))\n", "\n", "for ax, (name, func_call, func_put) in zip(axes, [\n", " ('Delta', \n", " lambda s: delta(s, K_test, T_test, r, sigma_test, 'call'),\n", " lambda s: delta(s, K_test, T_test, r, sigma_test, 'put')),\n", " ('Theta',\n", " lambda s: theta(s, K_test, T_test, r, sigma_test, 'call'),\n", " lambda s: theta(s, K_test, T_test, r, sigma_test, 'put')),\n", " ('Rho',\n", " lambda s: rho(s, K_test, T_test, r, sigma_test, 'call'),\n", " lambda s: rho(s, K_test, T_test, r, sigma_test, 'put')),\n", "]):\n", " call_vals = [func_call(s) for s in S_range]\n", " put_vals = [func_put(s) for s in S_range]\n", " ax.plot(S_range, call_vals, linewidth=2, label='Call', color='#10b981')\n", " ax.plot(S_range, put_vals, linewidth=2, label='Put', color='#ef4444')\n", " ax.axvline(x=K_test, color='gray', linestyle=':', alpha=0.5)\n", " ax.axhline(y=0, color='gray', linestyle='-', alpha=0.2)\n", " ax.set_title(name, fontweight='bold')\n", " ax.legend()\n", " ax.grid(True, alpha=0.3)\n", "\n", "plt.tight_layout()\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.10.0" } }, "nbformat": 4, "nbformat_minor": 4 }