Lección 3.7.2 · 75 min

Arbitraje de funding, basis con futuros y arbitraje entre exchanges

El cash-and-carry cobra el funding del perpetuo o fija el basis del trimestral sin apostar por el precio. Esta lección mide cuánto pagó en cuatro exchanges sintéticos y cuánto se estrechó, qué cuesta en margen y en liquidaciones, cuándo conviene fijar el basis y qué queda de todo cuando el exchange que pagaba más quiebra.

Fig. — Funding cobrado cada año por el corto de un cash-and-carry de XBQ en los cuatro exchanges, en % del nominal (2022 de dedalo, hasta su quiebra)
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)

Tres formas de cobrar el carry

La lección 2.3.7 presentó el cash-and-carry: comprar la moneda al contado y vender la misma cantidad en un derivado, de modo que el precio no importe y quede el carry. Con los datos del nivel 3 se puede hacer con cuatro exchanges y dos activos, con perpetuos y con trimestrales, y medir lo que la 2.3.7 solo enumeró: cuánto margen pide la pata corta, cuándo se liquida, cuándo conviene el futuro y qué pasa cuando el exchange quiebra. Hay tres variantes:

Contado largoPerpetuo cortoTrimestral cortoPerp. otro exch.Funding variableBasis fijadoDos contrapartes
Fuente Mermaid
flowchart TB
  C[Contado largo] --> P[Perpetuo corto]
  C --> T[Trimestral corto]
  C --> O[Perp. otro exch.]
  P --> F[Funding variable]
  T --> B[Basis fijado]
  O --> R[Dos contrapartes]
  • Con el perpetuo. Se cobra el funding de cada periodo, que cambia y puede volverse negativo.
  • Con el trimestral. El basis queda fijado al abrir: al vencimiento el futuro liquida al índice y el resultado es la diferencia inicial, haga lo que haga el funding.
  • Repartido entre exchanges. El contado en uno y el derivado en otro, o el derivado en el que más paga. Gana algo de carry o de margen y añade una contraparte.
IN [01]python
import numpy as np
import pandas as pd

fu = pd.read_parquet("cripto3_funding.parquet")
carry = (100 * fu.groupby(["activo", "exchange",
                           fu["ts"].dt.year])["tasa_funding"]
         .sum()).unstack()
print("funding cobrado por el corto, % del nominal por año:")
print(carry.round(1).to_string())
suelo = 100 * 0.0001 * 3 * 365
print(f"suelo del término de interés: {suelo:.2f} % al año")
OUT [01]El carry del perpetuo por exchange y año
funding cobrado por el corto, % del nominal por año:
ts               2020  2021  2022  2023  2024  2025
activo exchange
XBQ    alfa      25.6  24.4  10.4  11.8  11.2   9.7
       boreal    28.7  26.4  11.4  13.3  12.2  10.5
       cenit     23.7  23.0   8.8  10.8   9.9   8.8
       dedalo    29.8  28.7   7.5   NaN   NaN   NaN
XEQ    alfa      52.9  38.3  11.7  12.4  10.9   9.4
       boreal    55.5  40.0  13.4  13.8  11.9  10.4
       cenit     49.9  35.6   9.6  11.8  10.2   8.6
       dedalo    59.5  42.8  10.1   NaN   NaN   NaN
suelo del término de interés: 10.95 % al año

La tabla es lo que cobró el corto del perpetuo cada año, en % del nominal, sin costes ni capitalización. En XBQ, del 23,0 % al 29,8 % en 2020 y 2021 según el exchange; desde 2022, entre el 8,8 % y el 13,3 % en los tres que sobreviven. XEQ paga el doble en los años de euforia (del 49,9 % al 59,5 % en 2020) y casi lo mismo que XBQ después. La figura de la cabecera dibuja las líneas de XBQ. Dos cosas destacan: dedalo es el que más paga mientras existe, y desde 2022 todos los demás se quedan pegados al suelo del 10,95 % que fija el término de interés de la fórmula (0,01 %×3×3650{,}01\,\% \times 3 \times 365, lección 3.7.1).

Ese suelo merece atención. No es el tipo de interés del dólar ni el resultado de una oferta y una demanda: es una constante de la fórmula del exchange, la que paga un largo mientras la prima está dentro de la banda. El carry «de mercado» es lo que hay por encima, y en los datos está plantado como una prima alcista que se va estrechando con una vida media de 2,5 años (más capital dedicado a arbitrarla). ¿Se recupera esa vida media?

IN [02]python
from scipy.optimize import curve_fit

a = fu[(fu["exchange"] == "alfa") & (fu["activo"] == "XBQ")]
a = a.set_index("ts")
r7 = np.log(a["precio_indice"] / a["precio_indice"].shift(21))
z = np.tanh(r7 / 0.15)                   # euforia: z cerca de 1
d = pd.DataFrame({"prima": a["prima_media"], "z": z}).dropna()
d["anos"] = (d.index - d.index[0]).days / 365.25
eu = d[d["z"] > 0.5]


def prima_alcista(X, amp, vida):
    anos, z = X
    return amp * np.exp(-np.log(2) * anos / vida) * z ** 2


