Lección 3.6.3 · 70 min

Estrategias con VIX y VSTOXX: futuros y ETP de volatilidad

El VIX es un cálculo, no un activo: lo que se negocia son futuros que convergen a él y productos cotizados que ruedan esos futuros cada día. Esta lección reconstruye con los datos del curso la curva, el índice de futuros a corto plazo y dos ETP, uno largo que pierde un 99,4 % en doce años y uno inverso que desaparece en una sesión, y mide qué queda de las estrategias de venta de volatilidad cuando se mira su peor día.

Fig. — ETP de volatilidad sobre los futuros del VORX, base 100 en enero de 2014, escala logarítmica: el largo (imita al VXX) pierde un 99,4 % en doce años; el inverso diario (imita al XIV) llega a 221 y se liquida el 2018-02-05 (datos sintéticos)
Lecciones del nivel 3
  1. 3.1 · Futuros en profundidad

    1. 3.1.1 Contratos de futuros principales
    2. 3.1.2 Curva de futuros: base, cost of carry, contango y roll yield
    3. 3.1.3 Gestión del roll, márgenes, SPAN y apalancamiento implícito
    4. 3.1.4 Sistemas de futuros diversificados: el enfoque de Carver
  2. 3.2 · Spreads de futuros

    1. 3.2.1 Spreads de calendario, butterflies y condors
    2. 3.2.2 Spreads intercommodity: crack, spark y crush
    3. 3.2.3 Spreads de tipos y de índices: 2s10s, NOB, NQ/ES y Europa frente a EE. UU.
    4. 3.2.4 Ratios de cobertura: por nominal, por DV01 y por volatilidad
    5. 3.2.5 Datos y backtesting de spreads: cotizados, sintéticos y por patas
    6. 3.2.6 Estacionalidad de spreads: análisis multi-año, patrones y trampas
  3. 3.3 · Forex avanzado

    1. 3.3.1 Microestructura FX: OTC, ECN, last look y sesiones
    2. 3.3.2 Carry y riesgo de crash, momentum y value en divisas; cestas
    3. 3.3.3 Riesgo de divisa en carteras multi-moneda; ejecución vía OANDA, IBKR o MT5
  4. 3.4 · Teoría y valoración de opciones

    1. 3.4.1 Payoffs, paridad put-call y límites de arbitraje
    2. 3.4.2 Árboles binomiales, Black-Scholes-Merton, Black-76 y Monte Carlo
    3. 3.4.3 Griegas: delta, gamma, vega, theta, rho, vanna, volga y charm
    4. 3.4.4 Volatilidad implícita: Newton-Raphson, Brent, py_vollib y QuantLib
    5. 3.4.5 Sonrisa, skew y estructura temporal; superficie de volatilidad con SVI
    6. 3.4.6 Volatilidad realizada frente a implícita; prima de riesgo de volatilidad; VIX y VSTOXX
    7. 3.4.7 Modelos avanzados: Heston, SABR y volatilidad local
  5. 3.5 · Estructuras de opciones en Python

    1. 3.5.1 Estructuras direccionales y verticales: call, put, covered call, collar y spreads
    2. 3.5.2 Estructuras de volatilidad y rango: straddles, strangles, cóndores y mariposas
    3. 3.5.3 Calendarios, diagonales, ratios, backspreads, risk reversals y jade lizard
    4. 3.5.4 Herramienta propia: payoff, griegas agregadas y escenarios
    5. 3.5.5 Gestión: ajustes, roll, cierre anticipado, asignación temprana y pin risk
  6. 3.6 · Estrategias sistemáticas de volatilidad y opciones

    1. 3.6.1 Venta sistemática de prima: put-write, strangles y su riesgo de cola
    2. 3.6.2 Delta hedging, gamma scalping y dispersión
    3. 3.6.3 Estrategias con VIX y VSTOXX: futuros y ETP de volatilidad
    4. 3.6.4 Backtesting de opciones: datos, fills y ajustes por eventos
  7. 3.7 · Cripto derivados y estrategias específicas

    1. 3.7.1 Perpetuos: mecánica del funding, mark price y liquidaciones
    2. 3.7.2 Arbitraje de funding, basis con futuros y arbitraje entre exchanges
    3. 3.7.3 Opciones cripto, datos on-chain y DeFi
    4. 3.7.4 ccxt para operar en varios exchanges
    5. 3.7.5 MiCA: el marco de la UE para criptoactivos y sus proveedores (CASP)

Un índice que no se puede comprar

El VIX de Cboe mide la volatilidad esperada a 30 días del S&P 500 con los precios de una franja de sus opciones, con la fórmula de varianza que la lección 3.4.6 aplica al VORX de los datos del curso. Cboe lo publicó en 1993 sobre opciones del S&P 100 y lo cambió en 2003 a la fórmula actual, según su metodología. El VSTOXX es el equivalente europeo, sobre las opciones del Euro Stoxx 50.

Ninguno de los dos se puede comprar. Para mantener «el VIX» habría que tener una cesta de opciones con 30 días que cambia de strikes y de vencimientos cada día; no es una cartera que se compre y se guarde. Lo que se negocia son futuros sobre el índice y, encima de ellos, productos cotizados (ETP: fondos y notas) que mantienen una posición en esos futuros y la ruedan. Cada capa añade una diferencia con el índice que el inversor cree estar comprando.

