---
title: "3.4.6 Volatilidad realizada, implícita, VIX y VSTOXX"
description: "El VIX desde la cadena con el método de Cboe, recalculado al céntimo; volatilidad realizada frente a implícita, prima de riesgo de volatilidad y el VSTOXX."
url: "https://pythonparatrading.com/curso-python-trading/nivel-3/volatilidad-realizada-implicita-y-vix/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-3/volatilidad-realizada-implicita-y-vix.png"
---

# 3.4.6 · Volatilidad realizada frente a implícita; prima de riesgo de volatilidad; VIX y VSTOXX

> La volatilidad implícita es un precio y la realizada, un resultado. Entre las dos hay una prima que los vendedores de opciones cobran casi siempre y devuelven de golpe. Esta lección construye desde la cadena de opciones un índice tipo VIX con la fórmula de Cboe, comprueba que coincide con el publicado, mide la prima con datos sintéticos de respuesta conocida y compara la metodología con la del VSTOXX.

- Curso: [Nivel 3: Derivados: futuros, spreads, forex y opciones](https://pythonparatrading.com/curso-python-trading/nivel-3/)
- Módulo: 3.4 · Teoría y valoración de opciones
- Duración: 70 min
- Requisitos: [1.6.1 · Rentabilidades, volatilidad, correlaciones móviles y drawdown](https://pythonparatrading.com/curso-python-trading/nivel-1/volatilidad-correlaciones-y-drawdown/), [3.4.4 · Volatilidad implícita: Newton-Raphson, Brent, py_vollib y QuantLib](https://pythonparatrading.com/curso-python-trading/nivel-3/volatilidad-implicita-newton-brent-py-vollib-y-quantlib/), [3.4.5 · Sonrisa, skew y estructura temporal; superficie de volatilidad con SVI](https://pythonparatrading.com/curso-python-trading/nivel-3/sonrisa-skew-y-superficie-de-volatilidad-svi/)

## Al terminar esta lección

- Calcular un índice de volatilidad a 30 días desde una cadena de opciones con la fórmula del libro blanco de Cboe: forward, K0, selección de strikes, varianza por vencimiento e interpolación.
- Explicar por qué el VIX es la raíz de un swap de varianza y no una volatilidad ATM, y medir la diferencia.
- Medir la volatilidad realizada y la prima de riesgo de volatilidad (implícita menos realizada posterior), con su media, su cola y sus peores episodios.
- Distinguir las metodologías del VIX y del VSTOXX con sus documentos oficiales.

## Dos volatilidades distintas

La palabra «volatilidad» designa dos cosas que conviene no confundir:

- La **volatilidad realizada** es una medida estadística del pasado: la desviación típica anualizada de los
  rendimientos de un periodo ya ocurrido. Con rendimientos logarítmicos diarios $r_t$ y $n$ sesiones,
  $\sigma_{\text{real}} = \sqrt{(252/n)\sum r_t^2}$ (sin restar la media, como en los contratos de varianza). Hay
  estimadores mejores con máximos y mínimos (el research «Estimadores de volatilidad» del sitio los compara), pero el
  de cierre a cierre es el que liquidan los derivados.
- La **volatilidad implícita** es un precio: lo que el mercado de opciones cobra hoy por la volatilidad de un periodo
  futuro (lecciones 3.4.4 y 3.4.5). No es una previsión neutral, porque incluye lo que los compradores pagan por
  protegerse.

La diferencia entre la implícita de hoy y la realizada que llega después es la **prima de riesgo de volatilidad**. Si
es positiva de media, vender volatilidad gana dinero de media; la pregunta es a cambio de qué riesgo. Para medirla
hace falta una implícita a plazo constante, y el estándar del mercado es el **VIX** de Cboe: la volatilidad
implícita a 30 días del S&P 500 calculada con toda la cadena de opciones, no con una sola.

```mermaid
flowchart TB
  O[Opciones OTM] --> V[Varianza a T1 y T2]
  V --> I[Interpolar a 30 d]
  I --> X[VIX = 100 raíz]
  X --> P{Comparar}
  R[Realizada 30 días] --> P
  P --> VRP[Prima de riesgo]
```

## De la cadena al índice: la fórmula de Cboe

El VIX nació en 1993 sobre opciones ATM del S&P 100. En 2003 Cboe, con Goldman Sachs, lo rehízo sobre las opciones del
S&P 500 con la fórmula actual, que no depende de ningún modelo de valoración[^cboe]. La idea es de la teoría de los
swaps de varianza (Demeterfi, Derman, Kamal y Zou, 1999; Carr y Madan, 1998): una cartera de opciones fuera del dinero
con pesos inversamente proporcionales al cuadrado del strike replica la varianza realizada, sea cual sea el nivel del
índice. Su precio, por tanto, es la varianza esperada bajo la medida de valoración. Para un vencimiento $T$:

$$
\sigma^2 = \frac{2}{T}\sum_i \frac{\Delta K_i}{K_i^2}\,e^{RT}\,Q(K_i) - \frac{1}{T}\left(\frac{F}{K_0} - 1\right)^2 .
$$

Cada término tiene su regla en la metodología de Cboe:

| Elemento | Regla |
|---|---|
| $T$ | Tiempo hasta el vencimiento en años de 365 días (en el VIX real, en minutos) |
| $R$ | Tipo libre de riesgo al plazo $T$ (en el VIX real, curva del Tesoro con spline cúbico) |
| $F$ | Forward por la paridad en el strike donde $\lvert C - P \rvert$ es mínimo: $F = K + e^{RT}(C - P)$, con medios |
| $K_0$ | Primer strike igual o inferior a $F$ |
| Opciones | Puts por debajo de $K_0$ y calls por encima, desde $K_0$ hacia fuera; se excluyen las de bid nulo y se para tras dos bids nulos seguidos; en $K_0$, la media de put y call |
| $\Delta K_i$ | Media de la distancia a los strikes vecinos; en los extremos, la distancia al único vecino |
| $Q(K_i)$ | Punto medio del bid y el ask |

Después se interpolan los dos vencimientos a 30 días en varianza total y se pasa a volatilidad:

$$
\text{VIX} = 100\sqrt{\left[T_1\sigma_1^2\,\frac{N_2 - N_{30}}{N_2 - N_1} + T_2\sigma_2^2\,\frac{N_{30} - N_1}{N_2 - N_1}\right]
\frac{N_{365}}{N_{30}}} .
$$

El VIX real usa hoy opciones con más de 23 y menos de 37 días, mensuales y semanales, y cuenta el tiempo en
minutos. El libro blanco de 2009, con solo vencimientos mensuales, tomaba los dos primeros vencimientos con al menos
una semana de vida. Esa versión mensual es la que usa el **VORX**, el índice tipo VIX de los datos del curso sobre el
índice ficticio ORX (`vol3_indices.csv`): los dos primeros vencimientos con al menos 8 días, plazo en días naturales
y tipo interpolado linealmente en la curva de `opciones3_indice.csv`. Su respuesta conocida es que se recalcula
exactamente desde los ficheros publicados.

## El VORX de un día, paso a paso

```python
import math
import numpy as np
import pandas as pd

cad = pd.read_parquet("opciones3_cadena.parquet")
ind = pd.read_csv("opciones3_indice.csv", parse_dates=["fecha"]) \
    .set_index("fecha")
vx = pd.read_csv("vol3_indices.csv", parse_dates=["fecha"]) \
    .set_index("fecha")

ancha = cad.pivot_table(index=["fecha", "vencimiento", "strike"],
                        columns="tipo", values=["bid", "ask"])
ancha.columns = [f"{a}_{t}" for a, t in ancha.columns]
ancha = ancha.dropna().reset_index()   # strikes con call y put

PLAZOS = np.array([1 / 12, 0.25, 0.5, 1.0, 2.0])
CURVA = ["tipo_1m", "tipo_3m", "tipo_6m", "tipo_1a", "tipo_2a"]


def tipo(fecha, T):
    """Tipo continuo a plazo T: interpolación lineal de la curva."""
    return float(np.interp(T, PLAZOS, ind.loc[fecha, CURVA])) / 100


hoy = pd.Timestamp("2025-06-04")
dia = ancha[ancha["fecha"] == hoy]
print({f"{(v - hoy).days} días": len(g)
       for v, g in dia.groupby("vencimiento")})
```
```output
{'16 días': 48, '44 días': 45, '72 días': 40}
```

`pivot_table` deja una fila por strike con el bid y el ask de la call y de la put. Ese día hay tres vencimientos en la
cadena diaria, a 16, 44 y 72 días, con 48, 45 y 40 strikes que tienen las dos patas.

```python
def hasta_dos_ceros(bid):
    """Desde K0 hacia fuera: fuera los bids nulos; se para al
    encontrar dos seguidos."""
    nulo = bid <= 0
    pares = np.flatnonzero(nulo[:-1] & nulo[1:])
    fin = pares[0] if len(pares) else len(bid)
    usar = ~nulo
    usar[fin:] = False
    return usar


def var_cboe(g, T, R, detalle=False):
    K = g["strike"].to_numpy()
    c = ((g["bid_C"] + g["ask_C"]) / 2).to_numpy()
    p = ((g["bid_P"] + g["ask_P"]) / 2).to_numpy()
    j = np.argmin(np.abs(c - p))
    F = K[j] + math.exp(R * T) * (c[j] - p[j])
    i0 = np.flatnonzero(K <= F)[-1]
    ip = np.arange(i0 - 1, -1, -1)       # puts, hacia abajo
    ic = np.arange(i0 + 1, len(K))       # calls, hacia arriba
    ip = ip[hasta_dos_ceros(g["bid_P"].to_numpy()[ip])][::-1]
    ic = ic[hasta_dos_ceros(g["bid_C"].to_numpy()[ic])]
    idx = np.r_[ip, i0, ic]
    Q = np.r_[p[ip], (c[i0] + p[i0]) / 2, c[ic]]
    Ks = K[idx]
    dK = np.gradient(Ks)   # centrado; en los bordes, el vecino
    aporte = 2 / T * dK / Ks ** 2 * Q * math.exp(R * T)
    s2 = aporte.sum() - (F / K[i0] - 1) ** 2 / T
    if detalle:
        return s2, F, K[i0], pd.DataFrame(
            {"strike": Ks, "tipo": ["P"] * len(ip) + ["PC"]
             + ["C"] * len(ic), "Q": Q, "aporte": aporte})
    return s2


for v, g in dia.groupby("vencimiento"):
    n = (v - hoy).days
    T = n / 365
    s2, F, K0, tabla = var_cboe(g, T, tipo(hoy, T), detalle=True)
    puts = tabla.loc[tabla["tipo"] == "P", "aporte"].sum()
    print(f"{n} días: F = {F:.2f}, K0 = {K0:.0f}, "
          f"{len(tabla)} strikes, σ² = {s2:.6f}, "
          f"vol = {100 * math.sqrt(s2):.2f}, "
          f"puts {puts / tabla['aporte'].sum():.0%}")
```
```output
16 días: F = 5143.89, K0 = 5100, 32 strikes, σ² = 0.065072, vol = 25.51, puts 56%
44 días: F = 5155.03, K0 = 5150, 40 strikes, σ² = 0.067723, vol = 26.02, puts 69%
72 días: F = 5166.23, K0 = 5150, 39 strikes, σ² = 0.069099, vol = 26.29, puts 69%
```

Para cada vencimiento, el forward sale de la paridad en el strike con $|C - P|$ mínimo, $K_0$ es el strike justo por
debajo y la selección deja 32, 40 y 39 strikes: en el de 16 días se quedan fuera las alas con bids nulos. Las puts
aportan el 56 %, el 69 % y el 69 % de la varianza; con skew, la parte baja de la sonrisa pesa más (y los pesos
$1/K^2$ la favorecen todavía más). La volatilidad de cada vencimiento, 25,5 %, 26,0 % y 26,3 %, es la de un swap de
varianza a ese plazo, no la ATM: la ATM de 44 días de ese día era del 22,2 % (lección 3.4.5).

```python
def vorx(fecha, grupos):
    """Índice a 30 días con los dos primeros vencimientos de 8 días
    o más (libro blanco de Cboe, versión mensual)."""
    vencs = sorted(v for v in grupos if (v - fecha).days >= 8)[:2]
    n1, n2 = [(v - fecha).days for v in vencs]
    s2 = [var_cboe(grupos[v], n / 365, tipo(fecha, n / 365))
          for v, n in zip(vencs, (n1, n2))]
    w = (n1 / 365 * s2[0] * (n2 - 30) / (n2 - n1)
         + n2 / 365 * s2[1] * (30 - n1) / (n2 - n1))
    return 100 * math.sqrt(max(w * 365 / 30, 0.0))


grupos_hoy = dict(tuple(dia.groupby("vencimiento")))
print(f"VORX calculado: {vorx(hoy, grupos_hoy):.2f}")
print(f"VORX publicado: {vx.loc[hoy, 'vorx']:.2f}")
```
```output
VORX calculado: 25.89
VORX publicado: 25.89
```

Con $N_1 = 16$ y $N_2 = 44$, los 30 días quedan a mitad de camino y los dos vencimientos pesan lo mismo en varianza
total. El resultado, 25,89, coincide con el publicado.

*Fig. — Aporte de cada strike a la varianza del vencimiento de 44 días del VORX, 4 de junio de 2025, en % del total: puts por debajo de K0 y calls por encima.* Barras por strike de 2.400 a 6.200 puntos. Las puts, a la izquierda, aportan el 69 % de la varianza y se extienden hasta 2.400; las calls, a la derecha, el 23 %, en un tramo mucho más corto. El strike K0 = 5.150, destacado, aporta la barra más alta.

La figura descompone la varianza del vencimiento de 44 días por strike. Las puts se extienden hasta 2.400 puntos, un
53 % por debajo del índice, con aportes pequeños pero no despreciables; las calls se acaban mucho antes, porque las
lejanas tienen bid nulo. La barra de $K_0$ es la más alta porque ahí se suman la put y la call (su media) con el peso
de un strike cercano al dinero.

## Doce años recalculados

```python
grupos = {}
for (f, v), g in ancha.groupby(["fecha", "vencimiento"]):
    grupos.setdefault(f, {})[v] = g
calc = pd.Series({f: vorx(f, gv) for f, gv in grupos.items()})
dif = (calc.round(2) - vx["vorx"].reindex(calc.index)).abs()
print(f"{len(calc)} días; diferencia máxima: {dif.max():.3f}")
sin = vx.index.difference(calc.index)
print("Días del índice sin cadena:", [d.date() for d in sin])
```
```output
3017 días; diferencia máxima: 0.000
Días del índice sin cadena: [datetime.date(2019, 7, 23)]
```

Los 3.017 días con cadena dan el VORX publicado al céntimo: es la respuesta conocida del conjunto de datos, y la
prueba de que el código aplica bien cada regla. El único día del índice que falta, el 2019-07-23, es la incidencia
`dia_sin_cadena` de la lección 3.6.4: ese día el proveedor no entregó la cadena y el índice no se puede recalcular.

```python
ver = pd.read_parquet("opciones3_verdad.parquet")


def atm30(g):
    """Vol ATM verdadera a 30 días: θ interpolado, θ(0) = 0."""
    th = np.interp(30 / 365, np.r_[0, g["dias"] / 365],
                   np.r_[0, g["theta"]])
    return 100 * math.sqrt(th * 365 / 30)


vx["atm30"] = ver.groupby("fecha").apply(atm30)
d_mod = vx["vorx"] - vx["vorx_modelo"]
d_atm = vx["vorx"] - vx["atm30"]
print(f"VORX − swap del modelo: media {d_mod.mean():.2f}, "
      f"mín. {d_mod.min():.2f}, máx. {d_mod.max():.2f}")
print(f"VORX − ATM a 30 días: media {d_atm.mean():.2f}, "
      f"mediana {d_atm.median():.2f}")
vx[["vorx", "vorx_modelo", "atm30"]].describe().round(2) \
    .loc[["mean", "50%", "min", "max"]]
```
```output
VORX − swap del modelo: media 0.17, mín. -2.36, máx. 1.39
VORX − ATM a 30 días: media 2.86, mediana 2.58
       vorx  vorx_modelo  atm30
mean  19.80        19.63  16.94
50%   17.66        17.37  15.13
min    9.55         9.72   8.50
max   73.98        74.16  63.02
```

El VORX queda de media 0,17 puntos por encima del swap de varianza de la superficie verdadera (`vorx_modelo`), con
desviaciones de −2,36 a 1,39: es el error de discretizar la integral en strikes, truncar las alas e interpolar entre
dos vencimientos. Frente a la volatilidad ATM a 30 días, en cambio, está 2,86 puntos por encima de media (mediana
2,58): la diferencia no es un error, es el skew. Un índice tipo VIX no mide la volatilidad ATM, sino la raíz de una
media de las varianzas de toda la sonrisa, y con skew esa media supera a la del dinero.

## Volatilidad realizada y prima de riesgo

La comparación justa es la implícita de hoy frente a la realizada **después**: el VORX del día $t$ mira los 30 días
naturales siguientes, unas 21 sesiones. Usar la realizada de las 21 sesiones anteriores sería comparar el precio de
hoy con un dato que ya se conocía.

```python
r = np.log(ind["cierre"]).diff()
real_post = 100 * np.sqrt(252 * (r ** 2).rolling(21).mean()) \
    .shift(-21)                       # sesiones t+1 … t+21
real_prev = 100 * np.sqrt(252 * (r ** 2).rolling(21).mean())
prima = (vx["vorx"] - real_post).dropna()
print(f"Prima VORX − realizada: media {prima.mean():.2f}, "
      f"mediana {prima.median():.2f}")
print(f"Días con la realizada por encima: {(prima < 0).mean():.1%}")
print(f"Peor día: {prima.idxmin().date()}, {prima.min():.1f} puntos")
p_atm = (vx["atm30"] - real_post).dropna()
print(f"Con la ATM a 30 días: media {p_atm.mean():.2f}, "
      f"mediana {p_atm.median():.2f}")
var_prima = (vx["vorx"] ** 2 - real_post ** 2).dropna() / 100
print(f"En varianza (puntos² / 100): media {var_prima.mean():.2f}")
```
```output
Prima VORX − realizada: media 5.30, mediana 6.38
Días con la realizada por encima: 11.1%
Peor día: 2020-03-06, -76.5 puntos
Con la ATM a 30 días: media 2.43, mediana 3.88
En varianza (puntos² / 100): media 1.53
```

La prima media es de 5,30 puntos de volatilidad y la mediana, de 6,38. La realizada supera al VORX el 11,1 % de los
días, y el peor caso es el 6 de marzo de 2020: el VORX marcaba 23,2 y la realizada de las 21 sesiones siguientes,
que incluyen las caídas de doble dígito del 12 y el 16 de marzo, fue del 99,7 %, una diferencia de −76,5 puntos.
Con la volatilidad ATM a 30 días, la prima es menor (2,43 de media) porque parte de lo que el VORX cobra es el skew.
En varianza, que es lo que se negocia en un swap, la diferencia media es de 153 puntos de volatilidad al cuadrado
(0,0153 de varianza anual).

En los datos la prima está plantada: la varianza implícita es entre 1,0 y 1,3 veces la esperada (más en calma que en
estrés), según el README de los datos. La referencia académica sobre la prima de varianza en los mercados reales es Carr y
Wu (2009), en los recursos; aquí no se da ninguna cifra real.

```python
anual = prima.groupby(prima.index.year).agg(
    media="mean", mediana="median", minimo="min",
    negativa=lambda z: (z < 0).mean())
anual.round(2).T
```
```output
fecha     2014   2015   2016  2017   2018  2019   2020  2021  2022  2023  2024   2025
media     3.91   4.38   4.19  4.26   6.04  6.90   5.08  7.18  5.67  6.35  5.41   4.18
mediana   4.23   5.68   5.50  5.02   8.13  7.07  11.92  8.62  6.37  7.15  5.63   6.33
minimo   -4.19 -15.67 -16.19 -8.09 -16.95 -1.40 -76.46 -7.03 -9.44 -1.15 -2.88 -24.94
negativa  0.11   0.22   0.15  0.17   0.16  0.02   0.10  0.09  0.08  0.04  0.06   0.14
```

La mediana es positiva todos los años, de 4,2 en 2014 a 11,9 en 2020; la fracción de días negativos va del 2 % (2019)
al 22 % (2015). Los mínimos cuentan otra historia: −76,5 en 2020, −24,9 en 2025, −17,0 en 2018 y −16,2 en 2016, los
años con tramos de estrés en el guion de los datos. La prima es estable en el centro y muy inestable en la cola.

*Fig. — Distribución diaria de la prima de riesgo de volatilidad de los datos, VORX menos la realizada de las 21 sesiones siguientes, en puntos de volatilidad, 2014-2025 (número de días en escala log).* Histograma con barras de 2 puntos. La masa está entre 0 y 15 puntos, con la moda entre 6 y 8; media 5,3 y mediana 6,4. A la izquierda de cero (destacado), el 11,1 % de los días, con una cola que llega a −76 puntos en marzo de 2020.

La figura muestra toda la distribución, con el número de días en escala logarítmica para que se vea la cola: la masa
entre 0 y 15 puntos y, a la izquierda de cero (destacado), una cola larga con un grupo aislado entre −76 y −62 que
son las 16 sesiones del 13 de febrero al 6 de marzo de 2020.

```python
import statsmodels.api as sm

d = pd.concat({"real_post": real_post, "vorx": vx["vorx"],
               "real_prev": real_prev}, axis=1).dropna()
d = d.iloc[::21]          # sin solapamiento: una cada 21 sesiones
for x_cols in (["vorx"], ["real_prev"], ["vorx", "real_prev"]):
    m = sm.OLS(d["real_post"], sm.add_constant(d[x_cols])).fit()
    coef = ", ".join(f"{c} {m.params[c]:.2f} (t {m.tvalues[c]:.1f})"
                     for c in x_cols)
    print(f"{coef} · R² {m.rsquared:.2f} · n {int(m.nobs)}")
```
```output
vorx 0.70 (t 7.9) · R² 0.31 · n 142
real_prev 0.41 (t 5.3) · R² 0.17 · n 142
vorx 0.91 (t 5.5), real_prev -0.19 (t -1.5) · R² 0.32 · n 142
```

Con una observación cada 21 sesiones (142, sin solapamiento), el VORX explica el 31 % de la varianza de la realizada
posterior, frente al 17 % de la realizada pasada; juntas, el 32 %, y la pasada pierde su significación (t = −1,5). El
VORX contiene la información de la volatilidad pasada y algo más. Su pendiente de 0,70 (sola) dice que es un
predictor sesgado al alza: lleva la prima dentro.

<aside class="callout" data-kind="riesgo">

Una prima media positiva no convierte la venta de volatilidad en una renta. La distribución de la figura tiene una
cola izquierda que llega a −76 puntos, y una posición vendida en varianza pierde en proporción al cuadrado de la
volatilidad realizada. La lección 3.6.1 mide la venta sistemática de prima con su peor episodio, y la 3.6.3, los
productos sobre el VIX, cuyo roll en contango también se paga.

</aside>

## El VSTOXX y el índice europeo de los datos

El **VSTOXX** es el índice de volatilidad del EURO STOXX 50, desarrollado por Goldman Sachs y Deutsche Börse y
calculado por STOXX con las opciones OESX de Eurex. Su varianza por vencimiento usa la misma fórmula que el VIX, pero
la guía de STOXX[^stoxx] cambia bastantes detalles:

| Aspecto | VIX (Cboe) | VSTOXX (STOXX) |
|---|---|---|
| Opciones | SPX mensuales y semanales, de 23 a 37 días | OESX de Eurex; 8 subíndices por vencimiento, de 1 a 24 meses |
| Índice principal | 30 días, interpolando dos vencimientos | 30 días (y otros 11 plazos hasta 360), interpolando dos subíndices |
| Precio de cada opción | Punto medio del bid y el ask | El más reciente entre operación, medio y liquidación; el medio solo si bid y ask son de al menos 0,1 y la horquilla no supera el 8 % del bid (entre 1,2 y 18 puntos en mercado normal) |
| Exclusiones | Bids nulos; se para tras dos seguidos | Precios por debajo de 0,5 puntos; un subíndice necesita al menos 5 opciones |
| Tipos | Curva del Tesoro de EE. UU. | €STR, EURIBOR y REX a 2 años, interpolados |
| Tiempo | Minutos | Segundos; fotos cada 5 segundos de 9:15 a 17:30 CET |

La consecuencia práctica es que los dos índices no son intercambiables aunque se muevan juntos: con horquillas
anchas (estrés), el VSTOXX puede usar precios de liquidación o de la última operación donde el VIX usa medios, y el
filtro de 0,5 puntos recorta sus alas antes. En los datos del curso, el índice europeo ficticio **VGX** tiene su índice
de volatilidad **VVGX**, calculado como la raíz del swap de varianza a 30 días de su propio modelo (no hay cadena de
VGX publicada, así que no se puede recalcular):

```python
rg = np.log(vx["vgx"]).diff()
real_post_g = 100 * np.sqrt(252 * (rg ** 2).rolling(21).mean()) \
    .shift(-21)
prima_g = (vx["vvgx"] - real_post_g).dropna()
print(f"VVGX: media {vx['vvgx'].mean():.1f}, "
      f"VORX: media {vx['vorx'].mean():.1f}")
print(f"Prima VVGX: media {prima_g.mean():.2f}, mediana "
      f"{prima_g.median():.2f}, negativa {(prima_g < 0).mean():.1%}")
print(f"Correlación de rendimientos ORX-VGX: {r.corr(rg):.2f}")
print("Correlación de cambios diarios VORX-VVGX: "
      f"{vx['vorx'].diff().corr(vx['vvgx'].diff()):.2f}")
print("Correlación de ORX con los cambios del VORX: "
      f"{r.corr(vx['vorx'].diff()):.2f}")
```
```output
VVGX: media 21.3, VORX: media 19.8
Prima VVGX: media 5.41, mediana 6.16, negativa 11.0%
Correlación de rendimientos ORX-VGX: 0.82
Correlación de cambios diarios VORX-VVGX: 0.96
Correlación de ORX con los cambios del VORX: -0.61
```

El VVGX tiene una media de 21,3 frente a 19,8 del VORX, una prima parecida (5,41 de media, 6,16 de mediana, negativa
el 11,0 % de los días) y unos cambios diarios casi idénticos a los del VORX (correlación 0,96), porque en el modelo de
los datos su varianza es 1,2 veces la de ORX con un ruido propio pequeño. En los mercados reales la relación entre el
VIX y el VSTOXX es estrecha, pero no tanto: cada uno tiene su propio mercado de opciones, sus horarios y sus reglas.
La correlación negativa de −0,61 entre el rendimiento de ORX y el cambio del VORX es el efecto apalancamiento: la
volatilidad implícita sube cuando el índice cae.

## Ejercicios

1. Calcula el VORX del miércoles 18 de junio de 2025, cuando el primer vencimiento está a dos días. ¿Qué vencimientos
   entran y por qué? Comprueba el resultado con el publicado.

**Solución.**

```python
f = pd.Timestamp("2025-06-18")
print({(v - f).days: len(g) for v, g in grupos[f].items()})
print(f"Calculado {vorx(f, grupos[f]):.2f}, "
      f"publicado {vx.loc[f, 'vorx']:.2f}")
```
```output
{2: 48, 30: 45, 58: 40}
Calculado 25.11, publicado 25.11
```

El vencimiento de 2 días tiene menos de 8 y se salta: entran los de 30 y 58 días. Con $N_1 = 30$, todo el peso cae en
el primero, y el VORX es exactamente la volatilidad del swap de 30 días: 25,11, igual que el publicado. La regla de
los 8 días evita usar opciones a punto de vencer, cuyo precio está dominado por el ruido y el valor intrínseco.

2. Repite la prima con la realizada de las 21 sesiones **anteriores** en vez de las siguientes. ¿Cuánto cambia la media
   y la fracción de días negativos? ¿Por qué esa versión no sirve para evaluar una estrategia?

**Solución.**

```python
prima_prev = (vx["vorx"] - real_prev).dropna()
print(f"Media {prima_prev.mean():.2f} (posterior {prima.mean():.2f})")
print(f"Negativa {(prima_prev < 0).mean():.1%} "
      f"(posterior {(prima < 0).mean():.1%})")
print(f"Mínimo {prima_prev.min():.1f} el {prima_prev.idxmin().date()}")
```
```output
Media 5.33 (posterior 5.30)
Negativa 12.3% (posterior 11.1%)
Mínimo -36.6 el 2020-04-06
```

La media apenas cambia (5,33 frente a 5,30), pero la fracción de días negativos sube al 12,3 % y el peor día pasa al
6 de abril de 2020, con −36,6: es el día en que la realizada de las 21 sesiones anteriores recoge todo el desplome
de marzo mientras el VORX ya ha bajado. Esa comparación no sirve para evaluar una venta de volatilidad, porque la
posición abierta hoy gana o pierde con la volatilidad que llega después, no con la que ya pasó.

3. En la cadena del 4 de junio de 2025, el VORX usa 32 de los 48 strikes del vencimiento de 16 días. ¿Qué pasaría
   con su varianza si se usaran todos, con el medio de las opciones de bid nulo? Razónalo con la fórmula y
   compruébalo.

**Solución.**

```python
g = grupos_hoy[pd.Timestamp("2025-06-20")]
T = 16 / 365
R = tipo(hoy, T)
K = g["strike"].to_numpy()
c = ((g["bid_C"] + g["ask_C"]) / 2).to_numpy()
p = ((g["bid_P"] + g["ask_P"]) / 2).to_numpy()
j = np.argmin(np.abs(c - p))
F = K[j] + math.exp(R * T) * (c[j] - p[j])
i0 = np.flatnonzero(K <= F)[-1]
Q = np.r_[p[:i0], (c[i0] + p[i0]) / 2, c[i0 + 1:]]
todos = (2 / T * np.gradient(K) / K ** 2 * Q
         * math.exp(R * T)).sum() - (F / K[i0] - 1) ** 2 / T
regla = var_cboe(g, T, R)
print(f"Regla de Cboe: σ² = {regla:.6f} "
      f"(vol {100 * math.sqrt(regla):.2f})")
print(f"Todos los strikes: σ² = {todos:.6f} "
      f"(vol {100 * math.sqrt(todos):.2f})")
```
```output
Regla de Cboe: σ² = 0.065072 (vol 25.51)
Todos los strikes: σ² = 0.065269 (vol 25.55)
```

Cada término $\Delta K_i\,Q(K_i)/K_i^2$ es positivo, así que añadir opciones solo puede subir la suma (los
$\Delta K$ de los vecinos cambian poco). En los datos, la varianza pasa de 0,065072 a 0,065269 y la volatilidad, de
25,51 a 25,55: poco, porque esas opciones son baratas y lejanas. Pero su «precio» no es un precio: con bid nulo nadie
compra, y el medio de 0,025 es una convención. La regla de Cboe las excluye y corta el ala tras dos bids nulos
seguidos para que el índice no dependa de cotizaciones que no se pueden ejecutar.

[^cboe]: Historia y reglas actuales: Cboe, *Volatility Index Methodology: Cboe Volatility Index* (versión 6.0) y
    *Cboe Volatility Index Mathematics Methodology*; versión mensual con al menos una semana de vida: libro blanco de
    2009. Enlaces en los recursos de la lección.

[^stoxx]: STOXX, *Strategy Index Guide*, edición de septiembre de 2024, sección 9 (EURO STOXX 50 Volatility). Enlace
    en los recursos.

## Autoevaluación

1. En la fórmula del VIX, ¿por qué cada opción pesa ΔK/K²?

   - A. Porque así lo decidió Cboe para dar más peso a las opciones baratas
   - B. Porque una cartera de opciones fuera del dinero con pesos 1/K² replica un contrato que paga la varianza realizada (un swap de varianza), con sensibilidad a la varianza que no depende del nivel del índice
   - C. Para corregir la paridad put-call
   - D. Porque las opciones de strike alto son más líquidas

   *Respuesta B: Porque una cartera de opciones fuera del dinero con pesos 1/K² replica un contrato que paga la varianza realizada (un swap de varianza), con sensibilidad a la varianza que no depende del nivel del índice.* Es el resultado de Demeterfi, Derman, Kamal y Zou (1999) y de Carr y Madan: la varianza esperada bajo la medida riesgo neutral es 2/T por la integral de las OTM ponderadas por 1/K². El VIX es 100 veces la raíz de esa varianza a 30 días.

2. El VORX de los datos está de media 2,9 puntos por encima de la volatilidad ATM a 30 días del modelo. ¿Por qué?

   - A. Por el ruido de las cotizaciones
   - B. Porque un swap de varianza integra toda la sonrisa, y con skew las puts fuera del dinero tienen más volatilidad que el ATM: la raíz de la varianza del swap queda por encima de la volatilidad ATM
   - C. Porque el VORX usa días hábiles
   - D. Porque el VORX incluye el dividendo

   *Respuesta B: Porque un swap de varianza integra toda la sonrisa, y con skew las puts fuera del dinero tienen más volatilidad que el ATM: la raíz de la varianza del swap queda por encima de la volatilidad ATM.* La varianza del swap es una media de las varianzas de toda la sonrisa, con más peso en los strikes bajos (1/K²). Con un skew como el de un índice, esa media supera a la varianza ATM.

3. La volatilidad implícita a 30 días ha superado a la realizada de los 30 días siguientes en el 89 % de los días de los datos. ¿Es vender volatilidad una renta segura?

   - A. Sí: gana casi nueve de cada diez veces
   - B. No: en el 11 % restante la realizada puede superar a la implícita por decenas de puntos (76 en marzo de 2020 en los datos), y una venta sin cobertura pierde en pocos días lo ganado en años
   - C. Sí, si se hace con futuros en vez de opciones
   - D. No, porque la prima es negativa de media

   *Respuesta B: No: en el 11 % restante la realizada puede superar a la implícita por decenas de puntos (76 en marzo de 2020 en los datos), y una venta sin cobertura pierde en pocos días lo ganado en años.* La prima de riesgo de volatilidad es la compensación por cargar con ese riesgo de cola. Su media es positiva (5,3 puntos en los datos) y su distribución tiene una cola izquierda muy larga. La lección 3.6.1 mide el resultado de venderla.

4. ¿Cuál de estas diferencias entre el VSTOXX y el VIX es correcta según los documentos de STOXX y Cboe?

   - A. El VSTOXX usa solo opciones ATM
   - B. El VSTOXX toma como precio de cada opción el más reciente entre la última operación, el punto medio (si la horquilla pasa un filtro) y la liquidación; el VIX usa el punto medio del bid y el ask
   - C. El VSTOXX no interpola entre vencimientos
   - D. El VSTOXX se calcula sobre el DAX

   *Respuesta B: El VSTOXX toma como precio de cada opción el más reciente entre la última operación, el punto medio (si la horquilla pasa un filtro) y la liquidación; el VIX usa el punto medio del bid y el ask.* La guía de STOXX define un precio de inclusión que puede ser la operación, el medio o la liquidación, con filtros de horquilla; Cboe usa medios y excluye las opciones con bid nulo. La fórmula de varianza por vencimiento es la misma.

## Ideas clave

- El VIX es 100 veces la raíz de la varianza riesgo neutral a 30 días, estimada con una cartera de opciones fuera del dinero ponderadas por ΔK/K² e interpolada entre dos vencimientos.
- Con la fórmula de Cboe sobre la cadena publicada se recalcula el VORX de los datos al céntimo en los 3.017 días con cadena.
- Las puts aportan la mayor parte de la varianza del índice por el skew: en el vencimiento de 44 días del 4 de junio de 2025, el 69 %.
- Prima de riesgo de volatilidad en los datos: VORX menos realizada posterior, media de 5,3 puntos y mediana de 6,4; la realizada lo supera el 11 % de los días, con un máximo de 76 puntos en marzo de 2020.
- El VSTOXX usa la misma fórmula de varianza por vencimiento, pero otros precios (operación, medio filtrado o liquidación), otros tipos (€STR, EURIBOR) y subíndices por vencimiento.

## Recursos

### Research

- [Usos de la Volatilidad y Volatilidad Actual - VIX1D](https://pythonparatrading.com/usos-de-la-volatilidad/) · Research-0003 · 6 min

### Documentación

- [Cboe: Volatility Index Methodology, Cboe Volatility Index (versión 6.0, febrero de 2026)](https://cdn.cboe.com/resources/indices/Volatility_Index_Methodology_Cboe_Volatility_Index.pdf) · cdn.cboe.com
- [Cboe: Cboe Volatility Index Mathematics Methodology](https://cdn.cboe.com/resources/indices/Cboe_Volatility_Index_Mathematics_Methodology.pdf) · cdn.cboe.com
- [Cboe (2009): The CBOE Volatility Index, VIX (libro blanco con vencimientos mensuales; copia de la OIC)](https://www.optionseducation.org/getmedia/5d6a69e4-8a3a-449d-8fef-be10638919c7/vixwhite.pdf) · optionseducation.org
- [STOXX: Strategy Index Guide, sección 9, EURO STOXX 50 Volatility (VSTOXX) (septiembre de 2024)](https://www.stoxx.com/documents/stoxxnet/Documents/News/2024/September/Stoxx_strategy_guide.pdf) · stoxx.com

### Libros

- [Carr, P. y Wu, L. (2009): Variance Risk Premiums. Review of Financial Studies 22(3), 1311-1341](https://doi.org/10.1093/rfs/hhn038) · doi.org

### Datos

- [Datos del nivel 3: VORX, VGX y VVGX diarios (CSV)](https://pythonparatrading.com/curso/datos/nivel-3/vol3_indices.csv) · Descarga · vol3_indices.csv

Lección anterior: [3.4.5 · Sonrisa, skew y estructura temporal; superficie de volatilidad con SVI](https://pythonparatrading.com/curso-python-trading/nivel-3/sonrisa-skew-y-superficie-de-volatilidad-svi/)

Lección siguiente: [3.4.7 · Modelos avanzados: Heston, SABR y volatilidad local](https://pythonparatrading.com/curso-python-trading/nivel-3/heston-sabr-y-volatilidad-local/)