(amp, vida), _ = curve_fit(prima_alcista, (eu["anos"], eu["z"]),
                           eu["prima"], p0=[0.003, 2.0])
print(f"{len(eu)} periodos de euforia; amplitud {1e4 * amp:.1f} pb,"
      f" vida media {vida:.2f} años")
print((1e4 * eu["prima"] / eu["z"] ** 2).groupby(eu.index.year)
      .mean().round(1).to_dict())
OUT [02]Cuánto se estrecha la prima alcista
1091 periodos de euforia; amplitud 33.7 pb, vida media 2.53 años
{2020: 29.0, 2021: 23.1, 2022: 15.8, 2023: 14.2, 2024: 10.0, 2025: 7.2}

En los 1.091 periodos de euforia (rendimiento de 7 días alto, tanh⁡(r7/0,15)>0,5\tanh(r_7/0{,}15) > 0{,}5), un ajuste no lineal recupera una amplitud de 33,7 puntos básicos por periodo y una vida media de 2,53 años, frente a los 35 y 2,5 plantados. La prima por unidad de euforia baja de 29,0 puntos básicos en 2020 a 7,2 en 2025. Los datos no son la realidad, pero la dirección coincide con lo que documentan He, Manela, Ross y von Wachter: las desviaciones de los perpetuos frente a su precio sin arbitraje se han ido reduciendo con el tiempo1Nota 1 · S. He, A. Manela, O. Ross y V. von Wachter, «Fundamentals of Perpetual Futures», arXiv 2212.06888 (versión 1 de diciembre de 2022, revisada después). El resumen dice que las desviaciones son mayores que en los mercados de divisas, se mueven juntas entre monedas y se reducen con el tiempo; la lección no cita cifras del artículo..

La pata corta necesita margen

El cash-and-carry no tiene riesgo de precio en el papel, pero el capital no es solo el contado. La pata corta pide margen, y con margen aislado se liquida si el mark sube hasta su precio de liquidación, aunque el contado haya ganado lo mismo (lección 3.7.1). Con apalancamiento LL en esa pata, el capital por unidad de nominal es 1+1/L1 + 1/L y el rendimiento sobre el capital, el carry dividido por esa cantidad. Más apalancamiento sube el rendimiento y acerca la liquidación. Las barras de 1 hora de alfa permiten contar cuántas veces habría ocurrido si cada semana (o cada mes) se repusiera el margen y se reabriera la pata corta al precio de ese momento:

IN [03]python
h1 = pd.read_parquet("cripto3_1h.parquet")
b = h1[h1["activo"] == "XBQ"].set_index("ts")
f_alfa = a["tasa_funding"]
anual = f_alfa.sum() / ((f_alfa.index[-1] - f_alfa.index[0]).days
                        / 365.25)
MMR = 0.005
filas = []
for L in (1, 2, 3, 5, 10, 20):
    fila = {"apal_corto": L,
            "rend_capital_pct": 100 * anual / (1 + 1 / L)}
    for nombre, frec in (("semanal", "7D"), ("mensual", "30D")):
        g = b.groupby(pd.Grouper(freq=frec))
        liq = g["apertura"].first() * (1 + 1 / L) / (1 + MMR)
        fila[f"liq_{nombre}"] = int((g["mark_maximo"].max() >= liq)
                                    .sum())
    filas.append(fila)
print(f"carry medio de alfa, XBQ: {100 * anual:.1f} % del nominal")
pd.DataFrame(filas).set_index("apal_corto").round(1)
OUT [03]Apalancamiento de la pata corta: rendimiento y liquidaciones
carry medio de alfa, XBQ: 15.5 % del nominal
            rend_capital_pct  liq_semanal  liq_mensual
apal_corto
1                        7.8            0            0
2                       10.4            0            2
3                       11.6            1            9
5                       12.9            8           28
10                      14.1           71           52
20                      14.8          180           60
Fig. — Cash-and-carry de XBQ en alfa según el apalancamiento de la pata corta: rendimiento anual sobre el capital sin costes y semanas en las que el mark habría liquidado el corto (rebalanceo semanal, 2020-2025)

El carry medio de XBQ en alfa es del 15,5 % anual del nominal. Sin apalancamiento en el corto (1x), el capital se duplica y el rendimiento cae al 7,8 %; con 3x, un 11,6 %, y en seis años el mark solo habría liquidado el corto una semana; con 10x, un 14,1 %, pero 71 semanas de 314 terminan con el corto liquidado y el contado sin cubrir. Con rebalanceo mensual el riesgo crece en los apalancamientos bajos (9 liquidaciones a 3x frente a 1): en 30 días el precio tiene más tiempo para subir antes de que se reponga el margen. Las cifras de 10x y 20x mensuales son menores solo porque hay menos meses que semanas. El gráfico resume el intercambio: los últimos puntos de rendimiento se pagan con un número de liquidaciones que crece mucho más deprisa.

Los costes también cuentan. Entrar y salir paga cuatro lados (comprar y vender contado, vender y recomprar el perpetuo). Con un supuesto de 5 puntos básicos por lado, del orden de la comisión de un cliente que toma liquidez en un exchange grande (lección 2.4.7), cuesta:

IN [04]python
COMISION = 5 / 1e4          # supuesto: 5 pb por lado y pata
lados = 4                   # comprar y vender contado y perpetuo
for nombre, diario in [("suelo (0,03 % diario)", 0.0003),
                       ("media de 2025", carry.loc[("XBQ", "alfa"),
                                                   2025] / 100 / 365)]:
    dias = lados * COMISION / diario
    print(f"{nombre}: {dias:.1f} días de carry para pagar la entrada"
          " y la salida")
OUT [04]Lo que cuesta entrar y salir
suelo (0,03 % diario): 6.7 días de carry para pagar la entrada y la salida
media de 2025: 7.5 días de carry para pagar la entrada y la salida

Unos 7 días de carry al suelo, 7,5 al ritmo de 2025. Un cash-and-carry que se abre y se cierra a menudo, por ejemplo cada vez que el funding de una semana baja (ejercicio de la lección 2.3.7), se come el carry en comisiones.

El basis de los trimestrales

cripto3_futuros.parquet tiene una foto diaria, a las 00:00 UTC, de los dos trimestrales más cercanos de cada exchange y activo; vencen el último viernes de marzo, junio, septiembre y diciembre a las 08:00 UTC. El basis anual se mide con el índice de la misma hora, como ln⁡(F/S)×365/dias\ln(F/S) \times 365/\text{dias}:

IN [05]python
ft = pd.read_parquet("cripto3_futuros.parquet")
ind = (fu[fu["exchange"] == "alfa"]
       .set_index(["ts", "activo"])["precio_indice"])
ft = ft.join(ind, on=["ts", "activo"]).dropna(subset=["precio_indice"])
ft["basis"] = np.log(ft["precio"] / ft["precio_indice"]) * 365 \
    / ft["dias"]
vivos = ft[ft["exchange"] != "dedalo"]
err = 100 * (vivos["basis"] - vivos["basis_anual_modelo"]).abs()
print(f"error frente al del modelo (puntos): mediana {err.median():.4f}"
      f", máximo {err.max():.2f}, máximo a más de 10 días "
      f"{err[vivos['dias'] > 10].max():.2f}")
x = vivos[(vivos["exchange"] == "alfa") & (vivos["activo"] == "XBQ")]
orden = x.groupby("ts").cumcount()
primero, segundo = x[orden == 0], x[orden == 1]
print("basis medio del primer trimestral, % anual:")
print((100 * primero.groupby(primero["ts"].dt.year)["basis"].mean())
      .round(1).to_dict())
dif = (segundo.set_index("ts")["basis"] - primero.set_index("ts")
       ["basis"])
print(f"segundo menos primero: {100 * dif.mean():+.2f} puntos")
OUT [05]El basis medido en los trimestrales
error frente al del modelo (puntos): mediana 0.0029, máximo 1.33, máximo a más de 10 días 0.26
basis medio del primer trimestral, % anual:
{2020: 22.3, 2021: 23.1, 2022: 10.9, 2023: 11.9, 2024: 11.1, 2025: 9.2}
segundo menos primero: +0.40 puntos

El basis medido coincide con la columna del modelo con una mediana de 0,003 puntos; el error máximo, de 1,33 puntos anuales, aparece en los últimos días antes del vencimiento, cuando el redondeo del precio al tick se multiplica por 365 entre unos pocos días (a más de 10 días, 0,26). El basis medio del primer trimestral de XBQ en alfa es del 22,3 % y el 23,1 % en 2020 y 2021, y del 9,2 % al 11,9 % después, a la par del funding. El segundo trimestral cotiza 0,40 puntos anuales por encima del primero: la prima plantada por el plazo.

La pregunta práctica es si conviene fijar el basis o cobrar el funding. Para cada trimestral, se abre el cash-and-carry cuando le quedan unos 95 días y se compara el basis fijado (en % del nominal para todo el trimestre) con el funding que habría cobrado el perpetuo desde ese día hasta el vencimiento:

IN [06]python
def trimestres(fut, fund):
    """Por contrato: basis fijado a <= 95 días del vencimiento, funding
    cobrado hasta el vencimiento y el de los 90 días previos (%)."""
    filas = []
    for contrato, c in fut.groupby("contrato"):
        ent = c[c["dias"] <= 95].head(1)
        if ent.empty:
            continue
        e0 = ent.iloc[0]
        t0 = e0["ts"]
        vto = (pd.Timestamp(e0["vencimiento"]).tz_localize("UTC")
               + pd.Timedelta(hours=8))
        if t0 < pd.Timestamp("2020-02-01", tz="UTC") or vto.year > 2025:
            continue
        hasta_vto = fund[(fund.index > t0) & (fund.index <= vto)].sum()
        previo = fund[(fund.index > t0 - pd.Timedelta(days=90))
                      & (fund.index <= t0)].sum()
        filas.append({"contrato": contrato,
                      "fijado": 100 * np.log(e0["precio"]
                                             / e0["precio_indice"]),
                      "funding": 100 * hasta_vto,
                      "funding_previo": 100 * previo})
    return pd.DataFrame(filas).set_index("contrato")