liquidaOpciones a 30 dVIX al contadoFuturos VXÍndice de futurosETP largoETP inverso
Fuente Mermaid
flowchart TB
  O[Opciones a 30 d] --> V[VIX al contado]
  V -. liquida .-> F[Futuros VX]
  F --> I[Índice de futuros]
  I --> L[ETP largo]
  I --> N[ETP inverso]

Las reglas reales de los futuros, de sus fuentes primarias:

Futuros sobre el VIX (Cboe, VX)Futuros sobre el VSTOXX (Eurex, FVS)
Multiplicador1.000 USD por punto100 EUR por punto
Tick0,05 puntos (50 USD)0,05 puntos (5 EUR)
Liquidación finalEl miércoles 30 días antes del tercer viernes del mes siguiente30 días naturales antes del vencimiento de las opciones subyacentes
Precio de liquidaciónSOQ: el VIX calculado con los precios de apertura de las opciones de ese díaMedia del índice entre las 11:00 y las 12:00 CET del último día
LiquidaciónEn efectivoEn efectivo

La fecha de los dos sale de la misma idea: 30 días antes de que venzan las opciones con las que se calcula el índice, para que el día de la liquidación el índice dependa de un único vencimiento a 30 días. La SOQ (Special Opening Quotation) no es el VIX de esa mañana: se calcula con los precios de apertura de una subasta especial de las opciones del S&P 500, con reglas propias (por ejemplo, admite strikes con bid nulo), según la sección 3.4 de la metodología de Cboe. En los datos del curso los futuros sobre el VORX vencen el miércoles 30 días antes del tercer viernes del mes siguiente, como los VX, y liquidan al cierre del VORX de ese día (simplificación).

La curva de futuros sobre el VORX

Los datos son sintéticos (public/curso/datos/nivel-3/README.md): vol3_indices.csv con el VORX, que imita al VIX y se recalcula exactamente con la fórmula de Cboe desde la cadena de ORX (lección 3.4.6), y el VVGX, que imita al VSTOXX; vol3_futuros.parquet con ocho futuros mensuales sobre el VORX, y vol3_etp.csv con el índice de futuros a corto plazo y dos ETP. El modelo de los futuros es la expectativa del VORX en su vencimiento bajo la medida de valoración, más la diferencia de hoy entre el VORX y su modelo, que se disipa con 10 días de vida. Y lleva plantado un episodio: el 2018-02-05 los dos primeros futuros liquidan un 22 % por encima de su valor de modelo, como la compra de los ETP inversos en la ventana de liquidación, y se deshace al día siguiente.

IN [01]python
import numpy as np
import pandas as pd

vi = pd.read_csv("vol3_indices.csv", parse_dates=["fecha"])
vi = vi.set_index("fecha")
fu = pd.read_parquet("vol3_futuros.parquet")
fu = fu.sort_values(["fecha", "vencimiento"])
fu["orden"] = fu.groupby("fecha").cumcount()   # 0 = el primero
vx = vi["vorx"]
print(vx.describe().round(2).to_dict())
curvas = {d: fu[fu["fecha"] == d].set_index("dias")["precio"]
          for d in ("2017-06-14", "2020-03-16")}
for d, c in curvas.items():
    print(d, "VORX", vx[d], "|", c.to_dict())
OUT [01]El VORX y dos curvas de futuros
{'count': 3018.0, 'mean': 19.8, 'std': 8.51, 'min': 9.55, '25%': 14.23, '50%': 17.66, '75%': 22.83, 'max': 73.98}
2017-06-14 VORX 11.05 | {7: 12.3, 35: 15.05, 63: 16.4, 98: 17.3, 126: 17.8, 154: 18.3, 189: 18.6, 217: 19.0}
2020-03-16 VORX 73.09 | {2: 71.45, 30: 51.35, 65: 37.9, 93: 31.35, 128: 26.8, 156: 25.15, 184: 24.2, 219: 23.7}
Fig. — Curva de futuros sobre el VORX en calma (2017-06-14) y en crisis (2020-03-16); el punto en el día 0 es el VORX al contado (datos sintéticos)

Las dos fotos son las dos formas de la curva. El 14 de junio de 2017, con el VORX en 11,05, el futuro a 7 días cotiza a 12,30 y el de 217 días a 19,00: contango, cada vencimiento más caro que el anterior, porque la volatilidad baja se espera que vuelva a su media, más alta. El 16 de marzo de 2020, con el VORX en 73,09, la curva baja de 71,45 a 23,70: backwardation, porque se espera que la crisis pase. La medida en toda la muestra:

IN [02]python
f1 = fu[fu["orden"] == 0].set_index("fecha")
f2 = fu[fu["orden"] == 1].set_index("fecha")
print(f"primer futuro sobre el VORX: "
      f"{(f1['precio'] > vx).mean():.1%} de las sesiones")
print(f"segundo sobre el primero: "
      f"{(f2['precio'] > f1['precio']).mean():.1%}; diferencia "
      f"media {(f2['precio'] / f1['precio'] - 1).mean():.1%}")
