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.

Fig. — Nominal y riesgo anual de un contrato de cada uno de los 23 futuros del curso y de sus seis micros y minis (26 de noviembre de 2025)
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)

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.

IN [01]python
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))
OUT [01]Las fichas de los 23 mercados
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: str

Seis 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.

FuturosFinancierosMaterias primasÍndicesTiposDivisasEnergíaMetalesAgrícolasEfectivoFísica con avisoFísica
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.

IN [02]python
cols = ["divisa", "multiplicador", "unidad_cotizacion", "tick",
        "valor_tick"]
base.loc[["RVA", "RVH", "TPC", "TPE", "PEC", "GNA", "MTO", "GRM",
          "DQE"], cols]
OUT [02]Multiplicador, tick y valor del tick
        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.250

El 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 realMultiplicadorTickVencimientosVencimiento y liquidación
E-mini S&P 500 (CME)50 USD × índice0,25 puntos = 12,50 USDTrimestralesTercer viernes; en efectivo, a la cotización especial de apertura
EURO STOXX 50 (Eurex, FESX)10 EUR × índice1 punto = 10 EURLos doce trimestrales más próximosTercer viernes (cierre a las 12:00 CET); en efectivo
IBEX 35 (MEFF)10 EUR × índicePuntos enteros, por circularDiez trimestrales, dos mensuales y semestralesTercer viernes; media del índice de 16:15 a 16:45; en efectivo
Mini IBEX 35 (MEFF)1 EUR × índice5 puntos = 5 EURIgual que el IBEX 35Igual que el IBEX 35
Euro-Bund (Eurex, FGBL)100.000 EUR, cupón del 6 %0,01 % = 10 EURLos tres trimestrales más próximosEntrega 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:

IN [03]python
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"]]
OUT [03]Códigos de mes y contratos listados
('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                True

Los 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:

IN [04]python
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"]
OUT [04]El contrato que se tiene en cada mercado
           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.000816

El 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:

IN [05]python
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})
OUT [05]Nominal en USD y riesgo anual de un contrato
        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.10

La 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.

IN [06]python
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]])
OUT [06]Margen inicial: porcentaje del nominal y apalancamiento
         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.36

El 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:

IN [07]python
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})
OUT [07]Contratos para un riesgo del 20 % con 100.000 USD
        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.0

Con 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:

IN [08]python
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)
OUT [08]Lo que cuesta un micro en puntos básicos
      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.58

Con 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):

liquidezfecha_rollprimer avisoefectivolargo dentrocerradoListadoCercanoRollAvisoVencidoEntrega
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 --> [*]
IN [09]python
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"]),
})
OUT [09]Calendario de cuatro contratos
                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           29
  • RVAZ25 (í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.
Fig. — Los últimos 140 días de tres contratos: cuándo tienen el mayor interés abierto, cuándo se tienen, el roll, el primer aviso y el vencimiento

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

IN [10]python
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]]
OUT [10]Volumen e interés abierto por mercado en 2025
         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               113

El 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.

IN [11]python
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)
OUT [11]Reparto del volumen a lo largo de la curva
            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.6

En 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:

IN [12]python
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))
OUT [12]Correlaciones dentro de cada sector y entre sectores
           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.0
Fig. — Correlación media de los rendimientos diarios dentro de cada sector y con el resto de mercados, 23 futuros sintéticos (2011-2025)

Dentro 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

  1. Calcula el nominal de un contrato RVE y de uno RVH el 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
IN [13]python
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}")
OUT [13]Riesgo de los índices en evros y en dólares
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.230

Un 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.

  1. 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
IN [14]python
n = 50_000 / ficha.loc[base.index, "riesgo_usd"]
print(n.round(2).sort_values().to_string())
OUT [14]Contratos para el mismo riesgo
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.23

Los í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).

  1. Explica por qué el PECF26 vence 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

  1. 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.

  2. ¿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.

  3. 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).

  4. ¿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.

  5. 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

Datos