q = trimestres(x, f_alfa)
print(q.round(2).head(8).to_string())
print(f"{len(q)} trimestres; media fijada {q['fijado'].mean():.2f} %,"
      f" funding cobrado {q['funding'].mean():.2f} %, correlación "
      f"{q['fijado'].corr(q['funding']):.2f}")
elige = np.where(q["fijado"] > q["funding_previo"], q["fijado"],
                 q["funding"])
print(f"regla «el mayor de los dos al abrir»: {elige.mean():.2f} % "
      f"por trimestre")
OUT [06]Fijar el basis o cobrar el funding, trimestre a trimestre
            fijado  funding  funding_previo
contrato
XBQ-200626    2.04     8.94            2.81
XBQ-200925    2.15     4.49            8.81
XBQ-201225    1.23     8.87            4.37
XBQ-210326   11.98    14.12            8.52
XBQ-210625    1.00     3.76           13.68
XBQ-210924    2.51     4.05            3.73
XBQ-211231   15.55     2.90            4.75
XBQ-220325    3.58     2.27            4.19
23 trimestres; media fijada 3.97 %, funding cobrado 3.97 %, correlación 0.24
regla «el mayor de los dos al abrir»: 5.14 % por trimestre
Fig. — Basis fijado al abrir un cash-and-carry con el futuro trimestral frente al funding que habría cobrado el perpetuo en el mismo trimestre (alfa, XBQ, 23 trimestres)

En 23 trimestres, la media del basis fijado es del 3,97 % por trimestre y la del funding cobrado, también del 3,97 %. Fijar no gana ni pierde de media: elimina la incertidumbre. La correlación entre los dos es de solo 0,24, y la figura enseña por qué: un trimestre cualquiera uno gana al otro por varios puntos. El trimestral que vence en diciembre de 2021 fijó un 15,55 % y el funding de ese trimestre dio un 2,90 %; el que vencía en junio de 2020 fijó un 2,04 % mientras el funding daba un 8,94 %.

Como el basis de los datos lleva un ruido propio que no anticipa el funding siguiente, una regla sin información del futuro lo aprovecha: fijar el basis si es mayor que el funding de los 90 días anteriores y, si no, quedarse con el perpetuo. Da un 5,14 % por trimestre. Es el ejercicio 3; antes de creerlo en mercados reales haría falta comprobar si allí el ruido del basis es independiente del funding futuro, y con 23 observaciones por par el error típico es grande.

Entre exchanges: diferenciales de funding y dislocaciones

Cada exchange calcula su funding con su prima. Si uno paga sistemáticamente más que otro, se puede estar corto en el perpetuo del que paga más y largo en el del que paga menos, sin contado: el diferencial de funding.

IN [07]python
p = fu[fu["activo"] == "XBQ"].pivot(index="ts", columns="exchange",
                                     values="tasa_funding")
dif = 100 * p.sub(p["alfa"], axis=0).drop(columns="alfa")
print("diferencia con alfa, puntos de % por año:")
print(dif.groupby(dif.index.year).sum(min_count=1).round(2).T
      .to_string())
diferencial = p["boreal"] - p["cenit"]
print(f"periodos en que boreal paga lo mismo que cenit: "
      f"{100 * (diferencial.abs() < 1e-9).mean():.1f} %")
OUT [07]El funding de cada exchange frente al de alfa
diferencia con alfa, puntos de % por año:
ts        2020  2021  2022  2023  2024  2025
exchange
boreal    3.03  1.99  1.05  1.42  0.98  0.86
cenit    -1.93 -1.44 -1.59 -1.05 -1.32 -0.87
dedalo    4.19  4.33 -1.72   NaN   NaN   NaN
periodos en que boreal paga lo mismo que cenit: 71.4 %

boreal paga 3,03 puntos al año más que alfa en 2020 y 0,86 en 2025; cenit, entre 0,87 y 1,93 menos todos los años; dedalo, 4,19 y 4,33 más en 2020 y 2021. La prima plantada de cada exchange es constante (medio punto básico más en boreal, medio menos en cenit), pero el diferencial se estrecha cada año. La razón es la banda de la fórmula: el 71,4 % de los periodos boreal y cenit pagan exactamente lo mismo, el punto básico fijo. La diferencia de primas solo pasa al funding cuando la prima sale de la banda, en las semanas de euforia, y esas son cada vez menos rentables. El ejercicio 2 calcula lo que queda tras los costes.

Las dislocaciones son otra cosa: el precio de contado de un exchange se separa del de los demás durante unas horas. En los datos hay cuatro plantadas; los cierres diarios publicados dejan ver dos:

IN [08]python
cd = pd.read_parquet("cripto3_diario.parquet")
xb = cd[cd["activo"] == "XBQ"]
sp = xb.pivot(index="fecha", columns="exchange", values="cierre_spot")
ok = xb.pivot(index="fecha", columns="exchange",
              values="retiradas_abiertas")
indice = sp.where(ok == True).median(axis=1)
desv = 100 * np.log(sp.div(indice, axis=0))
for e in ["alfa", "boreal", "cenit"]:
    m = desv[e].abs()
    print(f"{e}: desviación típica {desv[e].std():.3f} %, peor día "
          f"{m.idxmax():%Y-%m-%d} ({desv[e][m.idxmax()]:+.2f} %)")