venc = fu[fu["fecha"] == fu["vencimiento"]].set_index("fecha")
dif = (venc["precio"] - vx.reindex(venc.index)).abs()
print(f"{len(venc)} vencimientos; |futuro − VORX| al vencer: "
      f"máx. {dif.max():.3f}")
OUT [02]Contango y convergencia al vencimiento
primer futuro sobre el VORX: 62.8% de las sesiones
segundo sobre el primero: 71.1%; diferencia media 4.4%
144 vencimientos; |futuro − VORX| al vencer: máx. 0.000

Las tres cifras de la respuesta conocida del README (63 %, 71 % y 4,4 %) salen exactas, y los 144 vencimientos liquidan al VORX de ese día. La convergencia es la clave de todo lo que sigue: un futuro en contango tiene que bajar hasta el índice o el índice subir hasta él antes del vencimiento. ¿Cuál de los dos se mueve?

Roll yield: ¿converge el futuro o el índice?

El roll diario de un futuro es su base repartida entre los días que le quedan: (F−VORX)/dıˊas(F - \text{VORX}) / \text{días}. Si la base fuera una predicción insesgada del índice, el índice subiría de media lo que dice el roll y el futuro no se movería. Si es una prima, el futuro bajaría hacia el índice y el índice no se movería de forma predecible. La regresión de los cambios del día siguiente sobre el roll, con el primer futuro a 10 días o más y errores robustos a la autocorrelación (Newey-West con 5 retardos):

IN [03]python
import statsmodels.api as sm

fu["siguiente"] = fu.groupby("contrato")["precio"].shift(-1)
g = fu[(fu["orden"] == 0) & (fu["dias"] >= 10)].set_index("fecha")
g = g.assign(roll=(g["precio"] - vx.reindex(g.index)) / g["dias"],
             d_futuro=g["siguiente"] - g["precio"],
             d_vorx=(vx.shift(-1) - vx).reindex(g.index)).dropna()
for y in ("d_futuro", "d_vorx"):
    m = sm.OLS(g[y], sm.add_constant(g["roll"])).fit(
        cov_type="HAC", cov_kwds={"maxlags": 5})
    print(f"{y:9}: coeficiente {m.params['roll']:6.2f}, "
          f"t {m.tvalues['roll']:5.1f}, R² {m.rsquared:.3f}")
OUT [03]La base predice el futuro, no el índice
d_futuro : coeficiente  -1.56, t  -4.3, R² 0.024
d_vorx   : coeficiente   0.42, t   1.0, R² 0.001

El cambio del futuro tiene un coeficiente de −1,56 sobre el roll (t = −4,3): en contango el futuro baja hacia el índice y en backwardation sube. El cambio del VORX no tiene relación significativa con el roll (t = 1,0). Es lo que Simon y Campasano (2014) encuentran en el VIX real de 2006 a 2011: la base no predice el VIX al contado y sí el cambio de los futuros. Para quien mantiene futuros comprados, el contango es un coste que se paga cada día; para quien los vende, una prima. Los R² son pequeños (un 2,4 % para el futuro) porque la volatilidad diaria de los futuros es mucho mayor que el roll: la prima existe, pero se cobra entre mucho ruido y algún salto.

El índice de futuros a corto plazo y el ETP largo

Un producto que quiera «la volatilidad a 30 días» mantiene una mezcla del primer y del segundo futuro que pasa cada día un poco de peso del primero al segundo, de modo que el vencimiento medio quede en torno a un mes. Es la construcción del S&P 500 VIX Short-Term Futures Index, que el folleto del primer ETN sobre él describe como «una posición larga que rueda a diario en el primer y el segundo futuro mensual»1Nota 1 · Barclays Bank PLC, folleto (free writing prospectus) del iPath S&P 500 VIX Short-Term Futures ETN (VXX), 2 de diciembre de 2009, en la SEC: https://www.sec.gov/Archives/edgar/data/312070/000119312509245713/dfwp.htm. Describe el índice como una posición larga que rueda a diario del primer al segundo futuro mensual del VIX, con vencimiento constante de un mes, y una comisión anual del 0,89 %.. En los datos, indice_futuros_cp sigue la misma regla: el peso del primer futuro es la fracción de sesiones del periodo de roll (de un vencimiento al siguiente) que quedan hasta su vencimiento. Reconstruirlo desde los futuros es la prueba de que se entiende:

IN [04]python
etp = pd.read_csv("vol3_etp.csv", parse_dates=["fecha"])
etp = etp.set_index("fecha")
tabla = fu.pivot(index="fecha", columns="vencimiento",
                 values="precio")
vencs, ses = sorted(fu["vencimiento"].unique()), tabla.index
rend = [0.0]
for t in range(len(ses) - 1):
    hoy, man = ses[t], ses[t + 1]
    e1 = next(v for v in vencs if v > hoy)      # primer futuro
    e2 = next(v for v in vencs if v > e1)       # segundo
    previos = [v for v in vencs if v <= hoy]
    e0 = max(previos) if previos else e1 - pd.Timedelta(days=35)
    w1 = (((ses > hoy) & (ses <= e1)).sum()
          / ((ses > e0) & (ses <= e1)).sum())  # peso del primero
    a0 = w1 * tabla.at[hoy, e1] + (1 - w1) * tabla.at[hoy, e2]
    a1 = w1 * tabla.at[man, e1] + (1 - w1) * tabla.at[man, e2]
    rend.append(a1 / a0 - 1)
