{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ec244ffc",
   "metadata": {},
   "source": [
    "# Il modello aveva ragione. Ma non abbastanza.\n",
    "## Rischio energetico quando il futuro non assomiglia al passato\n",
    "\n",
    "**Fabio Mencio** · Energy | Data | AI · [fabio-mencio.it](https://fabio-mencio.it)\n",
    "\n",
    "---\n",
    "\n",
    "> Un modello può conoscere molto bene ciò che è già successo.\n",
    "> Ma come può assegnare una probabilità corretta a qualcosa che nei suoi dati\n",
    "> non è mai successo?\n",
    "\n",
    "Questo notebook risponde a una domanda sola:\n",
    "\n",
    "> **Quanto possiamo fidarci di un modello di rischio costruito sul passato,\n",
    "> quando il futuro entra in un regime che il modello non ha mai osservato?**\n",
    "\n",
    "Il soggetto è un'azienda che compra **10 GWh di energia elettrica all'anno**\n",
    "sul mercato italiano. Il momento è il **31 dicembre 2020**: sei anni di prezzi\n",
    "reali in mano e un budget da scrivere per l'anno dopo. Poi si guarda che cosa è\n",
    "successo davvero.\n",
    "\n",
    "### Due distinzioni che reggono tutto il lavoro\n",
    "\n",
    "| | |\n",
    "|---|---|\n",
    "| **Previsione** | che cosa pensiamo possa succedere |\n",
    "| **Gestione del rischio** | che cosa facciamo se ciò che pensiamo non succede |\n",
    "\n",
    "| | |\n",
    "|---|---|\n",
    "| **Calcolare il rischio** | un numero, con le sue ipotesi |\n",
    "| **Gestire il rischio** | decidere quanto dipendere da quel numero |\n",
    "\n",
    "### Come leggere\n",
    "\n",
    "Tredici sezioni, ognuna con la stessa struttura: **domanda, metodo, risultato,\n",
    "cosa significa, limite**. Le sezioni che simulano lo dichiarano, e i loro\n",
    "grafici lo portano scritto dentro l'immagine. Nessuno scenario ha una\n",
    "probabilità attaccata: sono futuri possibili, non previsioni.\n",
    "\n",
    "Le fonti citate nel testo (Kupiec 1995, Christoffersen 1998, Comitato di\n",
    "Basilea 2016, BCE 2022, ESMA 2022, IEA 2022, ACER 2022, Weron 2014) sono\n",
    "elencate con i riferimenti in `research/SOURCES.md`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81758ece",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys, warnings\n",
    "from pathlib import Path\n",
    "warnings.filterwarnings(\"ignore\", message=\"invalid value encountered in log\")\n",
    "sys.path.insert(0, str(Path.cwd().parent))\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import run_analisi as RA\n",
    "from src import config as C, grafici as G\n",
    "\n",
    "G.stile()\n",
    "pd.set_option(\"display.width\", 160, \"display.max_columns\", 30,\n",
    "              \"display.float_format\", lambda x: f\"{x:,.2f}\")\n",
    "print(f\"seme casuale: {C.SEME} · volume: {C.VOLUME_ANNO_MWH / 1000:.0f} GWh/anno · simulazioni: {C.N_SIM:,}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b419a56",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 1. La domanda\n",
    "\n",
    "> ### Domanda\n",
    "> **Possiamo prevedere il prossimo shock guardando quelli precedenti?**\n",
    "\n",
    "**Metodo.** Nessun calcolo ancora: si guarda la serie e si fissano le regole del gioco."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef9388ce",
   "metadata": {},
   "source": [
    "**Risultato.** Possiamo stimare ciò che è coerente con i dati osservati. Non\n",
    "possiamo presumere che il prossimo regime sia già contenuto nel dataset.\n",
    "\n",
    "Un modello impara, in sostanza, P(futuro | passato). Nel farlo assume che almeno\n",
    "parte della struttura che ha generato il passato continui a valere: la stessa\n",
    "volatilità, le stesse relazioni fra gas, domanda e prezzo, lo stesso\n",
    "comportamento degli operatori. Nei mercati energetici quella struttura può\n",
    "cambiare per ragioni che nessuna serie storica contiene: una guerra, un taglio\n",
    "delle forniture, un inverno anomalo, un intervento regolatorio, una crisi di\n",
    "liquidità. La letteratura sulla previsione dei prezzi elettrici (Weron, 2014)\n",
    "tratta i salti di regime come una caratteristica strutturale di questi mercati,\n",
    "non come un'anomalia.\n",
    "\n",
    "**Le regole del gioco di questo lavoro:**\n",
    "1. il modello di rischio è calibrato **solo** sui dati fino al 31/12/2020;\n",
    "2. non si prevede nulla: si misura, si stressa, si rovescia la domanda;\n",
    "3. dati reali e simulazioni restano separati e dichiarati;\n",
    "4. dove un'ipotesi iniziale non ha retto, c'è scritto che non ha retto."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "499b52ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "D = RA.passo_1_dati()\n",
    "dati = D[\"dati\"]\n",
    "D[\"descrizione\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1d7bdad",
   "metadata": {},
   "outputs": [],
   "source": [
    "for nota in D[\"note\"]:\n",
    "    print(\"-\", nota)\n",
    "v = D[\"validazione\"]\n",
    "p = v[\"mese_peggiore\"]\n",
    "print(f\"\\nScarto massimo fra la serie usata (Ember) e il PUN Index GME: \"\n",
    "      f\"{p['scarto']:+.1f} EUR/MWh a {p['mese']}. Le due serie coincidono fino al 2024.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ac636e61",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "La serie dei prezzi è distribuita da Ember e proviene da ENTSO-E: è il prezzo\n",
    "day-ahead medio giornaliero ponderato sul carico. **Non è** il PUN Index GME con\n",
    "cui si regolano i contratti indicizzati italiani, dal quale diverge dal 2025\n",
    "(fino a 20,8 €/MWh in un mese). Le conclusioni valgono per il prezzo di\n",
    "mercato. Il profilo di consumo è piatto (un dodicesimo al mese): un consumatore\n",
    "reale paga di più perché consuma nelle ore care; i livelli sono una sottostima,\n",
    "i confronti no."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca587bfb",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 2. Dati e regimi\n",
    "\n",
    "> ### Domanda\n",
    "> **Il mercato è rimasto lo stesso nel periodo osservato?**\n",
    "\n",
    "**Metodo.** Segmentazione a calendario su fatti noti, controllata con un rilevatore automatico di rottura strutturale (binary segmentation sul logaritmo del prezzo mensile) e con un test di distribuzione fra il 2015-2020 e il 2022."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23efc114",
   "metadata": {},
   "outputs": [],
   "source": [
    "RG = RA.passo_2_regimi(dati)\n",
    "RG[\"tabella\"].round(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fcb42705",
   "metadata": {},
   "outputs": [],
   "source": [
    "for r in RG[\"rotture\"]:\n",
    "    print(f\"rottura a {r['mese']}: media {r['media_prima']:.0f} -> {r['media_dopo']:.0f} EUR/MWh, \"\n",
    "          f\"riduzione della varianza {r['riduzione_sse_pct']:.0f}%\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "daaba1c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.q01_regimi({\"dati\": D, \"regimi\": RG})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1265dcca",
   "metadata": {},
   "source": [
    "![](../charts/q01_regimi.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0cce461a",
   "metadata": {},
   "outputs": [],
   "source": [
    "o = RG[\"stessa_distribuzione_2022\"]\n",
    "print(\"IL 2022 VIENE DALLA STESSA DISTRIBUZIONE DEL 2015-2020?\")\n",
    "print(f\"  sui LIVELLI: massimo mensile 2015-2020 = {o['massimo_livello_calibrazione']:.0f}, \"\n",
    "      f\"minimo 2022 = {o['minimo_livello_prova']:.0f}; mesi 2022 sopra il massimo storico: \"\n",
    "      f\"{o['mesi_prova_sopra_massimo_storico']}/{o['mesi_prova']}; z del livello medio = {o['z_livello_medio']:.0f}\")\n",
    "print(f\"  sulle VARIAZIONI mensili: Kolmogorov-Smirnov D = {o['ks_variazioni_D']:.2f}, p = {o['ks_variazioni_p']:.2f} \"\n",
    "      f\"-> {'distinguibili' if o['variazioni_distinguibili'] else 'NON distinguibili'}\")\n",
    "print(f\"  deviazione standard delle variazioni: {o['sd_variazioni_calibrazione_pct']:.0f}% -> {o['sd_variazioni_prova_pct']:.0f}%\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "196c318f",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.q04_livelli_vs_variazioni({\"dati\": D, \"regimi\": RG})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cef542d",
   "metadata": {},
   "source": [
    "![](../charts/q04_livelli_vs_variazioni.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16afb1f9",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Il rilevatore automatico mette due rotture: **luglio 2021** (la media passa da\n",
    "50 a 149 €/MWh) e **febbraio 2023** (da 238 a 121). Non coincidono con il\n",
    "calendario: la crisi, nei dati, comincia sei mesi prima dell'invasione, con la\n",
    "salita del gas dell'estate 2021. È coerente con la ricostruzione di ACER, che\n",
    "colloca l'inizio del rincaro del gas nel 2021 (ripresa post-Covid, scarsa\n",
    "produzione idro e rinnovabile, incertezza sulle forniture russe) e\n",
    "l'escalation nel 2022.\n",
    "\n",
    "Il controllo «stessa distribuzione?» dà due risposte diverse, e sono entrambe\n",
    "giuste. **Sui livelli** il 2022 è un altro mondo: tutti e dodici i mesi stanno\n",
    "sopra il massimo mai visto nei sei anni di calibrazione, a 23 deviazioni\n",
    "standard dalla media. **Sulle variazioni mensili**, che sono ciò su cui il\n",
    "modello è calibrato, con dodici osservazioni il test non riesce a dire che il\n",
    "2022 sia diverso (p = 0,19). La deviazione standard è passata dal 14% al 33%, ma\n",
    "dodici mesi non bastano a provarlo.\n",
    "\n",
    "È il cuore di tutto quello che segue: **il modello guardava le variazioni, e\n",
    "sulle variazioni non ha sbagliato molto. È cambiato il livello, e il livello è\n",
    "quello che si paga.** Il termine «fuori distribuzione» qui è appropriato per i\n",
    "livelli, non per le variazioni."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6031243",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Il rilevatore di rotture è il più elementare che esista, e con 141 mesi un\n",
    "metodo più raffinato troverebbe quello che gli si chiede. La soglia del 10% di\n",
    "riduzione della varianza per accettare una rottura è una scelta. Il test KS\n",
    "sulle variazioni ha pochissima potenza con 12 osservazioni: «non distinguibili»\n",
    "non vuol dire «uguali»."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7133c52",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 3. Che cosa sapeva il modello il 31 dicembre 2020\n",
    "\n",
    "> ### Domanda\n",
    "> **Che cosa avrebbe previsto il nostro modello prima della crisi?**\n",
    "\n",
    "**Metodo.** Bootstrap dei rendimenti mensili 2015-2020: 50.000 anni possibili, dodici mesi ciascuno, a partire dal prezzo di dicembre 2020. Nessun dato successivo entra nella stima."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af000f88",
   "metadata": {},
   "source": [
    "Prima dei numeri, la tabella che rende visibile il vincolo. Tutto ciò che sta\n",
    "nella terza colonna **non entra** nella stima fatta alla data della riga."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "351a02f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "RG[\"informazioni\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "93d8d93a",
   "metadata": {},
   "outputs": [],
   "source": [
    "MO = RA.passo_3_modello_2020(dati)\n",
    "rif = MO[\"riferimento\"]\n",
    "m = MO[\"metriche\"]\n",
    "print(f\"data della decisione: {rif['data_decisione']:%d/%m/%Y}\")\n",
    "print(f\"mesi di storia usati: {rif['osservazioni_stima']}  (2015-01 / 2020-12)\")\n",
    "print(f\"prezzo di partenza (dicembre 2020): {rif['prezzo_ultimo']:.2f} EUR/MWh\")\n",
    "print(f\"budget a quel prezzo, 10 GWh: {rif['budget_eur']:,.0f} EUR\")\n",
    "print()\n",
    "for etichetta, k_eur, k_pct in [(\"costo mediano\", \"mediana_eur\", \"mediana_pct\"),\n",
    "                                (\"VaR 95%\", \"var95_eur\", \"var95_pct\"),\n",
    "                                (\"VaR 99%\", \"var99_eur\", \"var99_pct\"),\n",
    "                                (\"Expected Shortfall 99%\", \"es99_eur\", \"es99_pct\"),\n",
    "                                (\"peggiore di 50.000 simulazioni\", \"peggiore_eur\", \"peggiore_pct\")]:\n",
    "    print(f\"  {etichetta:32s} {m[k_eur]:11,.0f} EUR  ({m[k_pct]:+6.1f}% sul budget)\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f3cd130",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.q02_modello_2020({\"modello\": MO})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "607f13f7",
   "metadata": {},
   "source": [
    "![](../charts/q02_modello_2020.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "404c16e5",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Il 31 dicembre 2020 il modello diceva: *nel 99% degli anni possibili il costo\n",
    "resta sotto 1,13 milioni di euro*, contro un budget di 541 mila. **Non era una\n",
    "previsione rassicurante**: diceva che il costo poteva raddoppiare. Per una\n",
    "materia prima volatile come l'energia elettrica era una risposta seria, e\n",
    "coerente con sei anni di dati reali.\n",
    "\n",
    "La domanda del lavoro non è se questo numero fosse «giusto». È che cosa\n",
    "contiene e che cosa no."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18b5c17b",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Il bootstrap estrae i mesi a caso con reinserimento: cancella il\n",
    "raggruppamento della volatilità e le salite che durano. La versione a blocchi\n",
    "di tre mesi, che conserva la persistenza, dà numeri simili (tabella in\n",
    "`outputs/tabelle/`). Il prezzo di partenza è il mese di dicembre 2020, non il\n",
    "forward Cal-21 che un ufficio acquisti avrebbe usato: quel dato non è pubblico.\n",
    "Il budget e la simulazione partono dallo stesso prezzo, quindi le percentuali\n",
    "«sul budget» misurano solo ciò che accade dopo."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2393ef3",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 4. Il Value at Risk\n",
    "\n",
    "> ### Domanda\n",
    "> **Che cosa dice davvero «VaR 99% = 1,13 milioni»?**\n",
    "\n",
    "**Metodo.** Lo stesso modello della sezione 3. Qui si legge il numero con cura."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "453e2a0d",
   "metadata": {},
   "source": [
    "**Risultato.** «VaR 99% = 1,13 milioni di euro» **non** significa «non pagherò\n",
    "mai più di 1,13 milioni». Significa:\n",
    "\n",
    "> *Secondo questo modello e le sue ipotesi, il 99% degli esiti considerati\n",
    "> resta entro quella soglia.*\n",
    "\n",
    "Restano due domande che il numero non contiene:\n",
    "\n",
    "1. **Che cosa succede nell'1% rimanente?** Il VaR è un quantile: dice dove\n",
    "   comincia la coda, non quanto è profonda.\n",
    "2. **Che cosa succede se la distribuzione futura non è quella stimata sul\n",
    "   passato?** Il VaR è condizionato alle ipotesi. Se le ipotesi cambiano, il\n",
    "   numero non è «sbagliato»: è la risposta a una domanda diversa da quella che\n",
    "   il futuro ha posto.\n",
    "\n",
    "Due controlli sul campione di calibrazione, per capire che cosa il modello\n",
    "poteva e non poteva sapere:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bcc0dd52",
   "metadata": {},
   "outputs": [],
   "source": [
    "mm = MO[\"mensile\"]\n",
    "print(f\"VaR 99% mensile, storico:   {mm['var99_pct']:+.1f}%\")\n",
    "print(f\"VaR 99% mensile, normale:   {mm['var99_normale_pct']:+.1f}%\")\n",
    "print(f\"Jarque-Bera sui mesi 2015-2020: p = {mm['code']['jarque_bera_p']:.2f} -> la normale NON viene rifiutata\")\n",
    "print(f\"curtosi in eccesso: {mm['code']['curtosi_eccesso']:+.2f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d440e27",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Nel campione tranquillo **non c'era nessun segnale di code grasse**: il VaR\n",
    "storico e quello normale danno quasi lo stesso numero, e il test di normalità\n",
    "non rifiuta. Chi avesse scelto una distribuzione a code pesanti nel 2020 lo\n",
    "avrebbe fatto per convinzione, non per evidenza. È un punto che tornerà nella\n",
    "sezione sul rischio di modello."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c107e0a4",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Il VaR qui è calcolato sul costo annuo di un consumatore, con la coda avversa\n",
    "in alto (il prezzo che sale). Confrontarlo con un VaR azionario, che guarda la\n",
    "coda in basso, senza accorgersi del ribaltamento è l'errore più facile."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06668922",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 5. Poi è arrivato il 2022\n",
    "\n",
    "> ### Domanda\n",
    "> **Quanto era improbabile il 2022 secondo il modello?**\n",
    "\n",
    "**Metodo.** Si prende il costo reale di ogni anno, con lo stesso volume e profilo, e si cerca dove cade nella distribuzione stimata nel 2020."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2356f682",
   "metadata": {},
   "outputs": [],
   "source": [
    "MO[\"confronto\"].round(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac427d8e",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.q03_2022_fuori({\"modello\": MO})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "309f8918",
   "metadata": {},
   "source": [
    "![](../charts/q03_2022_fuori.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe0885c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "conf = MO[\"confronto\"]\n",
    "r22 = conf.loc[2022, \"costo effettivo EUR\"]; r21 = conf.loc[2021, \"costo effettivo EUR\"]\n",
    "print(f\"2021: {r21:,.0f} EUR -> percentile {conf.loc[2021, 'percentile nella distribuzione stimata']:.1f} \"\n",
    "      f\"della distribuzione; {r21 / m['es99_eur']:.2f} volte l'Expected Shortfall 99%\")\n",
    "print(f\"2022: {r22:,.0f} EUR -> percentile {conf.loc[2022, 'percentile nella distribuzione stimata']:.1f}; \"\n",
    "      f\"{r22 / rif['budget_eur']:.1f} volte il budget, {r22 / m['var99_eur']:.1f} volte il VaR 99%, \"\n",
    "      f\"{r22 / m['peggiore_eur']:.1f} volte la PEGGIORE delle 50.000 simulazioni\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0940f3ad",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Il costo del 2022 è stato **3,03 milioni di euro: 5,6 volte il budget, 2,7\n",
    "volte il VaR 99% e 1,5 volte la peggiore delle 50.000 simulazioni**. Non è un\n",
    "evento che il modello giudicava improbabile: è un evento che questo modello\n",
    "collocava **oltre l'estremo della distribuzione simulata**. Zero simulazioni su\n",
    "cinquantamila.\n",
    "\n",
    "Il 2021 racconta la cosa più sottile: 1,25 milioni, al percentile 99,6. Il VaR\n",
    "99% lo sottostimava, l'Expected Shortfall 99% (1,27 milioni) lo ha quasi\n",
    "centrato. Per il primo anno guardare dentro la coda ha aggiunto informazione\n",
    "vera. Per il secondo non è bastato: la distribuzione intera si era spostata."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "175a91ad",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Il confronto è fra un costo stimato a dodici mesi e costi realizzati su anni\n",
    "solari: le finestre non coincidono. Il 2026 è su nove mesi riportati a dodici.\n",
    "I cinque anni «oltre il VaR 99%» non sono cinque eventi all'1%: sono un solo\n",
    "cambio di livello osservato cinque volte."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4831b226",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 6. Quindi il modello era sbagliato?\n",
    "\n",
    "> ### Domanda\n",
    "> **Il modello ha sbagliato, o è cambiato il processo che generava i dati?**\n",
    "\n",
    "**Metodo.** Si confrontano le relazioni stimate nel regime normale con quelle stimate nella crisi: il coefficiente con cui il prezzo elettrico segue il gas, e le correlazioni fra mercati."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec8aa69b",
   "metadata": {},
   "outputs": [],
   "source": [
    "REL = RA.passo_5_relazioni(dati)\n",
    "pd.DataFrame({\"regime normale (dal 2023)\": REL[\"calibrazione_normale\"].riassunto(),\n",
    "              \"crisi (lug 2021 - gen 2023)\": REL[\"calibrazione_tesa\"].riassunto()})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5333d4e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.s01_passaggio_gas({\"relazioni\": REL})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50367a59",
   "metadata": {},
   "source": [
    "![](../charts/s01_passaggio_gas.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ba8fbc0",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "**Non necessariamente.** Il modello può aver rappresentato correttamente il\n",
    "regime su cui era calibrato. Il problema può essere che è cambiato il processo\n",
    "che generava i dati, e i numeri qui sopra dicono che è successo.\n",
    "\n",
    "Il coefficiente con cui il prezzo elettrico segue il gas è passato da **0,71 a\n",
    "0,85**, e l'R² da 0,79 a **0,98**: durante la crisi il modello spiegava il\n",
    "prezzo *meglio*, ma con un coefficiente diverso. Il mondo non era diventato\n",
    "più casuale: era diventato un mondo in cui il gas comandava quasi tutto. È\n",
    "esattamente il meccanismo descritto da IEA e ACER: il gas fissa il prezzo\n",
    "marginale dell'elettricità, quindi quando il gas rincara l'elettricità rincara,\n",
    "e in crisi lo fa con più forza.\n",
    "\n",
    "Le correlazioni fra mercati fanno lo stesso, ma in direzioni opposte:\n",
    "Italia-Germania sale da 0,64 a 0,90, Italia-Spagna **crolla da 0,80 a 0,28**\n",
    "(il price cap iberico dal giugno 2022). Una matrice di correlazione stimata nel\n",
    "2020 non conteneva nessuno dei due numeri.\n",
    "\n",
    "**Questa distinzione è fondamentale per quello che si fa dopo.** Un modello\n",
    "sbagliato si corregge. Un processo che cambia non si corregge: si gestisce."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1356b22a",
   "metadata": {},
   "source": [
    "### Una parentesi: correlazione, causalità e il termometro\n",
    "\n",
    "La catena «fa freddo → serve energia → il prezzo sale» sembra ovvia. Misurata,\n",
    "la correlazione lineare fra temperatura e prezzo è quasi zero."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e20b53e7",
   "metadata": {},
   "outputs": [],
   "source": [
    "t = REL[\"temperatura\"]\n",
    "print(f\"correlazione lineare temperatura / prezzo (2015-2020): {t['corr_lineare']:+.2f}\")\n",
    "print(f\"correlazione con lo scostamento dai 18 gradi:          {t['corr_scostamento_18']:+.2f}\")\n",
    "for k, v in t[\"per_trimestre\"].items():\n",
    "    print(f\"   {k}: {v['corr']:+.2f}\")\n",
    "G.s04_temperatura({\"relazioni\": REL})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39781284",
   "metadata": {},
   "source": [
    "![](../charts/s04_temperatura.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f9cc60f",
   "metadata": {},
   "source": [
    "La relazione è a U: il prezzo sale col freddo *e* col caldo, e i due pezzi si\n",
    "annullano in una retta. Una correlazione vicina a zero non vuol dire «nessuna\n",
    "relazione»: vuol dire «nessuna relazione lineare». E il legame gas-prezzo a\n",
    "0,995, da solo, non dice chi muove chi: la freccia la mette chi conosce il\n",
    "meccanismo del mercato (il prezzo si forma sull'impianto marginale), non la\n",
    "statistica."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8547b10a",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Il regime di crisi è calibrato su 19 mesi e quello normale su 43: pochi, e una\n",
    "crisi sola. La correlazione sui livelli di serie che salgono insieme è gonfiata\n",
    "dalla tendenza comune; sulle variazioni giornaliere Italia-Germania è quasi\n",
    "ferma (0,39 → 0,40). I due numeri rispondono a domande diverse."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a8d52f2",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 7. Ma il test di Kupiec non lo aveva promosso?\n",
    "\n",
    "> ### Domanda\n",
    "> **Basta contare quante volte il modello sbaglia?**\n",
    "\n",
    "**Metodo.** Backtest del VaR mensile stimato sul 2015-2020 e messo alla prova sul 2021-2026: test di copertura incondizionata (Kupiec, 1995), test di indipendenza e di copertura condizionata (Christoffersen, 1998), più un conto esatto sulla concentrazione degli sfondamenti nella finestra di crisi e la misura della loro dimensione."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "79504974",
   "metadata": {},
   "outputs": [],
   "source": [
    "BT = RA.passo_4_backtest(dati)\n",
    "for livello in [\"var95\", \"var99\"]:\n",
    "    b = BT[livello]\n",
    "    k = b[\"kupiec\"]\n",
    "    print(f\"VaR {b['livello'] * 100:.0f}%  soglia {b['soglia_pct']:+.0f}% in un mese  |  {k['sfondamenti']} sfondamenti su {k['n']} mesi, \"\n",
    "          f\"{k['attesi']:.1f} attesi  |  Kupiec LR = {k['LR']:.2f}, p = {k['p']:.3f} -> \"\n",
    "          f\"{'BOCCIATO' if k['p'] < 0.05 else 'non bocciato'}\")\n",
    "    print(f\"        mesi sfondati: {', '.join(b['mesi_sfondati'])}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f19cc01d",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = BT[\"var95\"]\n",
    "ch = b[\"christoffersen\"]; cc = b[\"condizionata\"]; co = b[\"concentrazione\"]; dm = b[\"dimensione\"]\n",
    "print(\"CHRISTOFFERSEN, indipendenza (VaR 95%)\")\n",
    "print(f\"  transizioni 0->0: {ch['n00']}, 0->1: {ch['n01']}, 1->0: {ch['n10']}, 1->1: {ch['n11']}\")\n",
    "print(f\"  P(sfondamento | mese calmo) = {ch['p_sfondamento_dopo_mese_calmo']:.3f}   \"\n",
    "      f\"P(sfondamento | sfondamento) = {ch['p_sfondamento_dopo_sfondamento']:.3f}\")\n",
    "print(f\"  LR = {ch['LR']:.2f}, p = {ch['p']:.3f}   (potenza bassa: {ch['potenza_bassa']})\")\n",
    "print(f\"COPERTURA CONDIZIONATA: LR = {cc['LR']:.2f}, p = {cc['p']:.3f}\")\n",
    "print()\n",
    "print(\"CONCENTRAZIONE NELLA CRISI (ipergeometrica esatta)\")\n",
    "print(f\"  {co['sfondamenti_in_crisi']} sfondamenti su {co['sfondamenti_totali']} cadono nei {co['mesi_crisi']} mesi di crisi \"\n",
    "      f\"su {co['mesi_totali']}: frequenza {co['frequenza_in_crisi_pct']:.0f}% dentro, {co['frequenza_fuori_crisi_pct']:.0f}% fuori\")\n",
    "print(f\"  probabilita' che accada per caso: {co['p_per_caso']:.4f}  (1 su {co['uno_su']:,.0f})\")\n",
    "print()\n",
    "print(\"DIMENSIONE DEGLI SFONDAMENTI\")\n",
    "print(f\"  eccesso medio oltre la soglia: {dm['eccesso_medio_pct']:.0f} punti; massimo {dm['eccesso_massimo_pct']:.0f} punti \"\n",
    "      f\"({dm['mese_massimo']}, rialzo mensile del {dm['rialzo_massimo_pct']:.0f}%)\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d939d70",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.q05_backtest({\"backtest\": BT})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6132e8ff",
   "metadata": {},
   "source": [
    "![](../charts/q05_backtest.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21e163c9",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "**Al 95% il test di Kupiec non boccia il modello** (5 sfondamenti su 69 mesi,\n",
    "3,5 attesi, p = 0,42). **Al 99% lo boccia** (4 contro 0,7 attesi, p = 0,006).\n",
    "Già questo dice una cosa: la risposta dipende dal livello a cui si fa la\n",
    "domanda, e un backtest serio li riporta entrambi.\n",
    "\n",
    "Ma la cosa importante è che cosa il test di Kupiec **non guarda**. Conta\n",
    "quante volte il modello sbaglia. Non guarda *quando* sbaglia, né *quanto*. I\n",
    "cinque sfondamenti al 95% cadono **tutti** nei 19 mesi di crisi: 26% di\n",
    "frequenza dentro, 0% fuori. Che succeda per caso vale **1 su 967**. Il test di\n",
    "indipendenza di Christoffersen va nella stessa direzione (la probabilità di\n",
    "sfondare dopo uno sfondamento è tre volte quella dopo un mese calmo) ma con\n",
    "cinque eventi non ha potenza, e il suo p = 0,34 non prova nulla in nessuna\n",
    "direzione. Per questo serve anche il conto esatto.\n",
    "\n",
    "E la dimensione: in media il prezzo ha superato la soglia di **18 punti\n",
    "percentuali**, con un massimo di 37 nel luglio 2022. Nessuno dei tre test guarda\n",
    "questo numero.\n",
    "\n",
    "L'esempio costruito in fondo al grafico fa vedere la differenza: dieci errori\n",
    "in dieci anni distribuiti uno all'anno, e dieci errori di fila. Kupiec dà p =\n",
    "1,00 a entrambi. Per un'azienda non sono lo stesso rischio.\n",
    "\n",
    "**Risposta alla domanda: no, non basta contare. Conta anche quando sbaglia,\n",
    "quanto sbaglia, e se gli errori si concentrano proprio quando l'azienda è più\n",
    "vulnerabile.** «Statisticamente non rifiutato» non vuol dire «sicuro»."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb6aeb4c",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Kupiec stesso (1995) avverte che con campioni piccoli i test di verifica hanno\n",
    "poca potenza: 69 mesi sono pochi. I test asintotici (chi quadro) con 4-5 eventi\n",
    "sono indicativi; il conto ipergeometrico è esatto ma dipende da come è\n",
    "definita la finestra di crisi (qui: dal rilevatore automatico, non a mano). La\n",
    "finestra di crisi è una sola."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a3f81c5",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 8. Expected Shortfall\n",
    "\n",
    "> ### Domanda\n",
    "> **Quanto perdiamo quando il VaR viene superato?**\n",
    "\n",
    "**Metodo.** Sulla stessa distribuzione del modello 2020: media dei casi oltre il VaR."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be5dd5a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"VaR 99%:                {m['var99_eur']:11,.0f} EUR   dove comincia l'1% peggiore\")\n",
    "print(f\"Expected Shortfall 99%: {m['es99_eur']:11,.0f} EUR   la media dentro quell'1%\")\n",
    "print(f\"differenza:             {m['es99_eur'] - m['var99_eur']:11,.0f} EUR   ({(m['es99_eur'] / m['var99_eur'] - 1) * 100:.0f}%)\")\n",
    "print(f\"costo reale 2021:       {r21:11,.0f} EUR   ({r21 / m['es99_eur']:.2f} volte l'ES 99%)\")\n",
    "G.q06_expected_shortfall({\"modello\": MO})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35e13458",
   "metadata": {},
   "source": [
    "![](../charts/q06_expected_shortfall.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d9d2ece",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Il VaR risponde a «dove finisce la zona normale?». L'Expected Shortfall\n",
    "risponde a «se ne usciamo, quanto male va in media?». Nel modello 2020 la\n",
    "seconda risposta è del 12% più alta della prima. Nel 2021 l'ES 99% ha quasi\n",
    "centrato il costo reale (1,27 contro 1,25 milioni).\n",
    "\n",
    "Che il problema sia riconosciuto anche fuori dall'energia lo dice la\n",
    "regolamentazione bancaria: con la revisione del portafoglio di negoziazione\n",
    "(FRTB, Comitato di Basilea, gennaio 2016) il requisito di capitale per il\n",
    "rischio di mercato è passato dal VaR al 99% all'Expected Shortfall al 97,5%,\n",
    "proprio perché il VaR non cattura la severità oltre il quantile. Yamai e Yoshiba\n",
    "(2005) mostrano che sotto stress l'ES soffre meno del VaR nel trascurare code\n",
    "grasse e dipendenza di coda. Questo non è un progetto bancario: il riferimento\n",
    "serve a dire che la domanda «quanto pesa la coda?» non è un dettaglio accademico.\n",
    "\n",
    "Ma anche l'ES vive dentro la distribuzione stimata. Nel 2022 ha sbagliato\n",
    "quanto il VaR: **guardare più a fondo nella coda aiuta, se la coda è quella\n",
    "giusta.**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73c991d0",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "L'ES è stimato su una coda fatta ricombinando pochi mesi cattivi del 2015-2020:\n",
    "il bootstrap non inventa un mese peggiore di quelli che ha visto."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cff76f0b",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 9. Stress test e scenari\n",
    "\n",
    "> ### Domanda\n",
    "> **E se il prossimo shock non fosse nel dataset?**\n",
    "\n",
    "**Metodo.** Cinque scenari simulati con il modello strutturale (prezzo elettrico = beta·gas + beta·domanda + residuo, coefficienti stimati sui mesi reali) più uno scenario storico: i dodici mesi dopo il break di luglio 2021, riproporzionati al livello di oggi. Nessuno ha una probabilità."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6f7776b",
   "metadata": {},
   "source": [
    "> **Da qui i percorsi sono SIMULATI.** I parametri sono misurati sui dati\n",
    "> reali; i futuri no.\n",
    "\n",
    "Il meccanismo che si simula è quello ricostruito da IEA, ACER e BCE per il\n",
    "2022: shock sul gas → cambia l'economia della generazione marginale → sale il\n",
    "prezzo elettrico → sale il costo dell'energia → sale la volatilità → salgono i\n",
    "margini sulle coperture → serve più liquidità. Le prime quattro frecce stanno\n",
    "in questa sezione; le ultime due nella sezione 11."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0a46ba33",
   "metadata": {},
   "outputs": [],
   "source": [
    "ST = RA.passo_6_stress(dati, REL)\n",
    "print(f\"livello di partenza (media ultimi 3 mesi): {ST['prezzo_iniziale']:.1f} EUR/MWh -> budget {ST['budget']:,.0f} EUR\")\n",
    "for k, s in ST[\"definizioni\"].items():\n",
    "    print(f\"  {s['nome']:40s} {s['origine']}\")\n",
    "rp = ST[\"replay\"]\n",
    "print(f\"  {rp['nome']:40s} {rp['origine']}\")\n",
    "print(f\"     finestra {rp['finestra']}, prezzo prima del break {rp['prezzo_pre_break']:.0f}, rapporto medio x{rp['rapporto_medio']:.2f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f900671a",
   "metadata": {},
   "outputs": [],
   "source": [
    "ST[\"tabella\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d21bff35",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.q07_stress({\"stress\": ST})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2437d80",
   "metadata": {},
   "source": [
    "![](../charts/q07_stress.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57b50105",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Lo stesso contratto, sei futuri. Un raddoppio del gas porta il costo mediano a\n",
    "+33%; un gas ×4 a +79%; lo stesso ×4 **con i coefficienti della crisi** a\n",
    "+103%: un quarto del rischio, in quello scenario, non sta nello shock ma nel\n",
    "fatto che il sistema reagisce di più. La domanda, da sola, pesa poco (+2 punti\n",
    "sul gas ×2).\n",
    "\n",
    "**Lo scenario storico è il peggiore di tutti: +154%.** I dodici mesi dopo il\n",
    "break di luglio 2021, rigiocati dal livello di oggi, costano 4,6 milioni contro\n",
    "1,8 di budget. Non è una simulazione: è successo. È il dato «più fastidioso»\n",
    "del dataset, e per un risk manager è quello da cui imparare di più, non quello\n",
    "da togliere."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e583588",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Le intensità degli scenari sono scelte, con l'origine dichiarata, ma restano\n",
    "scelte. I residui sono normali e indipendenti. Lo scenario storico dipende dal\n",
    "mese da cui si parte: rigiocare il 2022 solare da dicembre 2021 darebbe +8%,\n",
    "perché a dicembre 2021 il prezzo era già a 281. Si è scelto il break perché è\n",
    "lì che i dati dicono che la salita comincia, e la scelta è dichiarata."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddb0e82a",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 10. Reverse stress test\n",
    "\n",
    "> ### Domanda\n",
    "> **Che cosa deve succedere perché il costo superi il doppio del budget?**\n",
    "\n",
    "**Metodo.** Si parte dalla soglia e si risale: che probabilità le assegnava il modello 2020, che rialzo del prezzo elettrico richiede, e quale multiplo del prezzo del gas lo produce con il passaggio gas→elettrico stimato (0,71 normale, 0,85 in crisi)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c06d7f52",
   "metadata": {},
   "outputs": [],
   "source": [
    "RV = RA.passo_7_reverse(dati, MO, REL)\n",
    "RV[\"soglie\"].round(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4fefdc0b",
   "metadata": {},
   "outputs": [],
   "source": [
    "RV[\"percorso\"].round(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e68b014e",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"gas PSV: gennaio 2021 = {RV['gas_2021_01']:.1f} EUR/MWh, media 2022 = {RV['gas_2022_media']:.1f} -> x{RV['gas_osservato_x']:.1f}\")\n",
    "print(f\"il 2022 e' stato {RV['reale_2022_su_budget']:.1f} volte il budget del modello 2020\")\n",
    "G.q08_reverse({\"reverse\": RV})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d04dcfa",
   "metadata": {},
   "source": [
    "![](../charts/q08_reverse.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01419933",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Rovesciare la domanda cambia il tipo di risposta. Non più «quanto è probabile?»\n",
    "ma «che cosa deve succedere?».\n",
    "\n",
    "Per un costo **doppio** del budget serve un rialzo del prezzo elettrico del\n",
    "100%, che con il passaggio normale richiede un gas **×2,7** (×2,3 con i\n",
    "coefficienti di crisi). Il modello del 2020 dava a quell'esito **1 probabilità\n",
    "su 67**. Per un costo **quadruplo**: gas ×7,1, e **zero simulazioni su\n",
    "50.000**. Il gas, fra gennaio 2021 e la media del 2022, è andato **×6,1**. Il\n",
    "costo, ×5,6.\n",
    "\n",
    "La frase da portare via: *un raddoppio del gas non bastava a rompere il\n",
    "budget; ne serviva quasi un triplo; ne è arrivato un sestuplo.* È una\n",
    "risposta che si confronta con la storia, non con una probabilità che nessuno\n",
    "può verificare."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb3e103d",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Il passaggio gas→elettrico è lineare nei logaritmi e stimato su pochi mesi; a\n",
    "multipli grandi l'estrapolazione è grossolana. Le soglie sono espresse sul\n",
    "budget al prezzo di dicembre 2020; con un budget al forward sarebbero diverse."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52495557",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 11. Cosa significa per un'azienda\n",
    "\n",
    "> ### Domanda\n",
    "> **Che cosa cambia per chi compra, vende, copre e deve pagare i margini?**\n",
    "\n",
    "**Metodo.** Due cose misurate sui dati reali: il fabbisogno di cassa di una copertura a termine lungo il percorso dei prezzi 2021-2023, e il costo di tre livelli di copertura nei sei scenari della sezione 9. Più il valore della flessibilità sui prezzi giornalieri."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d52079a0",
   "metadata": {},
   "source": [
    "### Treasury: coperto non vuol dire senza rischio di liquidità\n",
    "\n",
    "Chi si copre con un contratto a termine non paga alla scadenza: paga, o\n",
    "incassa, ogni giorno la differenza fra il prezzo fissato e il mercato, sul\n",
    "volume ancora da consegnare (variation margin). Il contratto ha azzerato il\n",
    "rischio di prezzo; ha creato un rischio di cassa. Nel 2022 ESMA (14 ottobre) e\n",
    "la Commissione europea (18 ottobre) hanno dovuto ampliare temporaneamente il\n",
    "collaterale ammesso dalle controparti centrali proprio per le pressioni di\n",
    "liquidità sulle imprese energetiche; la BCE (FSR, novembre 2022) riporta che i\n",
    "margini iniziali sulle commodity sono circa raddoppiati fra fine 2021 e metà\n",
    "2022.\n",
    "\n",
    "Qui il conto si fa sui prezzi reali, per **entrambi i lati**: il verso del\n",
    "rischio è la cosa che si sbaglia più spesso."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f65444cf",
   "metadata": {},
   "outputs": [],
   "source": [
    "LQ = RA.passo_8_liquidita(dati)\n",
    "c, v = LQ[\"casi\"][\"compratore\"], LQ[\"casi\"][\"venditore\"]\n",
    "print(f\"COMPRATORE coperto ad {c['ingresso']} a {c['prezzo_fissato']:.0f} EUR/MWh (costo coperto {c['costo_coperto']:,.0f} EUR):\")\n",
    "print(f\"  il prezzo scende fino a {c['prezzo_minimo']:.0f}; dopo {c['dopo_mesi']} mesi il contratto vale \"\n",
    "      f\"{c['cassa_da_versare']:,.0f} EUR meno del mercato = {c['pct_del_costo']:.0f}% del costo coperto da versare come margine\")\n",
    "print(f\"VENDITORE coperto a {v['ingresso']} a {v['prezzo_fissato']:.0f} EUR/MWh (ricavo coperto {v['ricavo_coperto']:,.0f} EUR):\")\n",
    "print(f\"  il prezzo sale fino a {v['prezzo_massimo']:.0f}; dopo {v['dopo_mesi']} mesi: {v['cassa_da_versare']:,.0f} EUR \"\n",
    "      f\"= {v['pct_del_ricavo']:.0f}% del ricavo coperto\")\n",
    "G.q09_liquidita({\"liquidita\": LQ})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e10e5f95",
   "metadata": {},
   "source": [
    "![](../charts/q09_liquidita.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f97f4a8",
   "metadata": {},
   "source": [
    "### Procurement e pricing: quanto coprire, e a che prezzo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "15914c70",
   "metadata": {},
   "outputs": [],
   "source": [
    "AZ = RA.passo_9_azienda(dati, ST)\n",
    "(AZ[\"matrice_coperture\"] / 1e6).round(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98a33101",
   "metadata": {},
   "outputs": [],
   "source": [
    "G.q10_coperture({\"azienda\": AZ})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6f22203",
   "metadata": {},
   "source": [
    "![](../charts/q10_coperture.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14d2d58d",
   "metadata": {},
   "outputs": [],
   "source": [
    "(AZ[\"premio\"].pivot_table(index=[\"premio sul fisso\", \"copertura\"], columns=\"scenario\", values=\"costo_atteso\") / 1e6).round(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd876ee4",
   "metadata": {},
   "source": [
    "### Flessibilità e forma del payoff"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef619469",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = AZ[\"legame\"]; s = AZ[\"soglia\"]\n",
    "print(f\"valore della flessibilita' (10% del volume): da {L['valore_peggiore']:,.0f} EUR ({L['anno_peggiore']}) \"\n",
    "      f\"a {L['valore_migliore']:,.0f} EUR ({L['anno_migliore']}): x{L['rapporto_max_min']:.0f}\")\n",
    "print(f\"con una regola decidibile il giorno prima se ne cattura il {AZ['quota_ex_ante_pct']:.0f}%; anni in perdita: {AZ['anni_in_perdita']}\")\n",
    "print(f\"riduzione della pendenza costo/prezzo con 50% coperto + 10% flessibile: {s['riduzione_pendenza_pct']:.0f}%\")\n",
    "print(f\"quota flessibile perche' il costo SCENDA al salire del prezzo: {s['quota_flessibile_necessaria'] * 100:.0f}% del volume -> \"\n",
    "      f\"{'raggiungibile' if s['raggiungibile'] else 'fuori scala'}\")\n",
    "G.s02_flessibilita({\"azienda\": AZ})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d65e4594",
   "metadata": {},
   "source": [
    "![](../charts/s02_flessibilita.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c83cc36",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "**Treasury.** Un compratore che avesse fissato dodici mesi ad agosto 2022\n",
    "(544 €/MWh) avrebbe visto il contratto perdere **3,05 milioni** di valore in\n",
    "due mesi, il **56% del costo coperto**, da versare come margine mentre il\n",
    "prezzo scendeva. Un produttore che avesse venduto a termine a maggio 2022 (230)\n",
    "avrebbe dovuto trovare **2,61 milioni**, il 114% del ricavo coperto, in tre\n",
    "mesi. Entrambi avevano *ragione* sul rischio di prezzo. **Hedged ≠\n",
    "liquidity-risk-free.**\n",
    "\n",
    "**Procurement.** Quanto coprire non è una scelta su quale rischio eliminare: è\n",
    "una scelta su quale rischio tenere. Tutto a mercato costa 1,9 milioni nel caso\n",
    "base e 4,6 nella salita rigiocata; tutto a prezzo fisso costa 1,8 in ogni\n",
    "scenario, ma se il mercato scende non lo vede. E se il fisso costa il 20% più\n",
    "del mercato di oggi, la copertura totale vale 2,18 milioni in ogni scenario e\n",
    "smette di essere la più economica in media.\n",
    "\n",
    "**Pricing e retail.** Chi vende a prezzo fisso per 12 o 24 mesi incorpora un\n",
    "forward, un premio di rischio e un margine di sicurezza: il grafico delle\n",
    "coperture è anche il suo, letto dall'altro lato. Il rischio non finisce alla\n",
    "firma del cliente: restano previsione dei consumi, churn, forma del profilo.\n",
    "\n",
    "**Portfolio.** Le correlazioni della sezione 6 non sono costanti. Un\n",
    "portafoglio costruito sulla matrice del 2020 avrebbe sbagliato sia il legame\n",
    "gas-elettrico sia quello fra mercati.\n",
    "\n",
    "**Flessibilità.** Vale sedici volte di più in un anno agitato, ma con una\n",
    "regola decidibile in diretta se ne cattura il 12%, e nel 2021 la regola ha\n",
    "perso soldi. Riduce la pendenza del costo sul prezzo (del 51% con metà volume\n",
    "coperto), non la rovescia: per un compratore puro servirebbe una quota\n",
    "flessibile del 484%. Cambiare il **segno** del payoff richiede asset, non\n",
    "contratti: generazione propria, accumulo, PPA, capacità di vendere flessibilità.\n",
    "È per questo che la parola «antifragilità», usata nella prima versione di\n",
    "questo lavoro, è stata tolta dal titolo: per chi compra energia la cosa\n",
    "misurabile è la convessità parziale, non il guadagno dallo shock.\n",
    "\n",
    "**Management.** La domanda non è solo «qual è il VaR?», ma: che cosa potrebbe\n",
    "renderlo sbagliato, quanto possiamo perdere oltre, quali scenari non sono nello\n",
    "storico, quanta liquidità serve nello shock, quali variabili stiamo assumendo\n",
    "costanti."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73dfc868",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Il prezzo a termine è approssimato con lo spot del mese d'ingresso: manca un\n",
    "archivio dei forward italiani. Il margine iniziale non è modellato. I contratti\n",
    "reali hanno vincoli di volume, finestre di firma e penali che qui non ci sono.\n",
    "Il valore della flessibilità è lordo. Gli scenari non hanno probabilità, quindi\n",
    "la «media fra scenari» non è un valore atteso."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46077a8d",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 12. Rischio di modello\n",
    "\n",
    "> ### Domanda\n",
    "> **E se il rischio maggiore fosse fidarsi troppo del modello?**\n",
    "\n",
    "**Metodo.** Tre sensibilità, una scelta alla volta: finestra di calibrazione, forma della distribuzione, frequenza dei dati. Per ognuna, VaR 99% e probabilità di superare il doppio del budget."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bbc2ae96",
   "metadata": {},
   "outputs": [],
   "source": [
    "MR = RA.passo_10_model_risk(dati, MO)\n",
    "MR[\"finestra\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "897daec0",
   "metadata": {},
   "outputs": [],
   "source": [
    "MR[\"distribuzione\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "88bbc107",
   "metadata": {},
   "outputs": [],
   "source": [
    "f = MR[\"frequenza\"]\n",
    "print(f\"volatilita' annua dai rendimenti GIORNALIERI (x sqrt 365): {f['vol_annua_da_giornaliera_pct']:.0f}%\")\n",
    "print(f\"volatilita' annua dai rendimenti MENSILI (x sqrt 12):      {f['vol_annua_da_mensile_pct']:.0f}%\")\n",
    "print(f\"rapporto: {f['rapporto']:.1f}   autocorrelazione a 1 giorno: {f['autocorrelazione_1_giorno']:+.2f}\")\n",
    "print(f\"varianza giornaliera spiegata dal giorno della settimana: {MR['ciclo_settimanale']['eta2_pct']:.0f}%\")\n",
    "G.q11_model_risk({\"model_risk\": MR})\n",
    "G.s03_radice_tempo({\"model_risk\": MR})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3003baf",
   "metadata": {},
   "source": [
    "![](../charts/q11_model_risk.png)\n",
    "![](../charts/s03_radice_tempo.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32485bdd",
   "metadata": {},
   "source": [
    "### Cosa significa\n",
    "\n",
    "\n",
    "Cambiando una sola scelta legittima nel dicembre 2020, il **VaR 99% si muove\n",
    "del 14%** (da 1,04 a 1,19 milioni). La **probabilità di superare il doppio del\n",
    "budget si muove del 158%** (da 0,68% a 1,74%). Più si guarda lontano nella\n",
    "coda, più il numero smette di dipendere dai dati e comincia a dipendere da noi.\n",
    "Con la Student-t la peggiore simulazione arriva a 18 milioni: la coda è quasi\n",
    "tutta ipotesi.\n",
    "\n",
    "E la frequenza: la stessa serie, con la convenzione da manuale, dà una\n",
    "volatilità annua del 267% dai giorni e del 48% dai mesi. Non è un errore di\n",
    "calcolo: la regola della radice del tempo presuppone variazioni indipendenti,\n",
    "e il 39% della varianza giornaliera è il giorno della settimana (il lunedì sale,\n",
    "il sabato scende). Un VaR giornaliero su questi prezzi misura il calendario.\n",
    "\n",
    "**Il rischio è nei dati e nelle ipotesi, in proporzione diversa a seconda di\n",
    "dove si guarda.** La parte che dipende dalle ipotesi è l'unica che possiamo\n",
    "scegliere, e va dichiarata."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fdfab6d",
   "metadata": {},
   "source": [
    "### Limite\n",
    "\n",
    "\n",
    "Tre sensibilità non sono un'analisi di model risk completa: mancano, fra le\n",
    "altre, la scelta del profilo di consumo, la proxy del prezzo a termine e\n",
    "l'ipotesi di residui indipendenti. Sono le tre che cambiano di più il numero\n",
    "con meno sforzo."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "029ebf5b",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 13. Conclusioni\n",
    "\n",
    "> ### Domanda\n",
    "> **Quindi i modelli servono oppure no? E qual è il vero obiettivo del risk management?**\n",
    "\n",
    "**Servono.** In questo lavoro il modello del 2020 ha fatto il suo mestiere: ha\n",
    "descritto correttamente il regime su cui era calibrato, ha superato il\n",
    "backtest al 95%, ha quasi centrato il 2021 con l'Expected Shortfall. Non ha\n",
    "visto il 2022 perché il 2022 non era nei suoi dati, e nessuna formula poteva\n",
    "mettercelo. **Il modello aveva ragione. Ma non abbastanza.**\n",
    "\n",
    "Vanno usati come strumenti di decisione, non come oracoli. Un buon sistema di\n",
    "gestione del rischio non cerca un numero capace di prevedere ogni crisi:\n",
    "\n",
    "- usa i **dati storici** per conoscere il comportamento osservato (52 → 303\n",
    "  €/MWh di media: due rotture di regime in otto anni);\n",
    "- usa le **probabilità** per quantificare l'incertezza conosciuta (VaR 99%\n",
    "  1,13 M€, ES 99% 1,27 M€);\n",
    "- usa gli **stress test** per esplorare ciò che lo storico recente non contiene\n",
    "  (gas ×4: +79%; con i coefficienti di crisi: +103%);\n",
    "- usa gli **scenari** per vedere che cosa succede quando più cose cambiano\n",
    "  insieme (la salita rigiocata: +154%);\n",
    "- usa il **reverse stress test** per capire dove l'azienda si rompe (per un\n",
    "  costo doppio serviva gas ×2,7; è arrivato ×6,1);\n",
    "- collega il rischio di mercato al **rischio di liquidità** (fino al 56% del\n",
    "  costo coperto da versare come margine);\n",
    "- e sottopone **le proprie ipotesi** a revisione (una scelta sola cambia la\n",
    "  coda del 158%).\n",
    "\n",
    "**Il vero obiettivo del risk management non è indovinare il futuro. È\n",
    "preparare l'organizzazione a più futuri possibili.** Il modello non deve sapere\n",
    "quale sarà il prossimo shock. Deve aiutare l'azienda a restare in piedi anche\n",
    "quando sbaglia previsione.\n",
    "\n",
    "> Non possiamo sapere quale sarà il prossimo shock.\n",
    "> Possiamo però sapere quanto siamo preparati quando arriverà.\n",
    "\n",
    "---\n",
    "\n",
    "## E quindi, lunedì mattina, cosa cambierei?\n",
    "\n",
    "Cinque azioni, nessuna delle quali richiede un modello nuovo.\n",
    "\n",
    "| azione | perché | metrica | decisione abilitata |\n",
    "|---|---|---|---|\n",
    "| **Affiancare l'Expected Shortfall al VaR** in ogni report di rischio | il VaR dice dove comincia la coda, non quanto pesa; nel 2021 l'ES ha centrato il costo, il VaR no | ES 99% accanto al VaR 99%, in euro | dimensionare la riserva per la coda, non per il bordo |\n",
    "| **Riportare il backtest a tre righe**: frequenza, concentrazione, dimensione | Kupiec al 95% non bocciava un modello sbagliato di 5 volte; tutti gli errori erano nella crisi | sfondamenti attesi/osservati, quota nella finestra di stress, eccesso medio | fermarsi quando gli errori si raggruppano, anche se il conteggio «passa» |\n",
    "| **Uno scenario storico sempre acceso**: la salita 2021-22 rigiocata dal livello di oggi | è il dato più fastidioso del dataset, e il più informativo | costo e cassa nello scenario storico, aggiornati ogni mese | sapere che cosa costerebbe «di nuovo come allora» prima di firmare |\n",
    "| **Un reverse stress test per ogni soglia che conta** (costo ×2, margine azzerato, cassa > X) | «che cosa deve succedere?» si confronta con la storia; «quanto è probabile?» no | multiplo del gas necessario, contro l'ultimo osservato | fissare trigger di copertura e di cassa su grandezze osservabili |\n",
    "| **Collegare copertura e cassa**: ogni hedge ha accanto il suo peggior mark-to-market | coperto non vuol dire senza rischio di liquidità; nel 2022 l'hanno scoperto compratori e venditori | peggior MtM a 12 mesi sul volume coperto, in % del costo | dimensionare linee di credito e collaterale prima dello shock, non durante |\n",
    "\n",
    "E una sesta, che è una regola e non un'azione: **ogni numero di rischio\n",
    "esce con le sue ipotesi scritte accanto**. Finestra, distribuzione,\n",
    "frequenza, proxy. Non per rigore formale: perché il giorno in cui il numero\n",
    "sbaglia, l'unica cosa utile è sapere quale ipotesi è saltata.\n",
    "\n",
    "---\n",
    "\n",
    "## Che cosa non è stato fatto\n",
    "\n",
    "1. **Prezzi forward italiani con data di pubblicazione.** È il dato che manca\n",
    "   davvero: ogni confronto fisso/variabile e ogni calcolo di margine usa una\n",
    "   proxy (lo spot del mese d'ingresso).\n",
    "2. **Dati orari.** La variabilità infragiornaliera, dove la flessibilità vale\n",
    "   davvero, qui non si vede.\n",
    "3. **CO2 (EUA), TTF, disponibilità nucleare francese, idraulicità.** Il canale\n",
    "   del gas è rappresentato dal solo PSV, dal 2021. Gli scenari su nucleare e\n",
    "   siccità, che IEA e ACER indicano fra i driver del 2022, restano qualitativi.\n",
    "4. **Una crisi sola nel campione.** Tutto ciò che si dice sui regimi poggia su\n",
    "   un episodio.\n",
    "5. **Niente volatilità condizionata** (GARCH e simili), né salti.\n",
    "6. **Margine iniziale e costi industriali della flessibilità** non modellati.\n",
    "\n",
    "---\n",
    "\n",
    "*Analisi e simulazione in Python. Dati: Ember (da ENTSO-E), Open-Meteo (ERA5),\n",
    "GME e ARERA tramite il progetto gemello. Fonti in `research/SOURCES.md`.\n",
    "Tutto rifacibile con `python esegui_tutto.py`.*\n",
    "\n",
    "**Fabio Mencio** · Energy | Data | AI · [fabio-mencio.it](https://fabio-mencio.it)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5a85df9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# l'ultima cella scrive i numeri che useranno carosello, report e video:\n",
    "# da qui in poi nessuno di quegli script ricalcola piu' niente\n",
    "R = RA.esegui(verbose=False, grafici=True)\n",
    "print(f\"numeri chiave -> outputs/numeri.json ({len(R['numeri'])} sezioni) · grafici -> charts/\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.13.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