OUT [08]Dislocaciones entre exchanges en los datos publicados
alfa: desviación típica 0.092 %, peor día 2025-10-10 (-3.96 %)
boreal: desviación típica 0.035 %, peor día 2020-01-23 (+0.14 %)
cenit: desviación típica 0.122 %, peor día 2020-03-12 (-5.45 %)

Fuera de esos días, el contado de cada exchange se separa del índice una desviación típica de entre 0,035 % y 0,122 %, menos que cualquier comisión. Los dos episodios grandes son el del 12 de marzo de 2020 en cenit (−5,45 %) y el del 10 de octubre de 2025 en alfa (−3,96 %), los dos en plena caída. Aprovecharlos exige comprar en el exchange barato y vender en los demás al mismo tiempo, lo que solo se puede hacer con inventario ya colocado en los dos sitios: no hay tiempo de mover monedas o dólares de un exchange a otro mientras dura. Y ocurren cuando los libros están más finos, las retiradas más congestionadas y el riesgo de que el exchange barato tenga un problema real es mayor. Una dislocación puede ser una oportunidad o el primer síntoma de una quiebra.

Riesgo de contraparte: la quiebra de dedalo

dedalo fue, hasta noviembre de 2022, el exchange que mejor pagaba. La cronología de su quiebra está en cripto3_exchanges.csv y se inspira en la de FTX, sin copiarla:

6 nov.8 nov. 12:0011 nov. 14:0011 nov. 23:00NormalRumoresSuspensionCeseQuiebra
Fuente Mermaid
stateDiagram-v2
  [*] --> Normal
  Normal --> Rumores: 6 nov.
  Rumores --> Suspension: 8 nov. 12:00
  Suspension --> Cese: 11 nov. 14:00
  Cese --> Quiebra: 11 nov. 23:00
  Quiebra --> [*]

En la suspensión, las retiradas se cierran y los saldos dejan de ser convertibles; el contado de dedalo cotiza con un descuento creciente y sale del índice; el funding se vuelve muy negativo; a las 14:00 del 11 cesa la negociación y, para el curso, los saldos y las posiciones valen cero.

IN [09]python
ded = (fu[(fu["exchange"] == "dedalo") & (fu["activo"] == "XBQ")]
       .set_index("ts"))
hasta = pd.Timestamp("2022-11-08 08:00", tz="UTC")
c_ded = ded["tasa_funding"][:hasta].sum()
c_alfa = f_alfa[:hasta].sum()
anos = (hasta - ded.index[0]).days / 365.25
print(f"carry acumulado hasta el {hasta:%Y-%m-%d}: dedalo "
      f"{100 * c_ded:.1f} %, alfa {100 * c_alfa:.1f} % del nominal")
print(f"prima de dedalo: {100 * (c_ded - c_alfa) / anos:.2f} puntos"
      " al año")
ded[ded.index >= "2022-11-08"][["precio_indice", "ultimo",
                                "tasa_funding"]].head(7)
OUT [09]El carry de dedalo y su final
carry acumulado hasta el 2022-11-08: dedalo 69.3 %, alfa 59.2 % del nominal
prima de dedalo: 3.53 puntos al año
                           precio_indice   ultimo  tasa_funding
ts
2022-11-08 00:00:00+00:00        22086.5  22098.6      0.000100
2022-11-08 08:00:00+00:00        22055.8  22068.4      0.000100
2022-11-08 16:00:00+00:00        20037.7  20012.2     -0.002016
2022-11-09 00:00:00+00:00        19958.3  19190.9     -0.003800
2022-11-09 08:00:00+00:00        19623.3  18367.6     -0.002295
2022-11-09 16:00:00+00:00        21563.9  20084.3     -0.004368
2022-11-10 00:00:00+00:00        19746.2  17699.2     -0.003066

Hasta el 8 de noviembre de 2022, el corto del perpetuo de XBQ cobró en dedalo un 69,3 % del nominal y en alfa un 59,2 %: una prima de 3,53 puntos al año por estar en dedalo. La tabla enseña cómo acaba. El 8 a las 16:00, cuatro horas después de suspender las retiradas, el perpetuo de dedalo ya cotiza algo por debajo del índice y el funding es de −0,20 % por periodo: ahora pagan los cortos. Al día siguiente el descuento es del 3,8 % y el funding, del −0,38 %.

Fig. — Quiebra plantada de dedalo: prima del último precio de su perpetuo de XBQ sobre el índice (arriba) y funding de cada periodo de 8 horas (abajo), del 5 al 11 de noviembre de 2022

La figura sigue el episodio entero: el perpetuo de dedalo pegado al índice hasta la suspensión y un descuento que llega al 17 % el día 11; el funding, de un punto básico antes a entre −20 y −50 puntos básicos por periodo después, con un periodo en el tope de −50 puntos básicos. Nada en los precios ni en el funding de los días anteriores avisaba. ¿Qué queda de un cash-and-carry según cómo se hubiera repartido el capital?

IN [10]python
L = 3
capital = 1 + 1 / L            # por unidad de nominal: contado + margen
retirado = ded["tasa_funding"][:"2022-10-31"].sum()  # a fin de mes
c = {e: fu[(fu["exchange"] == e) & (fu["activo"] == "XBQ")]
     .set_index("ts")["tasa_funding"][:hasta].sum()
     for e in ["alfa", "boreal", "cenit"]}