rend = pd.Series(rend, ses)
indice = 100 * (1 + rend).cumprod()
print(f"diferencia máxima con el archivo: "
      f"{(indice - etp['indice_futuros_cp']).abs().max():.5f}")
print(f"índice: 100 el {ses[0].date()}, "
      f"{indice.iloc[-1]:.2f} el {ses[-1].date()}")
OUT [04]Reconstrucción del índice de futuros a corto plazo
diferencia máxima con el archivo: 0.00005
índice: 100 el 2014-01-02, 0.49 el 2025-12-31

La diferencia máxima es de cinco cienmilésimas: el redondeo del archivo a cuatro decimales. El índice de futuros cae de 100 a 0,49 en doce años. Es el roll en contango acumulado sesión a sesión: cada día se vende un poco del primer futuro, que ha bajado hacia el índice, y se compra el segundo, más caro.

El ETP largo (lvol, que imita al VXX) suma al índice el tipo a 3 meses de su colateral y resta una comisión del 0,89 % anual, la que fijaba el folleto del VXX1. Con esa regla se reconstruye también, y el resultado por años es este:

IN [05]python
ind = pd.read_csv("opciones3_indice.csv", parse_dates=["fecha"])
tb = ind.set_index("fecha")["tipo_3m"] / 100
largo = [100.0]
for t in range(len(ses) - 1):
    largo.append(largo[-1] * (1 + rend.iloc[t + 1]
                              + tb.iloc[t] / 252 - 0.0089 / 252))
largo = pd.Series(largo, ses)
print(f"diferencia máxima con lvol: "
      f"{(largo - etp['lvol']).abs().max():.5f}")
print(f"total 2014-2025: {largo.iloc[-1] / 100 - 1:.1%}")
anual = etp[["lvol", "ivol"]].resample("YE").last()
anual.loc[pd.Timestamp("2013-12-31")] = 100.0
anual = anual.sort_index().pct_change().iloc[1:]
anual.index = anual.index.year
(100 * anual).round(0).T
OUT [05]El ETP largo, año a año
diferencia máxima con lvol: 0.00005
total 2014-2025: -99.4%
fecha  2014  2015  2016  2017  2018  2019   2020  2021  2022  2023  2024  2025
lvol  -48.0  11.0 -34.0 -57.0  44.0 -85.0  114.0 -75.0  61.0 -61.0 -54.0  -4.0
ivol   45.0 -44.0  10.0  96.0 -91.0   NaN    NaN   NaN   NaN   NaN   NaN   NaN

La figura de la cabecera es esta tabla en el tiempo, en escala logarítmica. El ETP largo pierde un 99,4 % en total, con años de −85 % (2019) y −75 % (2021), los que siguen a una crisis, cuando el VORX baja desde niveles altos y la curva vuelve al contango, y subidas fuertes en los años de crisis (+114 % en 2020). Mantenerlo es pagar un seguro caro; quien lo compra para cubrirse tiene que acertar el momento.

El 5 de febrero de 2018 y el ETP inverso

El ETP inverso diario (ivol, que imita al XIV) da cada día −1 vez el rendimiento del índice de futuros, más el tipo y menos una comisión del 1,35 %. Mientras la curva está en contango, gana lo que pierde el largo: pasa de 100 a 221. Y tiene una cláusula de aceleración: si pierde más de un 80 % en un día, se liquida. La de los datos imita la del XIV real: según el aviso de Credit Suisse a la SEC del 6 de febrero de 2018, el valor indicativo intradía del XIV del 5 de febrero cayó al 20 % o menos del cierre anterior, lo que constituía un evento de aceleración; el último día de negociación sería el 20 de febrero y los tenedores cobrarían el valor indicativo de cierre de la fecha de valoración.

IN [06]python
dias = pd.concat([vx.rename("vorx"),
                  f1["precio"].rename("f1"), f2["precio"].rename("f2"),
                  etp], axis=1).loc["2018-01-31":"2018-02-08"]
dias["rend_indice"] = dias["indice_futuros_cp"].pct_change()
print(f"VORX al final de la muestra: {vx.iloc[-1]}")
dias.round(3)
OUT [06]Del 31 de enero al 8 de febrero de 2018
VORX al final de la muestra: 13.74
             vorx     f1     f2  indice_futuros_cp    lvol     ivol  rend_indice
fecha
2018-01-31  15.96  16.00  16.65             14.401  14.121  201.189          NaN
2018-02-01  17.44  17.15  16.95             15.041  14.748  192.256        0.044
2018-02-02  20.37  19.45  18.05             16.488  16.168  173.754        0.096
2018-02-05  36.78  41.65  31.45             31.479  30.868   15.780        0.909
2018-02-06  37.46  35.10  26.40             26.468  25.955      NaN       -0.159
2018-02-07  36.74  34.70  26.45             26.390  25.880      NaN       -0.003
2018-02-08  37.04  35.25  26.85             26.795  26.278      NaN        0.015

