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.
- Módulo
- 3.7 · Cripto derivados y estrategias específicas
- Duración
- 75 min
Lecciones del nivel 3
3.1 · Futuros en profundidad
3.2 · Spreads de futuros
- 3.2.1 Spreads de calendario, butterflies y condors
- 3.2.2 Spreads intercommodity: crack, spark y crush
- 3.2.3 Spreads de tipos y de índices: 2s10s, NOB, NQ/ES y Europa frente a EE. UU.
- 3.2.4 Ratios de cobertura: por nominal, por DV01 y por volatilidad
- 3.2.5 Datos y backtesting de spreads: cotizados, sintéticos y por patas
- 3.2.6 Estacionalidad de spreads: análisis multi-año, patrones y trampas
3.3 · Forex avanzado
3.4 · Teoría y valoración de opciones
- 3.4.1 Payoffs, paridad put-call y límites de arbitraje
- 3.4.2 Árboles binomiales, Black-Scholes-Merton, Black-76 y Monte Carlo
- 3.4.3 Griegas: delta, gamma, vega, theta, rho, vanna, volga y charm
- 3.4.4 Volatilidad implícita: Newton-Raphson, Brent, py_vollib y QuantLib
- 3.4.5 Sonrisa, skew y estructura temporal; superficie de volatilidad con SVI
- 3.4.6 Volatilidad realizada frente a implícita; prima de riesgo de volatilidad; VIX y VSTOXX
- 3.4.7 Modelos avanzados: Heston, SABR y volatilidad local
3.5 · Estructuras de opciones en Python
- 3.5.1 Estructuras direccionales y verticales: call, put, covered call, collar y spreads
- 3.5.2 Estructuras de volatilidad y rango: straddles, strangles, cóndores y mariposas
- 3.5.3 Calendarios, diagonales, ratios, backspreads, risk reversals y jade lizard
- 3.5.4 Herramienta propia: payoff, griegas agregadas y escenarios
- 3.5.5 Gestión: ajustes, roll, cierre anticipado, asignación temprana y pin risk
3.6 · Estrategias sistemáticas de volatilidad y opciones
3.7 · Cripto derivados y estrategias específicas
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:
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.
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")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ñoLa 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
(, 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?
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())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, ), 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 en esa pata, el capital por unidad de nominal es 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:
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)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 60El 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:
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")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 salidaUnos 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 :
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")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 puntosEl 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:
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") 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 trimestreEn 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.
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} %")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:
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} %)")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:
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.
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)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.003066Hasta 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 %.
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?
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")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ñoLas 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
- 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
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) rend_capital_pct liq_semanal
apal_corto
2 15.1 0
3 17.0 5
5 18.9 25Con 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.
- Calcula el resultado anual de un diferencial de funding largo en el perpetuo de
cenity corto en el deboreal(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
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(){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.
- 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
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) 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.74En 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
-
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
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.
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.
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.
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.
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
Documentación
- CFTC: demanda contra Samuel Bankman-Fried, FTX Trading y Alameda Research (S.D.N.Y., 13 de diciembre de 2022, PDF)
- CFTC: nota de prensa 8638-22 sobre la demanda (13 de diciembre de 2022)
- SEC: nota de prensa 2022-219, SEC Charges Samuel Bankman-Fried with Defrauding Investors (13 de diciembre de 2022)
- Binance: Introduction to Binance Futures Funding Rates
- He, Manela, Ross y von Wachter: Fundamentals of Perpetual Futures (arXiv 2212.06888)