escenarios = {
    "todo en dedalo, sin retirar": 0.0,
    "todo en dedalo, retirando cada mes": retirado,
    "un cuarto en cada exchange": (3 * capital + sum(c.values())
                                   + retirado) / 4,
    "todo en alfa": capital + c["alfa"],
}
for k, v in escenarios.items():
    print(f"{k:36s} {v / capital:6.2f} veces el capital")
riesgo = (c_ded - c_alfa) / anos / capital
print(f"prima de dedalo sobre el capital: {100 * riesgo:.1f} % al año")
OUT [10]Cuatro formas de repartir el riesgo de contraparte
todo en dedalo, sin retirar            0.00 veces el capital
todo en dedalo, retirando cada mes     0.52 veces el capital
un cuarto en cada exchange             1.22 veces el capital
todo en alfa                           1.44 veces el capital
prima de dedalo sobre el capital: 2.6 % al año

Las cuatro cifras son el capital final, a 11 de noviembre de 2022, por unidad de capital inicial, con el corto a 3x y sin costes. Con todo en dedalo y sin retirar beneficios, cero: el contado, el margen y casi tres años de carry. Si se retiraba el carry a fin de cada mes, queda un 0,52, el carry sacado; el capital se pierde. Repartido a partes iguales entre los cuatro exchanges, un 1,22: la cuarta parte de dedalo se pierde y el resto cobra. Todo en alfa, 1,44. La prima de dedalo, 3,53 puntos de nominal al año, es un 2,6 % anual del capital: es la probabilidad de quiebra anual que esa prima compensaba si una quiebra destruye el capital depositado. Nadie podía estimarla con los precios.

Para una estrategia de carry, la lección es directa. El exchange no es una infraestructura neutra: es la contraparte de todo lo que se deposita en él. Un funding o un basis más alto en un exchange puede ser la señal de que el mercado le pide una prima por ese riesgo. Las defensas son las de cualquier riesgo de crédito: límites por contraparte, retirada periódica de beneficios, custodia separada cuando el exchange la ofrece y exchanges con supervisión y segregación de activos verificables (la lección 3.7.5 trata el marco europeo).

Lo que esto cambia en un backtest de carry

  • El carry neto del suelo. Separar el 10,95 % que fija la fórmula de la prima de mercado: es esta la que se estrecha, y la que una estrategia intenta capturar.
  • Margen y liquidaciones de la pata corta. Simular el margen con el mark intradía y una frecuencia de reposición realista; un cash-and-carry sin margen no es la estrategia que se puede operar.
  • Costes por cambio. Cuatro lados cada vez que se entra y se sale: una semana de carry.
  • Fijar o flotar. El trimestral elimina la incertidumbre del funding hasta el vencimiento, pero tiene sus propios rolls y su propio margen.
  • Una contraparte por exchange. Un backtest con precios de un exchange que ya no existe incluye su carry y no su quiebra si el universo se construye con los exchanges que siguen vivos: es sesgo de supervivencia (lección 2.5.1).

Ejercicios

  1. Repite la tabla de apalancamiento de la pata corta para XEQ en alfa (2x, 3x y 5x, rebalanceo semanal). ¿Qué cambia y por qué?
Solución
IN [11]python
bq = h1[h1["activo"] == "XEQ"].set_index("ts")
fe = fu[(fu["exchange"] == "alfa") & (fu["activo"] == "XEQ")]
fe = fe.set_index("ts")["tasa_funding"]
anual_e = fe.sum() / ((fe.index[-1] - fe.index[0]).days / 365.25)
filas = []
for L in (2, 3, 5):
    g = bq.groupby(pd.Grouper(freq="7D"))
    liq = g["apertura"].first() * (1 + 1 / L) / (1 + MMR)
    filas.append({"apal_corto": L,
                  "rend_capital_pct": 100 * anual_e / (1 + 1 / L),
                  "liq_semanal": int((g["mark_maximo"].max() >= liq)
                                     .sum())})
pd.DataFrame(filas).set_index("apal_corto").round(1)
OUT [11]Cash-and-carry en XEQ con la pata corta a 3x
            rend_capital_pct  liq_semanal
apal_corto
2                       15.1            0
3                       17.0            5
5                       18.9           25

Con XEQ el carry medio de alfa es mayor (el rendimiento sobre el capital sube al 15,1 % con 2x y al 17,0 % con 3x), pero XEQ es más volátil que XBQ y la pata corta se liquida mucho más: 5 semanas a 3x (frente a 1 en XBQ) y 25 a 5x. El apalancamiento razonable de la pata corta depende de la volatilidad del activo, no del carry: con XEQ, 2x rinde más (15,1 %) que XBQ a 3x y no tiene ninguna liquidación en seis años.

  1. Calcula el resultado anual de un diferencial de funding largo en el perpetuo de cenit y corto en el de boreal (XBQ, mismo nominal), descontando una entrada y una salida al año con 5 puntos básicos por lado. ¿Merece la pena el capital y las dos contrapartes?