El 2 de febrero el índice de futuros ya sube un 9,6 %. El lunes 5 el VORX pasa de 20,37 a 36,78 y el primer futuro, de 19,45 a 41,65, por encima del propio índice: es la subida plantada del 22 % sobre el modelo. El índice de futuros sube un 90,9 % en un día, el ETP inverso cae de 173,75 a 15,78 y se liquida; desde el día 6 su serie está vacía. El largo, que casi duplica su valor ese día, devuelve una parte el día siguiente, cuando la subida plantada se deshace.

¿Por qué los futuros subirían más que el índice justo ese día? Por el rebalanceo de los propios productos. Un ETP con apalancamiento diario LL y valor AA tiene una exposición L⋅AL \cdot A. Si su índice sube un xx, su valor pasa a A(1+Lx)A(1 + Lx) y su exposición vale LA(1+x)LA(1 + x); para volver a LL veces su nuevo valor tiene que operar

LA(1+Lx)−LA(1+x)=L(L−1) x A.L A (1 + L x) - L A (1 + x) = L (L - 1)\, x\, A .

Para L=1L = 1 no opera; para L=2L = 2 o L=−1L = -1, L(L−1)=2>0L(L-1) = 2 > 0: los dos compran después de una subida, y los dos lo hacen al cierre, cuando se fija el precio de su índice.

IN [07]python
x = dias.loc["2018-02-05", "rend_indice"]
filas = {L: {"valor_tras_subida": 100 * (1 + L * x),
             "compra_de_futuros": 100 * L * (L - 1) * x}
         for L in (-1.0, -0.5, 1.0, 1.5, 2.0)}
pd.DataFrame(filas).T.round(1)
OUT [07]Rebalanceo forzado tras una subida del 90,9 %
      valor_tras_subida  compra_de_futuros
-1.0                9.1              181.8
-0.5               54.5               68.2
 1.0              190.9                0.0
 1.5              236.4               68.2
 2.0              281.8              181.8
síSube la volSuben futurosPierden inversosRecompranPierde 80 %Se liquida
Fuente Mermaid
flowchart TB
  S[Sube la vol] --> F[Suben futuros]
  F --> P[Pierden inversos]
  P --> R[Recompran]
  R --> F
  P --> A{Pierde 80 %}
  A -- sí --> Q[Se liquida]

Por cada 100 de valor antes de la subida, un inverso −1× tiene que recomprar 181,8 de futuros, 20 veces lo que le queda de valor (9,1). Un producto de −0,5× tiene que recomprar 68,2 y sobrevive con 54,5. Es la razón por la que ProShares cambió su SVXY de −1× a −0,5× al cierre del 27 de febrero de 2018, según la propia ficha del fondo. Cuando el tamaño de esos productos es grande frente al volumen de los futuros en la ventana de cierre, la compra empuja el precio, la subida aumenta las pérdidas y obliga a recomprar más. En los datos esa presión está plantada como el 22 % sobre el modelo; en el mercado real su tamaño es un dato que hay que estimar, no suponer.

Estrategias: vender, comprar y filtrar la volatilidad

Con los rendimientos diarios del índice de futuros se pueden comparar las estrategias básicas, todas sobre el nominal (vender 1 de futuros por cada 1 de capital, que queda como colateral; se mide el rendimiento en exceso del colateral). Vender siempre es el ETP inverso sin comisiones y sin cláusula de aceleración; a −0,5×, el SVXY posterior a 2018; y el filtro de contango solo vende cuando, al cierre anterior, el primer futuro está por encima del VORX:

IN [08]python
def medidas(x):
    x = x.iloc[1:]
    eq = (1 + x).cumprod()
    mes = (1 + x).resample("ME").prod() - 1
    return {"anual": eq.iloc[-1] ** (252 / len(x)) - 1,
            "vol": x.std() * np.sqrt(252),
            "sharpe": x.mean() / x.std() * np.sqrt(252),
            "caida_max": (eq / eq.cummax() - 1).min(),
            "peor_dia": x.min(), "peor_mes": mes.min(),
            "fecha_peor_dia": str(x.idxmin().date())}

corto = -rend
contango = (f1["precio"] > vx).reindex(ses).astype(float)
estr = {"vender siempre": corto, "vender a -0,5x": 0.5 * corto}
for lag in (1, 2, 3):
    estr[f"contango, señal t-{lag}"] = corto * contango.shift(lag)
cambios = contango.shift(1).diff().abs()
estr["contango t-1, coste 0,5 %"] = (corto * contango.shift(1)
                                     - 0.005 * cambios)
print(f"entradas y salidas al año: {cambios.sum() / 12:.0f}")
tab = pd.DataFrame({k: medidas(v.fillna(0)) for k, v in estr.items()}).T
num = tab.columns[:-1]
tab[num] = tab[num].astype(float).round(3)
tab
OUT [08]Venta de volatilidad: media, cola y retraso de la señal
entradas y salidas al año: 33
                           anual    vol  sharpe  caida_max  peor_dia  peor_mes fecha_peor_dia
vender siempre            -0.071  0.592   0.502     -0.989    -0.921    -0.964     2020-03-09
vender a -0,5x             0.101  0.296   0.502     -0.715    -0.460    -0.628     2020-03-09
contango, señal t-1        0.813  0.314   2.058     -0.433    -0.373    -0.332     2016-06-24
contango, señal t-2        0.784  0.313   2.016     -0.456    -0.373    -0.368     2016-06-24
contango, señal t-3        0.281  0.419   1.022     -0.937    -0.909    -0.923     2018-02-05
contango t-1, coste 0,5 %  0.522  0.315   1.499     -0.506    -0.373    -0.342     2016-06-24

