Lección 3.1.1 · 60 min
Contratos de futuros principales
Un sistema de futuros diversificado opera en índices, bonos, energía, metales, agrícolas y divisas a la vez, y cada contrato es un objeto distinto: otro tamaño, otro tick, otra divisa, otro calendario de entrega. Esta lección recorre los 23 futuros sintéticos del nivel, que imitan a los contratos reales más negociados, y mide lo que importa antes de operar ninguno: cuánto riesgo trae un contrato, cuánto cuesta, cuándo hay que salir y dónde está la liquidez.
- Módulo
- 3.1 · Futuros en profundidad
- Duración
- 60 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
Veintitrés fichas
Un sistema de futuros diversificado no opera «futuros»: opera un índice estadounidense que cotiza en puntos, un bono europeo que cotiza en porcentaje del nominal, un crudo en dólares por barril y un maíz en centavos por bushel. Cada uno tiene su ficha (lección 1.2.3) y cada ficha cambia lo que vale un punto, lo que cuesta operar y cuándo hay que salir. Antes de escribir la primera regla hay que poner todos en la misma unidad.
Los datos del nivel traen 23 mercados ficticios que imitan a los contratos reales más negociados de cada sector, con todos los vencimientos listados cada sesión de 2010 a 2025, y seis micros y minis que usan los precios de su mercado base con una décima parte del multiplicador. Son datos sintéticos: los nombres son inventados y las magnitudes (multiplicadores, ticks, márgenes, volatilidades) son verosímiles, pero no son datos de mercado.
import numpy as np
import pandas as pd
esp = pd.read_csv("futuros3_especificaciones.csv",
index_col="mercado")
base = esp[esp["mercado_base"].isna()]
print(len(base), "mercados y", len(esp) - len(base), "micro o mini")
base.groupby("sector")["imita"].apply(
lambda s: ", ".join(x.split(" (")[-1].rstrip(")") for x in s))23 mercados y 6 micro o mini
sector
agricolas ZC, ZW, ZS, ZM, ZL
divisas 6E
energia CL, RB, HO, NG, PJM Western Hub Peak mensual
indices ES, NQ, RTY, FESX, MEFF
metales GC, SI
tipos ZT, ZF, ZN, ZB, FGBL
Name: imita, dtype: strSeis sectores. Índices: el E-mini S&P 500 (ES), el E-mini Nasdaq-100 (NQ), el E-mini Russell 2000 (RTY), el Euro
Stoxx 50 (FESX) y el IBEX 35 de MEFF. Tipos: las notas a 2, 5 y 10 años y el bono a 30 del Tesoro de EE. UU. (ZT, ZF,
ZN, ZB) y el Bund alemán (FGBL). Energía: crudo WTI (CL), gasolina (RB), gasóleo (HO), gas natural (NG) y un contrato
mensual de electricidad. Metales: oro (GC) y plata (SI). Agrícolas: maíz (ZC), trigo (ZW), soja (ZS), harina y aceite
de soja (ZM, ZL). Y una divisa: el euro contra el dólar (6E), aquí el «evro de Vesperia», QEV.
Fuente Mermaid
flowchart LR F[Futuros] --> FI[Financieros] F --> MP[Materias primas] FI --> IX[Índices] FI --> TP[Tipos] FI --> DV[Divisas] MP --> EN[Energía] MP --> MT[Metales] MP --> AG[Agrícolas] IX --> EF[Efectivo] TP --> FA[Física con aviso] DV --> FS[Física] EN --> FS MT --> FA AG --> FA
La forma de liquidar al vencimiento separa a los mercados en tres grupos, y el grupo decide cuándo tiene que salir un sistema que no quiere el subyacente: los índices se liquidan en efectivo; la divisa y la energía (salvo la electricidad del curso, que también se liquida en efectivo) se entregan; los bonos, los metales y los agrícolas se entregan con un primer día de aviso, a partir del cual el vendedor puede notificar la entrega. La sección del calendario vuelve sobre ello.
cols = ["divisa", "multiplicador", "unidad_cotizacion", "tick",
"valor_tick"]
base.loc[["RVA", "RVH", "TPC", "TPE", "PEC", "GNA", "MTO", "GRM",
"DQE"], cols] divisa multiplicador unidad_cotizacion tick valor_tick
mercado
RVA USD 50.0 puntos de índice 0.250000 12.500
RVH QEV 10.0 puntos de índice 1.000000 10.000
TPC USD 1000.0 % del nominal 0.015625 15.625
TPE QEV 1000.0 % del nominal 0.010000 10.000
PEC USD 1000.0 USD/barril 0.010000 10.000
GNA USD 10000.0 USD/MMBtu 0.001000 10.000
MTO USD 100.0 USD/onza 0.100000 10.000
GRM USD 50.0 centavos/bushel 0.250000 12.500
DQE USD 125000.0 USD por evro 0.000050 6.250El multiplicador traduce la cotización a dinero: 50 USD por punto en RVA, 1.000 USD por punto porcentual en la nota
a 10 años TPC (un nominal de 100.000 USD), 1.000 barriles en el crudo, 10.000 MMBtu en el gas, 100 onzas en el oro,
5.000 bushels en el maíz (50 USD por centavo) y 125.000 evros en DQE. El tick de la nota a 10 años es medio
treintaidosavo de punto (0,015625 = 15,625 USD), la convención de los futuros del Tesoro, y RVH y TPE cotizan en
evros: lo que ganan o pierden hay que pasarlo a dólares.
Las fichas de los contratos reales de Eurex y MEFF, leídas en sus páginas oficiales, coinciden con lo que imitan los datos en las cifras que se pueden comparar:
| Contrato real | Multiplicador | Tick | Vencimientos | Vencimiento y liquidación |
|---|---|---|---|---|
| E-mini S&P 500 (CME) | 50 USD × índice | 0,25 puntos = 12,50 USD | Trimestrales | Tercer viernes; en efectivo, a la cotización especial de apertura |
| EURO STOXX 50 (Eurex, FESX) | 10 EUR × índice | 1 punto = 10 EUR | Los doce trimestrales más próximos | Tercer viernes (cierre a las 12:00 CET); en efectivo |
| IBEX 35 (MEFF) | 10 EUR × índice | Puntos enteros, por circular | Diez trimestrales, dos mensuales y semestrales | Tercer viernes; media del índice de 16:15 a 16:45; en efectivo |
| Mini IBEX 35 (MEFF) | 1 EUR × índice | 5 puntos = 5 EUR | Igual que el IBEX 35 | Igual que el IBEX 35 |
| Euro-Bund (Eurex, FGBL) | 100.000 EUR, cupón del 6 % | 0,01 % = 10 EUR | Los tres trimestrales más próximos | Entrega el día 10 del mes; última negociación dos días hábiles antes |
El mini de los datos (RVHM) tiene un tick de 1 punto y el real de MEFF, de 5: es una de las simplificaciones de los
datos. Eurex lista además un micro del EURO STOXX 50 de 1 EUR por punto, y MEFF ha dado de baja su Micro IBEX 35 con
efecto desde el 1 de octubre de 2026 (circular C-EX-DF-2026-07). Las fichas cambian: antes de operar un contrato real
se lee la de la bolsa, no la de un libro ni la de un curso. Los contratos de CME Group que imitan los demás mercados
(NQ, RTY, ZN, CL, NG, GC, ZC, ZS, 6E y los micros) tienen sus fichas en el reglamento de cada bolsa del grupo; aquí
solo se usan las cifras de los datos.
Los contratos se nombran con la raíz del mercado, una letra por mes y dos cifras del año:
MESES = "FGHJKMNQUVXZ"
def descifra(contrato):
"""PECZ25 -> ('PEC', 2025, 12)."""
raiz, letra, anio = contrato[:-3], contrato[-3], contrato[-2:]
return raiz, 2000 + int(anio), MESES.index(letra) + 1
print(descifra("PECZ25"), descifra("GRMH26"), descifra("TPEU24"))
base[["meses", "meses_listados", "liquidacion_fisica"]].loc[
["RVA", "RVH", "TPC", "PEC", "GNA", "MTO", "GRM", "GRS"]]('PEC', 2025, 12) ('GRM', 2026, 3) ('TPE', 2024, 9)
meses meses_listados liquidacion_fisica
mercado
RVA HMUZ 13 False
RVH FGHJKMNQUVXZ 13 False
TPC HMUZ 9 True
PEC FGHJKMNQUVXZ 18 True
GNA FGHJKMNQUVXZ 24 True
MTO GJMQVZ 18 True
GRM HKNUZ 18 True
GRS FHKNQUX 16 TrueLos meses dicen qué vencimientos existen: trimestrales (HMUZ) en índices estadounidenses, bonos y divisa; todos los
meses en el índice español y en la energía; seis meses pares en el oro (GJMQVZ); los de las cosechas en los
agrícolas (HKNUZ en el maíz, FHKNQUX en la soja). meses_listados es hasta dónde llega la curva: 9 meses en los
bonos (tres vencimientos), 18 en el crudo, 24 en el gas. Que un vencimiento esté listado no quiere decir que se
negocie: la sección de la liquidez lo mide.
Nominal, tick y riesgo de un contrato
Para comparar los 23 mercados hace falta una serie por mercado: el contrato que se tiene cada día. Los datos traen la
regla de roll de cada contrato (fecha_roll, la sesión en la que se pasa al siguiente) y con ella se construye la
serie como en la lección 1.4.6, con el rendimiento diario calculado siempre con el mismo contrato:
curvas = pd.read_parquet("futuros3_curvas.parquet")
ctr = pd.read_csv("futuros3_contratos.csv",
parse_dates=["vencimiento", "primer_aviso",
"fecha_alta", "fecha_roll"])
def que_se_tiene(fechas, mercado):
"""El primer contrato cuya fecha de roll es posterior a cada
fecha (en la fecha de roll ya se tiene el siguiente)."""
cm = ctr[ctr["mercado"] == mercado].reset_index(drop=True)
pos = np.searchsorted(cm["fecha_roll"].to_numpy(),
fechas.to_numpy(), side="right")
return pd.Series(cm["contrato"].to_numpy()[pos], index=fechas)
def serie(mercado):
"""Precio y rendimiento diario (del mismo contrato) del que se
tiene: el rendimiento del día de roll es el del contrato viejo."""
c = curvas[curvas["mercado"] == mercado]
P = c.pivot(index="fecha", columns="contrato",
values="liquidacion")
tiene = que_se_tiene(P.index, mercado)
i = P.columns.get_indexer(tiene)
filas = np.arange(len(P))
precio = P.to_numpy()[filas, i]
ayer = np.r_[i[0], i[:-1]]
hoy_viejo = P.to_numpy()[filas, ayer]
antes = np.r_[np.nan, P.to_numpy()[filas[1:] - 1, ayer[1:]]]
return pd.DataFrame({"contrato": tiene.to_numpy(),
"precio": precio,
"ret": np.log(hoy_viejo / antes)},
index=P.index)
S = {m: serie(m) for m in base.index}
S["PEC"].loc["2025-11-07":"2025-11-14"] contrato precio ret
fecha
2025-11-07 PECZ25 76.42 0.015694
2025-11-10 PECZ25 75.86 -0.007355
2025-11-11 PECZ25 77.49 0.021259
2025-11-12 PECF26 75.59 0.012950
2025-11-13 PECF26 73.59 -0.026815
2025-11-14 PECF26 73.53 -0.000816El 12 de noviembre de 2025 el crudo pasa de PECZ25 a PECF26. El precio que se ve salta (de 77,49 a 75,59), pero el
rendimiento de ese día, un 1,30 %, es el del contrato de diciembre entre el día 11 y el 12: el salto entre contratos
no es una ganancia ni una pérdida. Con la serie de cada mercado, el nominal de un contrato es precio × multiplicador
(× USD por evro en los que cotizan en QEV), y su riesgo anual es el nominal por la volatilidad anual del
rendimiento:
fx = pd.read_parquet("fx3_diario.parquet")
usd_qev = fx[fx["divisa"] == "QEV"].set_index("fecha")[
"usd_por_unidad"]
DIA = "2025-11-26"
def ficha_del_dia(dia, mercados):
filas = {}
for m in mercados:
b = esp.loc[m, "mercado_base"]
s = S[b if isinstance(b, str) else m]
cambio = usd_qev[dia] if esp.loc[m, "divisa"] == "QEV" else 1
precio = s.loc[dia, "precio"]
nominal = precio * esp.loc[m, "multiplicador"] * cambio
vol = s["ret"].loc[:dia].tail(252).std() * np.sqrt(252)
filas[m] = {"contrato": s.loc[dia, "contrato"],
"precio": precio, "nominal_usd": nominal,
"vol_anual": vol, "riesgo_usd": vol * nominal,
"tick_pb": 1e4 * esp.loc[m, "valor_tick"]
/ (precio * esp.loc[m, "multiplicador"])}
return pd.DataFrame(filas).T.infer_objects()
ficha = ficha_del_dia(DIA, esp.index)
ficha.loc[base.index].sort_values("riesgo_usd").round(
{"nominal_usd": 0, "vol_anual": 3, "riesgo_usd": 0,
"tick_pb": 2}) contrato precio nominal_usd vol_anual riesgo_usd tick_pb
mercado
TPB TPBH26 109.164062 109164.0 0.041 4453.0 0.72
TPA TPAH26 104.449219 208898.0 0.023 4730.0 0.37
GRM GRMH26 335.750000 16788.0 0.285 4790.0 7.45
TPC TPCH26 113.078125 113078.0 0.058 6513.0 1.38
GRT GRTH26 461.500000 23075.0 0.318 7349.0 5.42
GRH GRHF26 299.200000 29920.0 0.254 7606.0 3.34
GRA GRAF26 53.110000 31866.0 0.275 8750.0 1.88
TPE TPEH26 128.120000 174586.0 0.058 10112.0 0.78
GRS GRSF26 1095.750000 54788.0 0.204 11168.0 2.28
DQE DQEZ25 1.363950 170494.0 0.075 12826.0 0.37
TPD TPDH26 122.281250 122281.0 0.113 13824.0 2.56
RVE RVEZ25 6946.000000 94651.0 0.186 17629.0 1.44
ELB ELBF26 58.150000 46520.0 0.506 23540.0 8.60
PEC PECF26 76.690000 76690.0 0.307 23550.0 1.30
MTO MTOG26 2170.700000 217070.0 0.130 28326.0 0.46
PEG PEGF26 2.066000 86772.0 0.361 31362.0 0.48
GNA GNAF26 7.239000 72390.0 0.438 31690.0 1.38
MTP MTPH26 28.320000 141600.0 0.241 34115.0 1.77
PEH PEHF26 2.582400 108461.0 0.342 37094.0 0.39
RVC RVCZ25 3232.000000 161600.0 0.257 41496.0 0.31
RVH RVHZ25 19700.000000 268447.0 0.223 59866.0 0.51
RVA RVAZ25 7851.750000 392588.0 0.177 69320.0 0.32
RVB RVBZ25 26222.000000 524440.0 0.221 116098.0 0.10La tabla ordena los 23 mercados por el riesgo de un contrato, y el orden no se parece al del nominal. La nota a 2
años (TPA) tiene un nominal de 208.898 USD, casi el del oro, pero con una volatilidad del 2,3 % su riesgo es de
4.730 USD al año; el maíz (GRM), con 16.788 USD de nominal, tiene casi el mismo riesgo (4.790) porque se mueve un
28,5 % al año. En el otro extremo, un solo RVB arriesga 116.098 USD al año. La figura de la cabecera dibuja las dos
dimensiones con escalas logarítmicas: cada diagonal es una volatilidad, y la distancia vertical entre un bono y un
índice de nominal parecido es de un orden de magnitud.
margen_usd = esp["margen_inicial"] * np.where(
esp["divisa"] == "QEV", usd_qev[DIA], 1)
ficha["margen_pct"] = 100 * margen_usd / ficha["nominal_usd"]
ficha["apalancamiento"] = ficha["nominal_usd"] / margen_usd
# cuántas desviaciones típicas diarias del nominal cubre el margen
ficha["desv_diarias"] = (margen_usd * np.sqrt(252)
/ ficha["riesgo_usd"])
(ficha.loc[base.index, ["margen_pct", "apalancamiento",
"desv_diarias"]]
.sort_values("apalancamiento").round(2).iloc[[0, 1, 2, -3, -2, -1]]) margen_pct apalancamiento desv_diarias
mercado
ELB 15.69 6.37 4.92
GNA 11.74 8.52 4.26
PEG 7.95 12.58 3.49
DQE 1.99 50.15 4.21
TPB 1.65 60.65 6.42
TPA 0.48 208.90 3.36El margen inicial va del 15,69 % del nominal en la electricidad al 0,48 % en la nota a 2 años: un apalancamiento de 6 a 1 en un caso y de 209 a 1 en el otro. Pero medido en riesgo es casi lo mismo: en todos los mercados de la tabla el margen cubre entre 3,4 y 6,4 desviaciones típicas diarias del nominal. La cámara fija el margen por el riesgo, así que el apalancamiento de un contrato dice lo poco que se mueve, no lo arriesgado que es. La lección 3.1.3 desmonta cómo se calcula ese margen y qué pasa cuando la volatilidad cambia.
Micros y minis: la granularidad
Un contrato es indivisible. Con una cuenta pequeña y un objetivo de riesgo razonable, el problema no es el margen sino el tamaño: un solo contrato puede ser demasiado riesgo. Para eso existen los micros y los minis, que en los datos tienen una décima parte del multiplicador de su mercado base:
capital, riesgo_obj = 100_000, 0.20
micro = esp[esp["mercado_base"].notna()]
pares = pd.DataFrame({
"base": micro["mercado_base"],
"riesgo_base": ficha.loc[micro["mercado_base"],
"riesgo_usd"].to_numpy(),
"riesgo_micro": ficha.loc[micro.index, "riesgo_usd"],
}, index=micro.index)
pares["n_base"] = capital * riesgo_obj / pares["riesgo_base"]
pares["n_micro"] = capital * riesgo_obj / pares["riesgo_micro"]
pares["capital_min_base"] = pares["riesgo_base"] / riesgo_obj
pares.round({"riesgo_base": 0, "riesgo_micro": 0, "n_base": 2,
"n_micro": 1, "capital_min_base": -3}) base riesgo_base riesgo_micro n_base n_micro capital_min_base
mercado
RVAM RVA 69320.0 6932.0 0.29 2.9 347000.0
RVBM RVB 116098.0 11610.0 0.17 1.7 580000.0
RVCM RVC 41496.0 4150.0 0.48 4.8 207000.0
RVHM RVH 59866.0 5987.0 0.33 3.3 299000.0
PECM PEC 23550.0 2355.0 0.85 8.5 118000.0
MTOM MTO 28326.0 2833.0 0.71 7.1 142000.0Con 100.000 USD y un 20 % de riesgo anual (20.000 USD), la posición ideal en RVA es de 0,29 contratos. Comprar uno
multiplica el riesgo por 3,5; no comprar ninguno deja el mercado fuera. Con el micro, la posición es de 2,9 contratos,
que se redondea a 3 con un error pequeño. capital_min_base es el capital con el que un solo contrato del mercado
base ya es todo el riesgo objetivo: 347.000 USD en RVA y 580.000 en RVB. Por debajo, el mercado no se puede operar
con su contrato grande sin concentrar el riesgo en él, que es la razón por la que la lección 2.2.2 sacaba del universo
los contratos que pesaban demasiado en el capital.
La granularidad no es gratis:
def coste_lado_pb(m, ticks=0.5):
"""Medio tick de horquilla más la comisión, por contrato y lado,
en puntos básicos del nominal."""
usd = (ticks * esp.loc[m, "valor_tick"] + esp.loc[m, "comision"])
if esp.loc[m, "divisa"] == "QEV":
usd *= usd_qev[DIA]
return 1e4 * usd / ficha.loc[m, "nominal_usd"]
pd.DataFrame({m: {"base": coste_lado_pb(b), "micro": coste_lado_pb(m)}
for m, b in micro["mercado_base"].items()}).T.round(2) base micro
RVAM 0.21 0.34
RVBM 0.09 0.18
RVCM 0.28 0.59
RVHM 0.31 0.46
PECM 0.95 1.63
MTOM 0.33 0.58Con medio tick de horquilla y la comisión de los datos, un lado en RVAM cuesta 0,34 puntos básicos del nominal
frente a 0,21 en RVA; en el crudo, 1,63 frente a 0,95. La comisión por contrato del micro (0,70 USD en RVAM) es
una tercera parte de la del grande (2,10), pero mueve una décima parte del nominal. Para un sistema que rota poco es
un precio razonable por poder operar; para uno que rota mucho, puede comerse la ventaja.
Calendario: meses, vencimiento, aviso y entrega
Cada contrato tiene cuatro fechas: el alta (primer día listado), el roll (cuando el sistema pasa al siguiente), el primer día de aviso en los de entrega física con aviso, y el vencimiento (último día de negociación):
Fuente Mermaid
stateDiagram-v2 [*] --> Listado Listado --> Cercano: liquidez Cercano --> Roll: fecha_roll Roll --> Aviso: primer aviso Roll --> Vencido: efectivo Aviso --> Entrega: largo dentro Aviso --> Vencido: cerrado Vencido --> [*] Entrega --> [*]
cal = ctr.set_index("contrato").loc[
["RVAZ25", "PECF26", "TPCZ25", "GRMZ25"]]
dias = lambda a, b: (b - a).dt.days
pd.DataFrame({
"alta": cal["fecha_alta"].dt.date,
"roll": cal["fecha_roll"].dt.date,
"primer_aviso": cal["primer_aviso"].dt.date,
"vencimiento": cal["vencimiento"].dt.date,
"vida_dias": dias(cal["fecha_alta"], cal["vencimiento"]),
"roll_a_venc": dias(cal["fecha_roll"], cal["vencimiento"]),
}) alta roll primer_aviso vencimiento vida_dias roll_a_venc
contrato
RVAZ25 2024-11-01 2025-12-09 NaT 2025-12-19 413 10
PECF26 2024-07-01 2025-12-11 NaT 2025-12-19 536 8
TPCZ25 2025-03-01 2025-11-24 2025-11-28 2025-12-19 293 25
GRMZ25 2024-06-01 2025-11-13 2025-11-28 2025-12-12 559 29RVAZ25(índice, efectivo) vence el tercer viernes de diciembre y no tiene aviso: el roll, 10 días naturales antes, lo marca la liquidez.PECF26(crudo, entrega física) es el contrato de enero, pero vence el 19 de diciembre: en el crudo la negociación termina en el mes anterior al de entrega. El roll es 8 días antes.TPCZ25(nota a 10 años) vence el 19 de diciembre, pero su primer aviso es el 28 de noviembre, el último día hábil del mes anterior: desde ahí el vendedor puede notificar la entrega. El roll de los datos es el 24 de noviembre, 25 días antes del vencimiento.GRMZ25(maíz) tiene el primer aviso el 28 de noviembre y vence el 12 de diciembre; el roll es el 13 de noviembre, 10 sesiones antes del aviso.
La figura pone tres de ellos sobre el mismo eje. En los tres, el tramo en que el contrato tiene el mayor interés abierto de su mercado empieza unos días antes de que se tenga y termina unos días antes del roll: el interés abierto migra antes de que el sistema se mueva. En la nota a 10 años, todo el tramo útil termina tres semanas antes del vencimiento. Un backtest que mantenga el contrato «hasta que venza» porque el precio sigue existiendo opera, en la realidad, en un contrato sin liquidez y con riesgo de entrega.
Dónde está la liquidez
anio = curvas[curvas["fecha"] >= "2025-01-01"]
por_dia = anio.groupby(["mercado", "fecha"])[
["volumen", "interes_abierto"]].sum()
liq = por_dia.groupby("mercado").median()
liq["nominal_dia_musd"] = (liq["volumen"]
* ficha.loc[liq.index, "nominal_usd"]
/ 1e6)
liq.sort_values("nominal_dia_musd", ascending=False).round(0).astype(
int).iloc[[0, 1, 2, 3, -4, -3, -2, -1]] volumen interes_abierto nominal_dia_musd
mercado
RVA 1817640 2271914 713583
RVB 655680 239321 343865
TPC 1429191 4356144 161610
TPE 689645 1150384 120402
GRA 115254 450506 3673
GRH 118998 426642 3560
GRT 133398 422790 3078
ELB 2422 30075 113El nominal negociado al día (volumen × nominal de un contrato, en millones de USD) separa los mercados por varios
órdenes de magnitud: RVA mueve unos 714.000 millones al día y la nota a 10 años, 162.000; el trigo y la harina y
el aceite de soja, entre 3.100 y 3.700; la electricidad, 113 millones, con una mediana de 2.422 contratos diarios. Son cifras de una simulación,
pero el orden (índices y bonos muy por encima de las materias primas, la electricidad muy por debajo) condiciona la
capacidad de un sistema (lección 2.2.3): un fondo grande puede tener el mismo riesgo en todos los mercados solo
mientras sus órdenes sean pequeñas frente al volumen del más estrecho.
anio = anio.assign(tiene=False)
for m in base.index:
sel = anio["mercado"] == m
t = que_se_tiene(pd.DatetimeIndex(anio.loc[sel, "fecha"]), m)
anio.loc[sel, "tiene"] = (anio.loc[sel, "contrato"].to_numpy()
== t.to_numpy())
cuota = anio.groupby("mercado").apply(
lambda g: g.loc[g["tiene"], "volumen"].sum() / g["volumen"].sum())
(100 * cuota).groupby(base["sector"]).agg(["min", "max"]).round(1) min max
sector
agricolas 59.2 64.9
divisas 91.3 91.3
energia 34.2 61.7
indices 86.9 91.8
metales 80.2 82.0
tipos 84.8 94.6En los índices, los bonos y la divisa, el contrato que se tiene concentra entre el 85 % y el 95 % del volumen del año; en los metales, en torno al 80 %; en los agrícolas, del 59 % al 65 %. En la energía, mucho menos: entre el 34,2 % de la electricidad y el 61,7 % de la gasolina. Los contratos de energía mensuales viven poco tiempo como cercanos y el volumen se reparte entre varios meses (y entre spreads de calendario, lección 3.2.1). Para un sistema, eso significa que en energía el siguiente contrato también es líquido y que se puede elegir en qué punto de la curva estar, una decisión que la lección 3.1.2 conecta con el roll yield.
Veintitrés mercados no son veintitrés apuestas
Si los mercados se movieran juntos, 23 mercados darían poca diversificación. La correlación media de los rendimientos diarios, dentro de cada sector y con el resto:
R = pd.DataFrame({m: S[m]["ret"] for m in base.index}).loc["2011":]
C = R.corr()
sector = base["sector"]
fuera_diag = ~np.eye(len(C), dtype=bool)
resumen = {}
for s in ["indices", "tipos", "energia", "metales", "agricolas"]:
f = (sector == s).to_numpy()
dentro = C.to_numpy()[np.ix_(f, f)][fuera_diag[np.ix_(f, f)]]
fuera = C.to_numpy()[np.ix_(f, ~f)]
resumen[s] = {"dentro": dentro.mean(),
"con_el_resto": fuera.mean()}
print(pd.DataFrame(resumen).T.round(2))
print("divisa con el resto:", round(C.loc["DQE"].drop("DQE").mean(), 2)) dentro con_el_resto
indices 0.82 0.00
tipos 0.76 -0.05
energia 0.41 0.03
metales 0.85 -0.02
agricolas 0.44 0.00
divisa con el resto: -0.0Dentro de cada sector las correlaciones son altas: 0,82 entre los cinco índices, 0,76 entre los bonos, 0,85 entre el oro y la plata. En energía y agrícolas son menores (0,41 y 0,44) porque mezclan mercados con factores propios (la electricidad, el gas, el trigo). Entre sectores, en estos datos, son prácticamente cero. Dos consecuencias:
- Cinco índices con una correlación de 0,82 son, a efectos de riesgo, poco más que uno. Un sistema que da el mismo peso a cada mercado tiene cinco veces más riesgo en índices que en divisas sin haberlo decidido. Repartir el riesgo primero por sectores y después dentro de cada uno lo corrige (lección 3.1.4).
- La diversificación de verdad viene de juntar sectores. En los datos, la correlación entre sectores es casi nula por construcción del generador; en los mercados reales no lo es y cambia con el régimen (la de la renta variable y los bonos, por ejemplo, ha cambiado de signo varias veces), así que la diversificación de un sistema real hay que estimarla y vigilarla.
Lo que esto cambia en tus sistemas
- Todo en riesgo, nada en contratos. Un sistema multimercado decide cuánto riesgo quiere en cada mercado y lo traduce a contratos con el nominal y la volatilidad de cada uno, en la divisa de la cuenta.
- El calendario es parte de la estrategia. Roll, primer aviso y vencimiento salen de la ficha y hay que tenerlos en una tabla, no en el código: las reglas cambian por contrato y por bolsa.
- Granularidad o coste. Con poco capital, los micros permiten operar mercados que si no quedarían fuera; con mucho, los contratos grandes son más baratos.
- La liquidez no está repartida. Los mercados del final de la tabla de liquidez limitan el tamaño del sistema entero.
Ejercicios
- Calcula el nominal de un contrato
RVEy de unoRVHel 26 de noviembre de 2025 en evros y en dólares. Compara su volatilidad medida en evros con la del rendimiento pasado a dólares. ¿Cuál es la relevante para el riesgo de un futuro?
Solución
fx_r = np.log(usd_qev).diff()
for m in ["RVE", "RVH"]:
r_qev = S[m]["ret"].loc[:DIA].tail(252)
r_usd = (r_qev + fx_r.reindex(r_qev.index)).dropna()
nom_qev = S[m].loc[DIA, "precio"] * esp.loc[m, "multiplicador"]
print(m, f"nominal {nom_qev:,.0f} QEV = "
f"{nom_qev * usd_qev[DIA]:,.0f} USD;",
f"vol en QEV {r_qev.std() * np.sqrt(252):.3f},",
f"en USD {r_usd.std() * np.sqrt(252):.3f}")RVE nominal 69,460 QEV = 94,651 USD; vol en QEV 0.186, en USD 0.199
RVH nominal 197,000 QEV = 268,447 USD; vol en QEV 0.223, en USD 0.230Un inversor en dólares que compra un futuro sobre un índice europeo no tiene el nominal en evros: solo el resultado diario, que se liquida en evros y se pasa a dólares (y el margen depositado). Por eso el riesgo de divisa de un futuro es mucho menor que el de comprar el índice al contado, y la volatilidad relevante es la del rendimiento en evros, convertida al cambio del día. La que se mide sumando el rendimiento del tipo de cambio sería la de una inversión al contado en el índice europeo. La lección 3.3.3 trata el riesgo de divisa de una cartera multimoneda.
- Con la tabla
ficha, ¿cuántos contratos de cada mercado harían falta para que todos aporten 50.000 USD de riesgo anual? ¿Qué mercados necesitan menos de un contrato y por qué es un problema?
Solución
n = 50_000 / ficha.loc[base.index, "riesgo_usd"]
print(n.round(2).sort_values().to_string())mercado
RVB 0.43
RVA 0.72
RVH 0.84
RVC 1.20
PEH 1.35
MTP 1.47
GNA 1.58
PEG 1.59
MTO 1.77
PEC 2.12
ELB 2.12
RVE 2.84
TPD 3.62
DQE 3.90
GRS 4.48
TPE 4.94
GRA 5.71
GRH 6.57
GRT 6.80
TPC 7.68
GRM 10.44
TPA 10.57
TPB 11.23Los índices grandes necesitan menos de un contrato para 50.000 USD de riesgo, y las notas cortas más de diez.
Redondear la fracción de RVB a 0 deja el mercado fuera; a 1, le da más del doble del riesgo pedido. Las soluciones
son subir el capital, usar el micro o aceptar que algunos mercados no entran (el bloque de universo de la lección
2.2.2).
- Explica por qué el
PECF26vence en diciembre de 2025 y qué pasaría en un backtest que, para no complicarse, supusiera que todos los contratos vencen el tercer viernes del mes de su código.
Solución
En el crudo, la negociación de un contrato termina en el mes anterior al de entrega (la regla de los datos: tres sesiones antes del día 25 del mes anterior), porque la entrega se hace a lo largo del mes del contrato. Un backtest que lo supusiera vencido el tercer viernes de enero tendría el contrato un mes más de lo posible: rodaría tarde, usaría precios de un contrato que ya no cotiza (o los inventaría) y calcularía mal el carry, que depende de la distancia entre vencimientos (lección 3.1.2). El calendario de cada contrato tiene que salir de su ficha.
Respuesta plegada en cada pregunta
Autoevaluación
El 26 de noviembre de 2025, un contrato RVA (multiplicador 50 USD) vale 392.588 USD y uno TPA (nota a 2 años, multiplicador 2.000) vale 208.898 USD. ¿Cuál aporta más riesgo a una cartera?
- ATPA, porque su apalancamiento (nominal entre margen) es diez veces mayor
- BRVA: con una volatilidad anual del 17,7 % frente al 2,3 %, su riesgo anual es de unos 69.300 USD por contrato frente a unos 4.700
- CLos dos lo mismo, porque los nominales son parecidos
- DNo se puede saber sin el margen inicial
Ver respuesta
Respuesta B. RVA: con una volatilidad anual del 17,7 % frente al 2,3 %, su riesgo anual es de unos 69.300 USD por contrato frente a unos 4.700
El riesgo de un contrato es su nominal por la volatilidad del rendimiento. TPA tiene más apalancamiento (209 a 1) porque la cámara pide poco margen para un activo que se mueve poco; para igualar el riesgo de un RVA harían falta casi quince TPA.
¿Qué significa el código
GRMH26?- AEl contrato de maíz (GRM) con entrega en marzo (H) de 2026
- BEl contrato de maíz de 2026 que vence en junio
- CEl contrato de maíz número 26 del año
- DEl micro del maíz
Ver respuesta
Respuesta A. El contrato de maíz (GRM) con entrega en marzo (H) de 2026
Raíz del mercado, letra del mes de entrega (F enero, G febrero, H marzo, J abril, K mayo, M junio, N julio, Q agosto, U septiembre, V octubre, X noviembre, Z diciembre) y dos cifras del año.
Una cuenta de 100.000 USD quiere un riesgo anual del 20 %. Un contrato RVA aporta unos 69.300 USD de riesgo al año y su micro RVAM, una décima parte. ¿Qué es razonable?
- AComprar un RVA: es lo más parecido al objetivo
- BUsar el micro: 2,9 micros se acercan al objetivo, mientras que un RVA llevaría el riesgo al 69 % del capital
- CNo operar índices nunca
- DComprar un RVA y reducir el apalancamiento con el margen
Ver respuesta
Respuesta B. Usar el micro: 2,9 micros se acercan al objetivo, mientras que un RVA llevaría el riesgo al 69 % del capital
Con 100.000 USD y un 20 % de riesgo, el objetivo son 20.000 USD al año: 0,29 contratos RVA. Redondear a 1 multiplica el riesgo por 3,5. El micro permite acercarse (3 micros, unos 20.800 USD), a cambio de pagar más comisión por unidad de nominal (0,34 frente a 0,21 puntos básicos por lado en los datos).
¿Por qué un sistema sale de un futuro de bonos antes de su primer día de aviso y no espera al último día de negociación?
- APorque después del primer aviso el contrato deja de cotizar
- BPorque desde el primer aviso un largo puede recibir una notificación de entrega, y la liquidez ya está en el siguiente contrato
- CPorque el margen se multiplica por diez
- DPorque así lo exige la ficha
Ver respuesta
Respuesta B. Porque desde el primer aviso un largo puede recibir una notificación de entrega, y la liquidez ya está en el siguiente contrato
En los de entrega física con aviso, el vendedor puede notificar la entrega desde el primer día de aviso: el largo que siga dentro puede acabar recibiendo el bono. En TPCZ25 el primer aviso es 21 días antes del vencimiento y el roll de los datos, 25 días antes.
Los cinco índices del curso tienen una correlación media de 0,82 entre sí. ¿Qué implica para un sistema que les da el mismo riesgo que a cinco mercados poco correlados?
- ANada: cinco mercados son cinco apuestas
- BQue el riesgo de los índices se suma casi entero: son casi una sola apuesta, y la cartera tiene mucho más riesgo en ese sector del que parece
- CQue hay que operar solo índices
- DQue la correlación no afecta al riesgo
Ver respuesta
Respuesta B. Que el riesgo de los índices se suma casi entero: son casi una sola apuesta, y la cartera tiene mucho más riesgo en ese sector del que parece
La varianza de una suma depende de las correlaciones. Con 0,82, cinco posiciones iguales tienen casi el riesgo de una sola posición cinco veces mayor. Por eso los sistemas diversificados reparten el riesgo por sectores y no solo por mercados (lección 3.1.4).
Ideas clave
- La ficha fija todo menos el precio: multiplicador, tick, meses, último día y forma de liquidación. Un mismo «1 contrato» va de 16.788 USD de nominal (maíz) a 524.440 (RVB).
- Lo que se compara entre mercados es el riesgo de un contrato (nominal × volatilidad), no el nominal ni el margen: en los datos, de unos 4.500 USD al año (notas a 2 y 5 años) a 116.098 (RVB).
- El margen inicial cubre de 3 a 6 desviaciones típicas diarias del nominal: por eso un bono a 2 años tiene un apalancamiento de 209 a 1 y la electricidad de 6 a 1. El apalancamiento no mide el riesgo.
- Micros y minis dan granularidad a cuentas pequeñas (con 100.000 USD, 2,9 micros RVAM frente a 0,29 RVA) a cambio de más coste por unidad de nominal.
- En los de entrega física hay que salir antes del primer día de aviso; en los de efectivo, el roll lo decide la liquidez. En energía, menos de la mitad del volumen está en el contrato que se tiene.
- Los datos son sintéticos: las cifras imitan a los contratos reales, pero para operar mandan las fichas oficiales de cada bolsa.
Recursos
Documentación
- Eurex: EURO STOXX 50 Index Futures (FESX), especificaciones
- Eurex: Euro-Bund Futures (FGBL), especificaciones
- MEFF: futuros sobre IBEX 35
- MEFF: futuros sobre Mini IBEX 35
- MEFF: circular C-EX-DF-2026-07 (subyacentes de los derivados sobre índice; baja del Micro IBEX 35)
- CME Rulebook, capítulo 358: E-mini S&P 500