Solución
IN [12]python
neto = diferencial.groupby(diferencial.index.year).sum() * 100
neto = neto - 4 * 5 / 1e4 * 100    # entrar y salir una vez al año
neto.round(2).to_dict()
OUT [12]El diferencial boreal-cenit con costes
{2020: 4.76, 2021: 3.24, 2022: 2.44, 2023: 2.28, 2024: 2.1, 2025: 1.53}

El diferencial neto de una entrada y una salida al año pasa de 4,76 puntos del nominal en 2020 a 1,53 en 2025. Pero el capital no es el nominal: cada pata necesita su margen en su exchange, con 3x en las dos un 67 % del nominal, así que en 2025 rinde alrededor de un 2,3 % sobre el capital, muy por debajo de un cash-and-carry sencillo con la pata corta a 3x (un 11,6 % de media en alfa). Además, hay dos contrapartes y dos márgenes que vigilar, y si una de las patas se liquida o su exchange falla, queda una posición direccional en la otra. Solo tiene sentido como complemento de una cartera de carry ya repartida entre exchanges, no como estrategia propia.

  1. Aplica la regla «fijar el basis si es mayor que el funding de los 90 días anteriores» a los seis pares de exchange y activo que sobreviven. ¿Mejora siempre al perpetuo solo? ¿Qué te haría desconfiar del resultado en datos reales?
Solución
IN [13]python
filas = []
for (e, ac), fut in ft[ft["exchange"] != "dedalo"].groupby(
        ["exchange", "activo"]):
    fund = (fu[(fu["exchange"] == e) & (fu["activo"] == ac)]
            .set_index("ts")["tasa_funding"])
    q2 = trimestres(fut, fund)
    fija = q2["fijado"] > q2["funding_previo"]
    filas.append({"exchange": e, "activo": ac,
                  "fijado": q2["fijado"].mean(),
                  "perpetuo": q2["funding"].mean(),
                  "regla": np.where(fija, q2["fijado"],
                                    q2["funding"]).mean(),
                  "fija_pct": 100 * fija.mean()})
pd.DataFrame(filas).set_index(["exchange", "activo"]).round(2)
OUT [13]La regla de fijar o flotar en los seis pares
                 fijado  perpetuo  regla  fija_pct
exchange activo
alfa     XBQ       3.97      3.97   5.14     43.48
         XEQ       3.92      5.30   6.55     43.48
boreal   XBQ       4.44      4.38   5.33     52.17
         XEQ       4.18      5.69   7.04     21.74
cenit    XBQ       3.13      3.62   4.42     26.09
         XEQ       3.58      4.88   6.26     21.74

En los seis pares, la regla mejora al perpetuo solo: de 3,97 % a 5,14 % por trimestre en XBQ de alfa, y entre 0,8 y 1,4 puntos en los demás; fija el basis entre el 22 % y el 52 % de los trimestres según el par. En XEQ, fijar siempre saldría peor que el perpetuo (3,92 % frente a 5,30 % en alfa): el basis de los datos solo descuenta 0,8 veces el funding, y con el funding alto de XEQ esa diferencia pesa. En los datos tiene una explicación conocida: el basis lleva un ruido propio que no anticipa el funding siguiente, así que elegir el mayor de los dos al abrir captura ese ruido sin mirar el futuro. En datos reales habría que desconfiar por varias razones: no hay garantía de que el ruido del basis sea independiente del funding que viene (puede descontar información que el funding pasado no tiene), 23 trimestres por par son pocas observaciones, la regla se ha elegido después de ver los datos (lección 2.5.1) y el trimestral tiene costes y riesgos propios (margen hasta el vencimiento, liquidez menor que el perpetuo).

Footnotes

  1. S. He, A. Manela, O. Ross y V. von Wachter, «Fundamentals of Perpetual Futures», arXiv 2212.06888 (versión 1 de diciembre de 2022, revisada después). El resumen dice que las desviaciones son mayores que en los mercados de divisas, se mueven juntas entre monedas y se reducen con el tiempo; la lección no cita cifras del artículo. ↩

Respuesta plegada en cada pregunta