Vender siempre da un Sharpe de 0,50 y una caída máxima del 98,9 %: el ETP inverso de antes, sin su liquidación. El peor día es el 2020-03-09 (−92,1 %) y el peor mes, marzo de 2020 (−96,4 %): quien vendía a 1× habría perdido prácticamente todo dos veces en la muestra. A −0,5× la caída máxima sigue siendo del 71,5 %. La venta de volatilidad de futuros es la venta de prima de la lección 3.6.1 con la cola más gruesa todavía: lo que se cobra es el roll, y lo que se arriesga es un salto del 90 % en una sesión.

Fig. — Venta del índice de futuros del VORX, capital mensual en escala logarítmica: siempre, con el filtro de contango del cierre anterior y con el mismo filtro tres sesiones más tarde (datos sintéticos, sin costes)

El filtro de contango con la señal del cierre anterior da un Sharpe de 2,06 y una caída máxima del 43,3 %, con el peor día el 2016-06-24. Es demasiado bueno, y la tabla dice por qué: con la señal de dos sesiones antes apenas cambia, pero con la de tres sesiones antes vende el 2018-02-05, pierde un 90,9 % ese día y su caída máxima pasa al 93,7 %. El filtro funciona en estos datos porque, en los dos grandes saltos del VORX de la muestra, el índice al contado sube uno o dos días antes que los futuros y la curva se invierte justo a tiempo de salir. Es una propiedad de cómo están generados los datos (el VORX se separa de su modelo y la diferencia se disipa en 10 días), no una ley del mercado. Con un coste de 0,5 % del nominal cada vez que la posición se abre o se cierra (unas 33 veces al año), el Sharpe baja a 1,50 y la caída máxima sube al 50,6 %.

La otra cara es comprar volatilidad como seguro. Una cartera que mantiene una parte en el ETP largo y el resto en el índice ORX con dividendos, rebalanceada cada mes:

IN [09]python
rt = ind.set_index("fecha")["cierre_rt"]
mens = (pd.concat([rt, etp["lvol"]], axis=1).resample("ME").last()
        .pct_change().dropna())
seguro = {}
for w in (0.0, 0.05, 0.10):
    p = (1 - w) * mens["cierre_rt"] + w * mens["lvol"]
    eq = (1 + p).cumprod()
    seguro[f"{w:.0%} en LVOL"] = {
        "anual": eq.iloc[-1] ** (12 / len(p)) - 1,
        "vol": p.std() * np.sqrt(12),
        "caida_max": (eq / eq.cummax() - 1).min(),
        "peor_mes": p.min()}
pd.DataFrame(seguro).T.round(3)
OUT [09]El ETP largo como seguro de una cartera
             anual    vol  caida_max  peor_mes
0% en LVOL   0.122  0.187     -0.366    -0.288
5% en LVOL   0.116  0.157     -0.269    -0.269
10% en LVOL  0.106  0.146     -0.249    -0.249

Con un 10 % en el ETP largo, la caída máxima de la cartera baja del 36,6 % al 24,9 % y el peor mes, del −28,8 % al −24,9 %. A cambio, la rentabilidad anual cae del 12,2 % al 10,6 %: 1,6 puntos al año durante doce años para recortar la peor caída. El seguro funciona porque se rebalancea cada mes (se vende lo que sube en las crisis) y porque las crisis de la muestra fueron cortas; con una crisis lenta, sin saltos de la volatilidad, el coste se paga igual y la cobertura apenas aparece.

VSTOXX y VIX: lo que se puede comparar

El VVGX de los datos imita al VSTOXX: la volatilidad a 30 días de un índice europeo ficticio con una varianza 1,2 veces la de ORX, rendimientos correlados 0,8 con él y ruido propio. Solo hay índice: ni cadena de opciones ni futuros.

IN [10]python
dif = vi["vvgx"] - vi["vorx"]
print(f"correlación de niveles: {vi['vorx'].corr(vi['vvgx']):.3f}; "
      f"de cambios diarios: "
      f"{vi['vorx'].diff().corr(vi['vvgx'].diff()):.3f}")
print(f"VVGX − VORX: media {dif.mean():.2f}, desv. {dif.std():.2f},"
      f" de {dif.min():.2f} a {dif.max():.2f} puntos")
vi[["vorx", "vvgx"]].describe().loc[["mean", "50%", "max"]].round(2)
OUT [10]VVGX frente a VORX
correlación de niveles: 0.992; de cambios diarios: 0.964
VVGX − VORX: media 1.50, desv. 1.22, de -3.89 a 6.97 puntos
       vorx   vvgx
mean  19.80  21.31
50%   17.66  19.05
max   73.98  72.48