Autoevaluación

  1. En calma, con la prima del perpetuo dentro de la banda, ¿qué cobra el corto de un cash-and-carry en un exchange que usa la fórmula de Binance?

    • ANada: sin prima no hay funding
    • BEl interés fijo de 0,01 % por periodo, casi un 11 % anual del nominal: una convención de la fórmula, no un precio de mercado
    • CEl tipo de interés del dólar
    • DLa mitad de la prima
    Ver respuesta

    Respuesta B. El interés fijo de 0,01 % por periodo, casi un 11 % anual del nominal: una convención de la fórmula, no un precio de mercado

    Con la prima entre −4 y +6 puntos básicos, F = P + (I − P) = I = 0,01 % por periodo: 0,0001 × 3 × 365 = 10,95 % al año. Desde 2022 el carry de los tres exchanges que sobreviven queda cerca de ese suelo; lo que se estrecha es la prima alcista, con una vida media de 2,5 años en los datos.

  2. La pata corta del cash-and-carry de XBQ en alfa se lleva con 10x y se rebalancea cada semana. ¿Qué dicen los datos?

    • AQue es la mejor opción: 14,1 % sobre el capital sin riesgo
    • BQue el rendimiento sobre el capital sube del 11,6 % (3x) al 14,1 %, pero el mark habría liquidado el corto en 71 de 314 semanas, dejando el contado sin cubrir
    • CQue no hay liquidaciones porque la posición está cubierta
    • DQue el apalancamiento no cambia el rendimiento
    Ver respuesta

    Respuesta B. Que el rendimiento sobre el capital sube del 11,6 % (3x) al 14,1 %, pero el mark habría liquidado el corto en 71 de 314 semanas, dejando el contado sin cubrir

    La cobertura compensa el PnL entre las dos patas, pero cada pata tiene su margen. Una subida del 9 % o 10 % en la semana liquida el corto 10x aunque el contado haya ganado lo mismo. Más apalancamiento rinde un poco más sobre el capital y multiplica las liquidaciones.

  3. Basis fijado con el trimestral y funding cobrado por el perpetuo en el mismo trimestre: en 23 trimestres de XBQ en alfa, ¿qué relación tienen?

    • AEl basis siempre gana
    • BEl funding siempre gana
    • CLa misma media (3,97 % por trimestre) y una correlación de solo 0,24: cada trimestre uno gana al otro por varios puntos
    • DSon idénticos por arbitraje
    Ver respuesta

    Respuesta C. La misma media (3,97 % por trimestre) y una correlación de solo 0,24: cada trimestre uno gana al otro por varios puntos

    El basis descuenta el funding esperado más una prima, con ruido propio. Fijarlo elimina la incertidumbre del funding, pero no gana de media. Elegir el mayor de los dos al abrir (el basis o el funding de los 90 días anteriores) da 5,14 %: en los datos, el ruido del basis no predice el funding siguiente, y se puede elegir sin mirar el futuro.

  4. boreal paga 3,03 puntos al año más que alfa en 2020 y 1,05 en 2022, aunque la diferencia plantada en su prima es constante. ¿Por qué se estrecha?

    • APor la quiebra de dedalo
    • BPorque la fórmula fija el funding en 0,01 % mientras la prima está dentro de la banda: una prima algo distinta solo se nota cuando se sale de ella, y en los años tranquilos casi nunca se sale
    • CPorque boreal bajó sus comisiones
    • DPor el redondeo
    Ver respuesta

    Respuesta B. Porque la fórmula fija el funding en 0,01 % mientras la prima está dentro de la banda: una prima algo distinta solo se nota cuando se sale de ella, y en los años tranquilos casi nunca se sale

    El 71,4 % de los periodos boreal y cenit pagan exactamente lo mismo, el punto básico de la banda. El diferencial entre exchanges vive en las semanas de euforia, que en los datos (y según He, Manela, Ross y von Wachter, en los mercados reales) son cada vez menos rentables.

  5. dedalo pagó 3,53 puntos al año más de funding que alfa hasta su quiebra. Con la pata corta a 3x, ¿qué probabilidad anual de quiebra compensaba esa prima?

    • ANinguna: la prima era gratis
    • BUn 35 %
    • CAlrededor de un 2,6 % al año: la prima sobre el capital; una quiebra se lleva el capital entero depositado en el exchange
    • DUn 0,01 %
    Ver respuesta

    Respuesta C. Alrededor de un 2,6 % al año: la prima sobre el capital; una quiebra se lleva el capital entero depositado en el exchange

    Con un capital de 1 + 1/3 por unidad de nominal, 3,53 puntos de nominal son un 2,6 % del capital al año. Si la quiebra destruye todo el capital depositado, la prima compensa una probabilidad de quiebra de ese orden, que ningún dato de precios permitía estimar antes del 8 de noviembre.

Ideas clave

  • El carry del perpetuo tiene dos partes: el suelo de casi un 11 % anual que fija el término de interés de la fórmula y una prima de mercado. En los datos la prima alcista se estrecha con una vida media de 2,53 años (plantada: 2,5); desde 2022 el carry queda cerca del suelo.
  • La pata corta necesita margen y puede liquidarse aunque la posición esté cubierta: con 3x y rebalanceo semanal, un 11,6 % anual sobre el capital y una liquidación en seis años; con 10x, un 14,1 % y 71 semanas liquidadas.
  • El basis del trimestral fija el carry hasta el vencimiento. En 23 trimestres, la media fijada (3,97 %) es la misma que el funding cobrado, con una correlación de 0,24: fijar quita incertidumbre, no añade rentabilidad.
  • Los diferenciales de funding entre exchanges se los come la banda del recorte (el 71,4 % de los periodos pagan lo mismo) y se estrechan cada año. Las dislocaciones de precio son raras, breves y exigen inventario en los dos exchanges.
  • La prima de dedalo (3,53 puntos al año de nominal) pagaba un riesgo de quiebra de alrededor de un 2,6 % anual del capital. Con todo en dedalo se perdía todo; repartido entre cuatro exchanges, una cuarta parte del capital.
  • En FTX, según las demandas de la CFTC y la SEC, los fondos de los clientes se desviaban a Alameda, que estaba exenta del motor de liquidación: el riesgo de contraparte no se ve en los precios hasta que es tarde.

Recursos