El índice europeo cotiza de media 1,5 puntos por encima del de EE. UU., con una correlación de niveles de 0,99. Con un diferencial así se suele plantear un spread de volatilidad: comprar futuros del VSTOXX y vender del VIX cuando el diferencial está bajo, o al revés. Con estos datos no se puede contrastar, por tres razones: no hay futuros del VVGX; los futuros de las dos bolsas vencen en fechas distintas (cada uno 30 días antes del vencimiento de sus opciones) y liquidan con métodos distintos (la SOQ de Cboe frente a la media de 11:00 a 12:00 CET de Eurex); y el multiplicador y la divisa cambian (1.000 USD frente a 100 EUR por punto), así que la cobertura necesita un ratio y deja riesgo de divisa (lección 3.3.3).

Ejercicios

  1. Calcula un ETP largo de 2× diario sobre el índice de futuros (sin comisión ni tipo) y compáralo con dos veces el rendimiento del índice en todo el periodo. ¿Por qué no coinciden?
Solución
IN [11]python
doble = (1 + 2 * rend).cumprod()
print(f"índice en el periodo: {indice.iloc[-1] / 100 - 1:.2%}")
print(f"2x diario: {doble.iloc[-1] - 1:.2%}")
print(f"2x del periodo (imposible por debajo de -100 %): "
      f"{2 * (indice.iloc[-1] / 100 - 1):.2%}")
print(f"máximo del 2x diario: {doble.max():.2f} el "
      f"{doble.idxmax().date()}")
OUT [11]Apalancamiento diario y rendimiento del periodo
índice en el periodo: -99.51%
2x diario: -100.00%
2x del periodo (imposible por debajo de -100 %): -199.02%
máximo del 2x diario: 1.08 el 2014-04-22

El 2× diario queda en prácticamente cero (su máximo, 1,08, fue en abril de 2014). Multiplica por 2 cada rendimiento diario, no el del periodo. Con un índice muy volátil y con tendencia a la baja, el producto de los (1+2rt)(1 + 2r_t) cae mucho más deprisa que el índice: la pérdida por volatilidad crece con el cuadrado del apalancamiento. Por eso los folletos de estos productos dicen que su objetivo es de un solo día.

  1. Repite la regresión del roll yield con el segundo futuro (orden == 1). ¿Es el coeficiente mayor o menor que en el primero?
Solución
IN [12]python
g2 = fu[fu["orden"] == 1].set_index("fecha")
g2 = g2.assign(roll=(g2["precio"] - vx.reindex(g2.index))
               / g2["dias"],
               d_futuro=g2["siguiente"] - g2["precio"]).dropna()
m2 = sm.OLS(g2["d_futuro"], sm.add_constant(g2["roll"])).fit(
    cov_type="HAC", cov_kwds={"maxlags": 5})
print(f"coeficiente {m2.params['roll']:.2f}, "
      f"t {m2.tvalues['roll']:.1f}")
OUT [12]Roll del segundo futuro
coeficiente -1.48, t -4.3

El coeficiente es parecido (−1,48 frente a −1,56, los dos con t = −4,3): el segundo futuro también baja con su roll. Su base frente al VORX al contado es, aun así, una medida más indirecta, porque le faltan más de 30 días para converger y antes ocupa el lugar del primero; con tan poca diferencia entre los dos coeficientes, los datos no permiten decir que uno sea mayor que el otro.

  1. Un inversor quiere «comprar el VIX» porque cree que habrá una crisis en algún momento de los próximos tres años y propone mantener un ETP largo de volatilidad. Explica qué le pasará si tiene razón en la crisis pero no en el momento.
Solución

El ETP largo no sigue al VIX: sigue a un índice de futuros que rueda en contango. Mientras la crisis no llega, pierde cada año una fracción grande de su valor (en los datos del curso, entre el 4 % y el 85 % en los años que baja). Si la crisis llega en el tercer año, el ETP sube mucho en porcentaje, pero sobre un valor que ya ha perdido la mayor parte: en los datos, tras perder un 85 % en 2019, el +114 % de 2020 deja el ETP muy por debajo de donde estaba a principios de 2019. La alternativa coherente con su idea es comprar opciones con vencimiento lejano (calls sobre futuros de volatilidad o puts del índice), cuyo coste se conoce al comprarlas, o mantener una parte pequeña rebalanceada como en la cartera de esta lección.

Footnotes

  1. Barclays Bank PLC, folleto (free writing prospectus) del iPath S&P 500 VIX Short-Term Futures ETN (VXX), 2 de diciembre de 2009, en la SEC: https://www.sec.gov/Archives/edgar/data/312070/000119312509245713/dfwp.htm. Describe el índice como una posición larga que rueda a diario del primer al segundo futuro mensual del VIX, con vencimiento constante de un mes, y una comisión anual del 0,89 %. ↩ ↩2

Respuesta plegada en cada pregunta

Autoevaluación

  1. ¿Por qué no existe un ETP que replique el VIX al contado?

    • APorque está prohibido por la SEC
    • BPorque el VIX es un cálculo sobre los precios de opciones del S&P 500 a 30 días que no se puede mantener como cartera estática: lo replicable son los futuros, que convergen a él solo al vencer
    • CPorque el VIX solo se calcula una vez al día
    • DPorque las opciones del S&P 500 no tienen liquidez suficiente
    Ver respuesta

    Respuesta B. Porque el VIX es un cálculo sobre los precios de opciones del S&P 500 a 30 días que no se puede mantener como cartera estática: lo replicable son los futuros, que convergen a él solo al vencer

    El VIX mide la volatilidad esperada a 30 días con una cesta de opciones que cambia cada día (strikes y vencimientos). Los productos cotizados tienen futuros, y un futuro sobre el VIX vale la expectativa del VIX en su vencimiento, no el VIX de hoy.

  2. En los datos, el primer futuro está por encima del VORX el 63 % de las sesiones. ¿Qué le pasa de media a quien mantiene un largo en el primer futuro?

    • AGana el roll yield, porque el futuro sube hacia el índice
    • BPierde: en contango el futuro tiende a bajar hacia el índice al acercarse el vencimiento, y la regresión de la lección da un coeficiente de −1,56 sobre el roll diario, mientras que el índice no se mueve de forma predecible
    • CNada: futuro e índice se mueven igual
    • DGana solo si el índice sube
    Ver respuesta

    Respuesta B. Pierde: en contango el futuro tiende a bajar hacia el índice al acercarse el vencimiento, y la regresión de la lección da un coeficiente de −1,56 sobre el roll diario, mientras que el índice no se mueve de forma predecible

    La base predice el cambio del futuro (t = −4,3) y no el del índice (t = 1,0). Es la misma conclusión que Simon y Campasano (2014) sacan del VIX real de 2006 a 2011: la base es sobre todo una prima que se cobra vendiendo futuros en contango.

  3. Un ETP inverso diario (−1×) tiene un valor de 100 y su índice sube un 90,9 % en un día. ¿Cuánto índice tiene que recomprar al cierre para volver a −1×?

    • ANada: los inversos no rebalancean
    • B9,1, lo que le queda de valor
    • C181,8: el corto vale ahora 190,9 y el objetivo es 9,1; recomprar es comprar futuros justo después de la subida
    • D90,9
    Ver respuesta

    Respuesta C. 181,8: el corto vale ahora 190,9 y el objetivo es 9,1; recomprar es comprar futuros justo después de la subida

    Con apalancamiento L, la compra de rebalanceo es L·(L − 1)·x por unidad de valor. Con L = −1 y x = 0,909, 2·0,909 = 1,818 veces el valor previo. Los inversos y los apalancados compran después de las subidas, lo que empuja el precio en la misma dirección.

  4. La venta del índice de futuros solo cuando el primer futuro está en contango da un Sharpe de 2,06 en los datos. ¿Qué la invalida como evidencia?

    • ANada: el filtro de contango funciona
    • BQue con la señal de tres sesiones antes en vez de la de ayer cae un 90,9 % el 2018-02-05 y su caída máxima pasa del 43 % al 94 %: el resultado depende de esquivar por uno o dos días un salto plantado en datos sintéticos
    • CQue el Sharpe se calcula con rendimientos diarios
    • DQue no incluye el dividendo del índice
    Ver respuesta

    Respuesta B. Que con la señal de tres sesiones antes en vez de la de ayer cae un 90,9 % el 2018-02-05 y su caída máxima pasa del 43 % al 94 %: el resultado depende de esquivar por uno o dos días un salto plantado en datos sintéticos

    Un resultado que cambia de forma radical con uno o dos días de retraso está ajustado a unos pocos episodios. En los datos sintéticos, el VORX sube antes de los saltos y la curva se invierte un día antes; en un mercado real nada garantiza ese aviso, y la venta de volatilidad sigue siendo corta de cola.

  5. ¿Qué permiten hacer con el VSTOXX los datos del curso?

    • ABacktestear sus futuros, como los del VORX
    • BComparar su nivel con el del VORX (el índice VVGX), pero no backtestear sus futuros: el archivo solo trae el índice
    • CNada, no hay datos europeos
    • DReconstruir el VSTOXX desde opciones del Euro Stoxx 50
    Ver respuesta

    Respuesta B. Comparar su nivel con el del VORX (el índice VVGX), pero no backtestear sus futuros: el archivo solo trae el índice

    vol3_indices.csv trae vvgx, la volatilidad a 30 días de un índice europeo ficticio, sin cadena ni futuros. Las reglas de los futuros del VSTOXX (Eurex, FVS) se pueden explicar, pero no contrastar con estos datos.

Ideas clave

  • El VIX y el VSTOXX se calculan con opciones a 30 días y no se pueden mantener en cartera; se negocian futuros que liquidan al índice en su vencimiento (Cboe: Special Opening Quotation; Eurex: media de 11:00 a 12:00 CET).
  • La curva de futuros está en contango casi siempre (el 63 % de las sesiones con el primer futuro sobre el VORX, el 71 % con el segundo sobre el primero) y se invierte en las crisis; la base predice el cambio del futuro, no el del índice.
  • Un índice que rueda a diario del primer al segundo futuro pierde en contango: el ETP largo cae un 99,4 % de 2014 a 2025 y solo gana en las crisis.
  • El ETP inverso diario gana mientras dura y pierde un 90,9 % el 2018-02-05: los productos inversos y apalancados tienen que comprar después de las subidas, y su cláusula de aceleración los liquida.
  • Vender volatilidad tiene un Sharpe de 0,50 con una caída máxima del 98,9 %; los filtros de contango mejoran mucho el resultado en estos datos, pero dependen de esquivar por uno o dos días los saltos.

Recursos