---
title: "3.2.1 Spreads de calendario, butterflies y condors"
description: "Spreads de calendario, butterflies y condors de futuros: construcción por patas, riesgo frente a la posición simple, márgenes y convenciones de signo."
url: "https://pythonparatrading.com/curso-python-trading/nivel-3/spreads-de-calendario-butterflies-y-condors/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-3/spreads-de-calendario-butterflies-y-condors.png"
---

# 3.2.1 · Spreads de calendario, butterflies y condors

> Comprar un mes de un futuro y vender otro del mismo mercado elimina casi toda la exposición a la dirección del precio y deja otra: la forma de la curva. Esta lección construye calendarios, butterflies y condors con los contratos de cada sesión, mide cuánto riesgo queda en los mercados sintéticos del curso y por qué el margen baja en la misma proporción.

- Curso: [Nivel 3: Derivados: futuros, spreads, forex y opciones](https://pythonparatrading.com/curso-python-trading/nivel-3/)
- Módulo: 3.2 · Spreads de futuros
- Duración: 65 min
- Requisitos: [1.2.3 · Futuros: especificaciones, margen, roll y contango](https://pythonparatrading.com/curso-python-trading/nivel-1/futuros-especificaciones-margen-y-roll/), [1.4.6 · Series continuas de futuros: reglas de roll, ajuste por diferencia y ajuste por ratio](https://pythonparatrading.com/curso-python-trading/nivel-1/series-continuas-de-futuros/), [3.1.2 · Curva de futuros: base, cost of carry, contango y roll yield](https://pythonparatrading.com/curso-python-trading/nivel-3/curva-de-futuros-base-contango-y-roll-yield/)

## Al terminar esta lección

- Construir spreads de calendario, butterflies y condors a partir de las patas de la curva y calcular su P&L con los mismos contratos, sin los saltos del roll.
- Medir cuánto riesgo de la posición simple elimina cada estructura y qué parte de la dirección queda (efecto Samuelson).
- Relacionar el margen reducido de un spread con su riesgo y explicar por qué un margen pequeño no es una pérdida máxima.
- Explicar qué factor de la curva aísla una butterfly, cuándo deja de aislarlo (meses que cruzan una estación) y leer las convenciones de signo de los spreads listados.

## Un spread compra un mes y vende otro

Un futuro de crudo no es un contrato: son dieciocho, uno por mes de entrega, todos vivos a la vez (lección 1.2.3).
Comprar uno y vender otro del mismo mercado es un **spread de calendario** (también *intra-commodity spread*). Los
dos contratos responden casi igual a lo que mueve el precio del crudo, así que la dirección se cancela en buena parte.
Lo que queda es la diferencia entre ellos: la pendiente de la curva entre esos dos meses, que depende del coste de
mantener el subyacente, del almacenamiento y de la escasez del momento (lección 3.1.2).

Las curvas de esta lección son las del nivel 3 (`futuros3_curvas.parquet`): 23 mercados ficticios que imitan a
contratos reales, con la liquidación de **todos** los contratos listados en cada sesión de 2010 a 2025. Son datos
sintéticos: los niveles se parecen a la historia, pero no son datos de mercado.

```python
import numpy as np
import pandas as pd

cur = pd.read_parquet("futuros3_curvas.parquet")
ctr = pd.read_csv("futuros3_contratos.csv",
                  parse_dates=["vencimiento", "fecha_roll"])
esp = pd.read_csv("futuros3_especificaciones.csv",
                  index_col="mercado")
dia = cur[(cur["mercado"] == "PEC")
          & (cur["fecha"] == "2025-06-04")].merge(
    ctr[["contrato", "vencimiento"]]).sort_values("vencimiento")
print(len(dia), "contratos de PEC listados el 2025-06-04")
dia[["contrato", "vencimiento", "liquidacion", "volumen"]].head(4)
```
```output
18 contratos de PEC listados el 2025-06-04
   contrato vencimiento  liquidacion  volumen
6    PECN25  2025-06-20        53.35   256676
8    PECQ25  2025-07-22        53.23   288298
10   PECU25  2025-08-20        53.23    93695
12   PECV25  2025-09-22        53.32    34244
```

`PEC` imita al WTI de NYMEX (1.000 barriles por contrato). El contrato de julio (`PECN25`) vence el 20 de junio, pero
ya tiene menos volumen que el de agosto: la liquidez se ha ido al siguiente antes del vencimiento, que es lo que marca
la columna `fecha_roll` de `futuros3_contratos.csv`. Para construir estructuras conviene numerar las patas desde el
contrato que se tiene, el primero que aún no ha llegado a su fecha de roll:

```python
def patas(mercado, n=4):
    """Contratos 1.º, 2.º… de cada sesión. El 1.º es el que se
    tiene: el primero que aún no ha llegado a su fecha_roll."""
    c = cur[cur["mercado"] == mercado].merge(
        ctr[["contrato", "vencimiento", "fecha_roll"]],
        on="contrato")
    c = c[c["fecha"] < c["fecha_roll"]]
    c = c.sort_values(["fecha", "vencimiento"])
    c["k"] = c.groupby("fecha").cumcount() + 1
    return c[c["k"] <= n]

pec = patas("PEC")
pec.loc[pec["fecha"] == "2025-06-04",
        ["k", "contrato", "liquidacion"]]
```
```output
       k contrato  liquidacion
68564  1   PECN25        53.35
68566  2   PECQ25        53.23
68568  3   PECU25        53.23
68570  4   PECV25        53.32
```

Con las patas numeradas, cada estructura es un vector de pesos sobre ellas. El calendario es la diferencia de dos
patas; la **butterfly**, la diferencia de dos calendarios consecutivos que comparten la pata central; el **condor**,
la diferencia de dos calendarios que no la comparten:

```mermaid
flowchart LR
  S[Simple +1] --> C[Calendario +1 −1]
  C --> B[Butterfly +1 −2 +1]
  C --> K[Condor +1 −1 −1 +1]
```

| Estructura | Pesos (1.º, 2.º, 3.º, 4.º) | Precio | Qué neutraliza | Qué apuesta |
|---|---|---|---|---|
| Simple | +1 | $F_1$ | nada | dirección |
| Calendario | +1, −1 | $F_1 - F_2$ | casi toda la dirección | pendiente entre dos meses |
| Butterfly | +1, −2, +1 | $F_1 - 2F_2 + F_3$ | dirección y pendiente | curvatura alrededor del 2.º |
| Condor | +1, −1, −1, +1 | $(F_1 - F_2) - (F_3 - F_4)$ | dirección y casi toda la pendiente | curvatura en un tramo más ancho |

Comprar el calendario 1.º − 2.º (largo en el cercano, corto en el siguiente) gana si el cercano sube más que el
siguiente: si la curva se empina en **backwardation** o se aplana en contango. Comprar la butterfly gana si el mes
central baja respecto a la media de sus vecinos.

## La serie de niveles y el P&L con los mismos contratos

La serie más fácil de construir es la del nivel del spread: en cada sesión, la liquidación del 1.º menos la del 2.º.

```python
niv = pec.pivot(index="fecha", columns="k", values="liquidacion")
cal = niv[1] - niv[2]                    # USD por barril
print(cal.describe().round(2).to_string())
print(f"Sesiones en backwardation (1.º > 2.º): {(cal > 0).mean():.1%}")
```
```output
count    4024.00
mean        0.15
std         1.64
min        -3.54
25%        -1.04
50%         0.14
75%         1.15
max         4.94
Sesiones en backwardation (1.º > 2.º): 53.5%
```

El spread del crudo sintético va de −3,54 USD por barril (contango profundo) a +4,94 (backwardation) y pasa algo más
de la mitad de las sesiones en backwardation. Esa serie sirve para describir la curva, pero no es el P&L de nadie. El
día del roll, «1.º» y «2.º» pasan a ser otros contratos y la serie salta sin que ninguna posición haya ganado ni
perdido ese salto, el mismo problema de las series continuas de la lección 1.4.6:

```python
rolls = ctr.loc[ctr["mercado"] == "PEC", "fecha_roll"]
salto = cal.diff()
en_roll = salto.index.isin(rolls)
print(f"Cambio medio absoluto en día de roll: "
      f"{salto[en_roll].abs().mean():.3f} USD/barril")
print(f"Resto de sesiones:                  "
      f"{salto[~en_roll].abs().mean():.3f} USD/barril")
```
```output
Cambio medio absoluto en día de roll: 0.270 USD/barril
Resto de sesiones:                  0.156 USD/barril
```

En el día de roll la serie cambia de media un 70 % más que el resto de días, y ese cambio es un artefacto. El P&L
correcto se calcula con los contratos que tenía la posición al cierre anterior: los pesos se fijan con las patas de
la sesión $t-1$ y se aplican a los cambios de esos mismos contratos entre $t-1$ y $t$. Con $M$ el multiplicador:

$$
\text{PyG}_t = M \sum_k w_k \left(F_{k,t} - F_{k,t-1}\right), \qquad k \text{ fijado en } t-1 .
$$

```python
def cambios(mercado, n, log=False):
    """Cambio diario de cada pata k = 1..n con los contratos que
    tenía la estructura al cierre anterior (sin saltos de roll)."""
    p = patas(mercado, n)
    px = cur[cur["mercado"] == mercado].pivot(
        index="fecha", columns="contrato", values="liquidacion")
    d = (np.log(px) if log else px).diff().stack()
    ley = p.pivot(index="fecha", columns="k",
                  values="contrato").shift(1).dropna()
    out = {k: d.reindex(pd.MultiIndex.from_arrays(
        [ley.index, ley[k]])).to_numpy() for k in ley.columns}
    return pd.DataFrame(out, index=ley.index)

def pyg(mercado, pesos):
    """P&L diario en la divisa del contrato, por estructura."""
    c = cambios(mercado, len(pesos))
    mult = esp.loc[mercado, "multiplicador"]
    return (c @ np.array(pesos) * mult).dropna()

ESTRUCTURAS = {"simple": [1], "calendario": [1, -1],
               "butterfly": [1, -2, 1], "condor": [1, -1, -1, 1]}
vol = pd.DataFrame({m: {n: pyg(m, w).loc["2025"].std()
                        for n, w in ESTRUCTURAS.items()}
                    for m in ["RVA", "MTO", "PEC", "PEG",
                              "GRM", "GNA"]}).T
vol.round(0)
```
```output
     simple  calendario  butterfly  condor
RVA  3957.0        41.0       25.0    24.0
MTO  1622.0        15.0       10.0     8.0
PEC  1258.0       149.0       29.0    46.0
PEG  1816.0       321.0      100.0   159.0
GRM   302.0        53.0       28.0    35.0
GNA  1695.0       637.0      639.0   596.0
```

La tabla es la figura de la cabecera: desviación típica del P&L diario por contrato en 2025, en USD. En el índice
`RVA` (imita al E-mini S&P 500), el calendario se mueve una centésima parte de lo que se mueve el futuro; en el oro,
todavía menos. En el crudo, el calendario conserva un 12 % del riesgo y la butterfly un 2,3 %. En el maíz y la
gasolina, el calendario conserva cerca del 18 %. El gas es la excepción que esta lección explica más abajo: su
butterfly (639 USD) se mueve tanto como su calendario (637).

## Qué queda de la dirección

Un calendario no es neutral a la dirección por construcción. Si los dos contratos se movieran lo mismo, su diferencia
no tendría riesgo; no lo hacen. En las materias primas, el cercano reacciona más a los choques que se espera que
reviertan (el **efecto Samuelson**, medido en la lección 3.1.2), así que largo en el 1.º y corto en el 2.º conserva un
pequeño largo:

```python
for m in ["RVA", "PEC", "GRM", "GNA"]:
    d = pd.concat([pyg(m, [1]), pyg(m, [1, -1])], axis=1,
                  keys=["simple", "cal"]).dropna()
    beta = d.cov().loc["cal", "simple"] / d["simple"].var()
    print(f"{m}: beta {beta:+.3f}  correlación "
          f"{d.corr().loc['cal', 'simple']:+.2f}")
```
```output
RVA: beta -0.003  correlación -0.20
PEC: beta +0.106  correlación +0.92
GRM: beta +0.238  correlación +0.89
GNA: beta +0.228  correlación +0.74
```

En el crudo, por cada 1.000 USD que gana la pata cercana, el calendario gana 106. Es poco en tamaño, pero la
correlación de 0,92 dice que el calendario de crudo es, sobre todo, una versión reducida de la posición simple. En el
maíz y en el gas la beta es mayor (0,24 y 0,23). Quien opera un calendario como si fuera «neutral» y lo combina con
una posición simple en el mismo mercado está sumando exposición, no cubriéndola. Las coberturas que corrigen esta beta
(por nominal, por DV01, por volatilidad) son el tema de la lección 3.2.4.

En el índice la beta es casi cero, por otra razón: el calendario de un índice no depende de choques que revierten,
sino de la financiación. Un futuro de índice vale el contado capitalizado al tipo menos los dividendos (lección 3.1.2),
así que la diferencia entre dos vencimientos es, casi exactamente, la financiación neta del tramo que los separa:

$$
F_2 - F_1 \approx S \, (r - q) \, (\tau_2 - \tau_1).
$$

```python
idx = pd.read_csv("futuros3_indices_contado.csv",
                  parse_dates=["fecha"])
s = idx[idx["indice"] == "RVA"].set_index("fecha")
rva = patas("RVA", 2)
f = rva.pivot(index="fecha", columns="k", values="liquidacion")
v = rva.pivot(index="fecha", columns="k", values="vencimiento")
dias = v.sub(v.index.to_series(), axis=0).apply(
    lambda c: c.dt.days)
carry = (s["tipo_1m"] - s["rentabilidad_dividendo"]) / 100
teo = s["contado"].to_numpy()[:, None] * np.exp(
    carry.to_numpy()[:, None] * dias / 365)
eq = pd.DataFrame({"real": f[2] - f[1],          # 2.º − 1.º
                   "teorico": teo[2] - teo[1]}).dropna()
print(f"Correlación: {eq.corr().iloc[0, 1]:.4f}; diferencia "
      f"mediana {(eq['real'] - eq['teorico']).abs().median():.2f}"
      " puntos")
eq.resample("YE").mean().round(1).loc["2019":]
```
```output
Correlación: 0.9997; diferencia mediana 0.14 puntos
            real  teorico
fecha
2019-12-31   2.9      3.0
2020-12-31  -7.9     -7.9
2021-12-31 -11.7    -11.7
2022-12-31   2.0      1.8
2023-12-31  30.1     30.1
2024-12-31  41.4     41.6
2025-12-31  39.1     38.9
```

La fórmula de financiación explica el calendario del índice con una correlación de 0,9997 y un error mediano de 0,14
puntos, menos que su tick (0,25). Con tipos por debajo de la rentabilidad por dividendo (2020 y 2021), el contrato
lejano cotiza por debajo del cercano; con tipos del 4-5 % (2023-2025), unos 40 puntos por encima. Para quien mantiene
el futuro y lo rueda cada trimestre, ese spread es el precio del roll (lección 3.1.3). Para quien lo opera, es una
apuesta sobre los tipos a corto y los dividendos, no sobre la bolsa.

```mermaid
flowchart TB
  C[Calendario] --> I["Índice: r − q"]
  C --> B["Bono: cupón y repo"]
  C --> A[Almacenable: stock]
  C --> E[Gas: estación]
```

Lo que mueve un calendario depende del mercado: la financiación neta en índices y divisas; el cupón, la financiación
y el bono más barato de entregar en los bonos; el almacenamiento y la escasez en crudo, metales y granos; y, en el gas
y la electricidad, el salto entre estaciones.

## Márgenes reducidos

Una cámara de compensación no pide margen por pata, sino por el riesgo de la cartera (el SPAN de la lección 3.1.3).
Si un calendario se mueve un 12 % de lo que se mueve la posición simple, su margen puede ser, aproximadamente, un 12 %
del de la posición simple. En los datos, `margen_spread_calendario` se fijó así: el mismo número de desviaciones
diarias que cubre el margen simple, aplicado a la desviación típica del spread. El cálculo con los 23 mercados:

```python
base = esp[esp["mercado_base"].isna()].index
filas = {}
for m in base:
    s1 = pyg(m, [1]).loc["2025"].std()
    s2 = pyg(m, [1, -1]).loc["2025"].std()
    filas[m] = {"riesgo": s2 / s1,
                "margen": esp.loc[m, "margen_spread_calendario"]
                / esp.loc[m, "margen_inicial"]}
rel = pd.DataFrame(filas).T.sort_values("riesgo")
print(rel.round(3).T.to_string())
```
```output
          RVH    MTO    RVC   RVB   RVA    RVE    MTP    DQE    TPD    TPE    TPC    TPB    PEC    TPA    PEH    GRM    PEG    GRT    GRS    GRA    GRH    GNA    ELB
riesgo  0.004  0.009  0.009  0.01  0.01  0.012  0.013  0.022  0.033  0.045  0.053  0.073  0.118  0.136  0.146  0.175  0.177  0.181  0.185  0.192  0.199  0.376  0.389
margen  0.030  0.030  0.030  0.03  0.03  0.029  0.030  0.029  0.033  0.043  0.052  0.072  0.120  0.140  0.147  0.179  0.174  0.186  0.178  0.188  0.195  0.388  0.438
```

*Fig. — Margen del spread de calendario frente a su riesgo, en proporción a la posición simple, en los 23 mercados.* Dispersión logarítmica de los 23 mercados: en el eje horizontal, la desviación típica del P&L diario del calendario 1.º − 2.º dividida por la de la posición simple (2025); en el vertical, el margen del calendario dividido por el margen inicial simple. Casi todos los puntos caen sobre la diagonal: bonos de 3,3 a 14 %, crudo 12 %, agrícolas y productos en torno al 18 %, gas 38 a 39 % y electricidad 39 a 44 %. Los índices, los metales y la divisa, con un riesgo del 0,4 al 2,2 %, se quedan en la línea destacada del 3 %, el suelo del margen.

Desde los bonos hasta la electricidad, las dos filas casi coinciden: el margen del calendario es proporcional a su
riesgo, del 3,3 % del margen simple en el bono a 30 años (`TPD`) al 44 % en la electricidad (`ELB`). Los índices, el
oro, la plata y la divisa se quedan en el 3 %, aunque su riesgo relativo esté entre el 0,4 y el 2,2 %: el generador de
los datos aplica un suelo del 3 % del margen simple. Las cámaras reales también aplican mínimos y recargos a los
spreads (por ejemplo, entre vencimientos que cruzan un periodo de entrega) y los publican con sus parámetros de margen.

Un margen reducido es, ante todo, apalancamiento:

```python
m = esp.loc["PEC"]
precio = niv[1].loc["2025"].median()
print(f"Nominal de una pata: {10 * precio * m['multiplicador']:,.0f}"
      " USD")
print(f"Margen de 10 largos y 10 cortos sueltos: "
      f"{20 * m['margen_inicial']:,.0f} USD")
print(f"Margen de 10 spreads de calendario: "
      f"{10 * m['margen_spread_calendario']:,.0f} USD")
```
```output
Nominal de una pata: 618,500 USD
Margen de 10 largos y 10 cortos sueltos: 112,000 USD
Margen de 10 spreads de calendario: 6,700 USD
```

Con 6.700 USD de margen se controlan 618.500 USD de nominal en cada pata, más de 1,2 millones entre las dos. La cifra
de nominal no dice nada del riesgo, que es el del spread; pero el margen tampoco dice cuánto se puede perder.

<aside class="callout" data-kind="riesgo">

El margen cubre unas pocas desviaciones típicas de un día normal, no el peor día. El segundo ejercicio lo mide: en
2016–2025, el peor día de 10 calendarios de crudo costó 1,9 veces su margen inicial, y diez sesiones superaron el
margen entero. Un spread «de bajo riesgo» con mucho apalancamiento se comporta como una posición simple con mucho
apalancamiento. Además, cuando la volatilidad sube, la cámara sube los márgenes justo cuando el spread pierde.

</aside>

## Butterflies y condors: la curvatura

Si el calendario deja la pendiente, la butterfly intenta quitarla también. Para ver qué queda hace falta saber cómo se
mueve la curva entera, y para eso sirve un análisis de componentes principales (PCA): los autovectores de la matriz de
covarianza de los cambios diarios de los doce primeros contratos. En curvas de tipos y de materias primas, los tres
primeros suelen leerse como **nivel** (toda la curva a la vez), **pendiente** (el corto contra el largo) y
**curvatura** (el centro contra los extremos). En el gas:

```python
r = cambios("GNA", 12, log=True).dropna()
val, vec = np.linalg.eigh(np.cov(r.T))
val, vec = val[::-1], vec[:, ::-1]
vec = vec * np.sign(vec[0])           # carga positiva en la 1.ª
print("Varianza explicada:", (val[:4] / val.sum()).round(3))
cargas = pd.DataFrame(vec[:, :3], index=r.columns,
                      columns=["nivel", "pendiente", "curvatura"])
cargas.T.round(2)
```
```output
Varianza explicada: [0.841 0.118 0.022 0.008]
             1     2     3     4     5     6     7     8     9     10    11    12
nivel      0.50  0.42  0.36  0.31  0.27  0.24  0.22  0.20  0.19  0.18  0.17  0.17
pendiente  0.55  0.31  0.11 -0.04 -0.16 -0.24 -0.29 -0.31 -0.31 -0.29 -0.27 -0.25
curvatura  0.38  0.02 -0.28 -0.41 -0.40 -0.30 -0.09  0.10  0.25  0.33  0.32  0.27
```

*Fig. — Los tres primeros componentes principales de los cambios diarios de la curva del gas, 2010–2025.* Tres líneas sobre los contratos 1.º a 12.º del gas GNA. El nivel (84,1 % de la varianza) carga en todos con el mismo signo, de 0,50 en el primero a 0,17 en el último. La pendiente (11,8 %) pasa de 0,55 en el primero a −0,31 en el octavo. La curvatura, destacada (2,2 %), es positiva en los extremos (0,38 y 0,27) y negativa en el centro (−0,41 en el cuarto y −0,40 en el quinto).

El nivel explica el 84,1 % de la varianza y carga más en los contratos cercanos (otra vez el efecto Samuelson: de 0,50
en el primero a 0,17 en el duodécimo). La pendiente (11,8 %) separa los cuatro primeros del resto. La curvatura
(2,2 %) es positiva en los extremos y negativa en el centro. La exposición de cada estructura a cada factor es el
producto de sus pesos por las cargas, y el reparto de su varianza entre los tres factores, esa exposición al cuadrado
por la varianza de cada uno:

```python
pesos = pd.DataFrame({n: (w + [0] * 12)[:12]
                      for n, w in ESTRUCTURAS.items()},
                     index=cargas.index)
expo = pesos.T @ cargas
print(expo.round(2))
reparto = expo ** 2 * val[:3]
(100 * reparto.div(reparto.sum(axis=1), axis=0)).round(0)
```
```output
            nivel  pendiente  curvatura
simple       0.50       0.55       0.38
calendario   0.08       0.24       0.35
butterfly    0.02       0.04       0.05
condor       0.03       0.09       0.23
            nivel  pendiente  curvatura
simple       84.0       14.0        1.0
calendario   37.0       45.0       19.0
butterfly    58.0       33.0        9.0
condor       31.0       29.0       40.0
```

El calendario reduce la exposición al nivel de 0,50 a 0,08, y su varianza dentro de estos tres factores se reparte
entre nivel (37 %), pendiente (45 %) y curvatura (19 %): es sobre todo una apuesta de pendiente con algo de nivel, la
beta de la sección anterior. La butterfly casi no se expone a ninguno de los tres (0,02, 0,04 y 0,05): sus pesos
+1 −2 +1 son casi ortogonales a las tres cargas, y el reparto de su poca exposición importa poco. El condor queda
expuesto sobre todo a la curvatura (0,23). Según este PCA, la butterfly del gas debería tener muy poco riesgo; la
tabla del principio dice que en 2025 se movió 639 USD al día, tanto como el calendario. Lo que falta no está en estos
tres factores.

Pero el PCA por orden de vencimiento promedia contratos de meses distintos: el 3.º es octubre en julio y marzo en
diciembre. En un mercado con estaciones, lo que importa es qué meses de entrega cruza la estructura. El gas tiene un
factor de invierno (en el modelo de los datos, carga +0,5 de noviembre a marzo y −0,5 de abril a octubre), y una
butterfly cuyas alas caen a los dos lados de ese salto no lo neutraliza:

```python
g = cur[cur["mercado"] == "GNA"]
mes = g["contrato"].str[3].map("FGHJKMNQUVXZ".index)
n = (g["contrato"].str[4:].astype(int) + 2000) * 12 + mes
px = g.assign(n=n).pivot(index="fecha", columns="n",
                         values="liquidacion")
d = px.diff() * esp.loc["GNA", "multiplicador"]
hoy = px.index.year * 12 + px.index.month - 1
por_mes = {}
for c in px.columns[1:-1]:
    fly = d[c - 1] - 2 * d[c] + d[c + 1]
    ok = (c - hoy >= 3) & (c - hoy <= 9) & (px.index.year >= 2016)
    por_mes.setdefault("FGHJKMNQUVXZ"[c % 12], []).append(fly[ok])
riesgo = pd.Series({k: pd.concat(v).std()
                    for k, v in por_mes.items()})
riesgo.reindex(list("FGHJKMNQUVXZ")).round(0).to_frame("usd_dia").T
```
```output
            F     G      H      J     K     M     N     Q     U      V      X     Z
usd_dia  54.0  55.0  391.0  489.0  45.0  31.0  43.0  44.0  71.0  422.0  511.0  35.0
```

*Fig. — Riesgo diario de una butterfly de gas de meses consecutivos según el mes de su pata central, 2016–2025.* Doce barras, una por mes de entrega de la pata central de una butterfly +1 −2 +1 de meses seguidos, a 3–9 meses del vencimiento. Ocho meses dan entre 31 y 71 USD por día. Las que cruzan el paso de invierno a verano (marzo 391, abril 489) y de verano a invierno (octubre 422, noviembre 511, destacada) multiplican el riesgo por siete u ocho.

Cada columna es una butterfly de tres meses de entrega seguidos, identificada por su mes central (código de mes de
futuros: F enero, G febrero… Z diciembre), cuando le quedan de 3 a 9 meses. Ocho de las doce se mueven entre 31 y 71
USD al día. Las cuatro que cruzan un cambio de estación —centradas en marzo y abril (febrero-marzo-abril y
marzo-abril-mayo) y en octubre y noviembre— se mueven entre 391 y 511: siete u ocho veces más. Son las estructuras
que convierten una butterfly de gas en una apuesta sobre el invierno, y las que más sorprenden a quien la trata como
«casi sin riesgo».

<aside class="callout" data-kind="aviso">

No confundas el nivel estacional de la curva con una deriva. Que el contrato de enero cotice por encima del de octubre
(en el gas de los datos, 6,875 frente a 5,363 el 4 de junio de 2025) es una forma de la curva que el mercado ya
descuenta: no da rendimiento por sí sola. Si hay o no una deriva estacional operable en un spread es la pregunta de la
lección 3.2.6.

</aside>

## Spreads listados y convenciones de signo

Los calendarios, butterflies y condors no solo se construyen por patas: las bolsas los listan como instrumentos con su
propio libro de órdenes. Una orden sobre el spread se ejecuta entera o no se ejecuta, sin el riesgo de quedarse con una
pata sola. En los datos, `spreads3_cotizados.parquet` tiene el libro al cierre del calendario 1.º − 2.º de seis
mercados:

```python
cot = pd.read_parquet("spreads3_cotizados.parquet")
fila = cot[(cot["mercado"] == "PEC")
           & (cot["fecha"] == "2025-06-04")].iloc[0]
print(fila[["spread", "liquidacion", "bid", "ask"]].to_string())
leg = niv.loc["2025-06-04"]
print(f"1.º − 2.º con las liquidaciones: {leg[1] - leg[2]:.2f}")
```
```output
spread         PECN25-PECQ25
liquidacion             0.12
bid                     0.12
ask                     0.13
1.º − 2.º con las liquidaciones: 0.12
```

El spread `PECN25-PECQ25` liquida a 0,12 USD por barril, la diferencia de las liquidaciones de las patas, y su libro
cotiza a un tick (0,12 a 0,13). Comparar ese libro con el spread «sintético» que se obtiene cruzando las horquillas de
las dos patas, y lo que cuesta ejecutar una pata y esperar a la otra (*legging risk*), es el tema de la lección 3.2.5.

Antes de enviar una orden sobre un spread listado hay que leer su convención de signo, porque no es la misma en todos
los productos. La documentación de CME Globex define, entre otros:

| Tipo de Globex | Ejemplo | Comprar el spread | Precio |
|---|---|---|---|
| SP, calendario estándar | `NGZ9-NGF0` | compra la pata 1 (cercana), vende la 2 | pata 1 − pata 2 |
| EQ, calendario de índices bursátiles | `ESU9-ESZ9` | **vende** la pata 1 (cercana), compra la 2 | pata 2 − pata 1 |
| BF, butterfly | `SR1:BF M9-U9-Z9` | compra la 1, vende 2 de la 2, compra la 3 | pata 1 − 2 × pata 2 + pata 3 |
| CF, condor | `SR1:CF M9U9Z9H0` | compra la 1, vende la 2 y la 3, compra la 4 | pata 1 − pata 2 − pata 3 + pata 4 |

<aside class="callout" data-kind="aviso">

El calendario de índices bursátiles de CME es la excepción que la propia documentación señala: el símbolo lista
primero la pata cercana, pero comprarlo compra la lejana, y su precio es lejana menos cercana (la columna `real` de la
celda del índice). En los datos del curso, en cambio, todos los spreads cotizados son cercano menos lejano. Un sistema
que mezcla fuentes tiene que normalizar el signo antes de calcular nada.

</aside>

## Lo que esto cambia en un sistema

- **El P&L, con los mismos contratos.** Una serie de niveles 1.º − 2.º sirve para describir la curva; para un backtest
  hay que fijar los contratos de cada día y rodar la estructura entera en una fecha decidida de antemano.
- **Neutral no es sin riesgo.** El calendario de crudo conserva una beta de 0,11 y una correlación de 0,92 con la
  posición simple; la butterfly del gas que cruza una estación se mueve como un calendario.
- **El margen pequeño es apalancamiento.** El tamaño de una posición en spreads se decide por su riesgo medido (y por
  su peor día), no por lo que deja abrir el margen.
- **Cada mercado tiene su motor.** En índices, el calendario es financiación; en materias primas, almacenamiento y
  estaciones. Una regla que funciona en uno no tiene por qué funcionar en otro.
- **El signo, antes que nada.** Cercano menos lejano o lejano menos cercano: depende de la bolsa, del producto y del
  proveedor de datos.

## Ejercicios

1. Comprueba que un condor de gas es exactamente la diferencia de dos calendarios (1.º − 2.º y 3.º − 4.º) y mide en
   2025 el riesgo de cada uno y su correlación. ¿Por qué el condor (596 USD) no tiene menos riesgo que el calendario
   1.º − 2.º (637)?

**Solución.**

```python
c = cambios("GNA", 4) * esp.loc["GNA", "multiplicador"]
condor = c[1] - c[2] - c[3] + c[4]
dos_cal = (c[1] - c[2]) - (c[3] - c[4])
print("Idénticos:", np.allclose(condor.dropna(), dos_cal.dropna()))
d = pd.DataFrame({"cal_1_2": c[1] - c[2], "cal_3_4": c[3] - c[4]})
print(d.loc["2025"].std().round(0).to_string())
print(f"Correlación: {d.loc['2025'].corr().iloc[0, 1]:.2f}")
```
```output
Idénticos: True
cal_1_2    637.0
cal_3_4    332.0
Correlación: 0.38
```

El condor es la diferencia de los dos calendarios. Restar dos posiciones reduce el riesgo solo si están muy
correladas: con una correlación de 0,38 y riesgos de 637 y 332 USD, la varianza del condor es
$637^2 + 332^2 - 2 \cdot 0{,}38 \cdot 637 \cdot 332$ y su desviación típica, unos 596 USD. En el gas, el calendario
cercano y el lejano se mueven por razones distintas (el cercano, por el tiempo del momento; el lejano, por el salto de
estación que tenga dentro), así que el condor no cancela casi nada. En el crudo, donde los calendarios consecutivos se
parecen mucho, el condor tiene un tercio del riesgo del calendario (46 frente a 149 USD).

2. Con los márgenes de la ficha de `PEC`, compara 10 largos en el contrato que se tiene con 10 calendarios 1.º − 2.º
   en 2016–2025: el peor día en USD, cuántas veces el margen inicial y en cuántas sesiones la pérdida del día supera
   el margen entero.

**Solución.**

```python
for nombre, w, marg in [
        ("10 largos", [1], 10 * m["margen_inicial"]),
        ("10 calendarios", [1, -1],
         10 * m["margen_spread_calendario"])]:
    p = 10 * pyg("PEC", w).loc["2016":]
    peor = p.min()
    print(f"{nombre}: peor día {peor:,.0f} USD = "
          f"{-peor / marg:.1f} veces el margen; "
          f"días que superan el margen: {(p < -marg).sum()}")
```
```output
10 largos: peor día -92,800 USD = 1.7 veces el margen; días que superan el margen: 9
10 calendarios: peor día -13,000 USD = 1.9 veces el margen; días que superan el margen: 10
```

En dinero, el calendario pierde siete veces menos en su peor día (13.000 frente a 92.800 USD). En proporción al
margen, pierde lo mismo o más: 1,9 veces el margen frente a 1,7, y la pérdida del día supera el margen entero en
nueve sesiones con los largos y en diez con los calendarios. Como el margen del spread se fijó con el mismo número
de desviaciones que el simple, el apalancamiento sobre el margen es el mismo; el spread solo es «más seguro» si se opera con el mismo número de contratos, no con el
mismo margen. Los márgenes de la ficha son los de 2025 aplicados a toda la década: con los de cada momento, la
comparación cambiaría.

3. Un sistema compra 10 spreads `ESU9-ESZ9` en CME (tipo EQ) pensando que está largo en septiembre y corto en
   diciembre. ¿Qué posición tiene en realidad y qué le pasa si los tipos a corto suben y la rentabilidad por dividendo
   no cambia?

**Solución.**

Está corto en septiembre y largo en diciembre: en el calendario EQ de índices bursátiles, comprar el spread compra la
pata lejana. El precio del spread es diciembre menos septiembre, que según la fórmula de financiación es
$S \cdot (r - q) \cdot (\tau_2 - \tau_1)$. Si $r$ sube y $q$ no cambia, el spread sube y la posición, larga en el
spread, gana. El sistema creía tener la apuesta contraria: si su intención era beneficiarse de una bajada de tipos,
con la lectura equivocada del signo ha abierto justo lo opuesto. Por eso conviene que el código lea las patas y el
signo de la definición del instrumento, no del nombre.

## Autoevaluación

1. En el crudo de los datos, el spread 1.º − 2.º tiene una desviación típica diaria de 149 USD por contrato frente a 1.258 de la posición simple, y su beta a la pata cercana es +0,106. ¿Qué significa esa beta?

   - A. Que el spread no tiene ninguna exposición a la dirección del crudo
   - B. Que por cada 1.000 USD que gana o pierde la pata cercana, el calendario gana o pierde unos 106 en el mismo sentido: el contrato cercano se mueve más que el siguiente
   - C. Que el spread está cointegrado con el crudo
   - D. Que hay que vender 0,106 contratos del segundo mes por cada uno del primero

   *Respuesta B: Que por cada 1.000 USD que gana o pierde la pata cercana, el calendario gana o pierde unos 106 en el mismo sentido: el contrato cercano se mueve más que el siguiente.* Es el efecto Samuelson de la lección 3.1.2: el contrato cercano reacciona más que el siguiente a los choques que revierten, así que largo en el cercano y corto en el siguiente conserva un pequeño largo en crudo. La correlación entre los dos P&L es 0,92: el calendario se mueve casi siempre en la dirección del crudo, pero con una décima parte del tamaño.

2. ¿Cuánto margen inicial piden 10 spreads de calendario de PEC frente a 10 largos y 10 cortos de los mismos contratos tratados por separado?

   - A. Lo mismo: son las mismas 20 patas
   - B. La mitad, porque una pata compensa la otra
   - C. 6.700 USD frente a 112.000: el margen del spread sigue a su riesgo, un 12 % del de la posición simple
   - D. Nada, porque el riesgo neto es cero

   *Respuesta C: 6.700 USD frente a 112.000: el margen del spread sigue a su riesgo, un 12 % del de la posición simple.* La cámara mira el riesgo de la cartera, no el número de patas (lección 3.1.3). El margen del calendario de PEC es 670 USD frente a 5.600 de la posición simple: el 12 %, la misma proporción que su desviación típica diaria. Con ese margen se controla un nominal de 618.500 USD por pata.

3. Una butterfly de gas de meses seguidos con la pata central en noviembre tiene un riesgo diario de 511 USD; con la central en junio, de 31. ¿Por qué?

   - A. Porque en noviembre hay menos liquidez
   - B. Porque sus alas cruzan el paso de verano a invierno: el factor de invierno del gas carga con signo opuesto en octubre y en noviembre, y los pesos +1 −2 +1 no lo neutralizan
   - C. Porque el contrato de noviembre vence antes
   - D. Por azar: con diez años de datos la diferencia no significa nada

   *Respuesta B: Porque sus alas cruzan el paso de verano a invierno: el factor de invierno del gas carga con signo opuesto en octubre y en noviembre, y los pesos +1 −2 +1 no lo neutralizan.* Una butterfly neutraliza nivel y pendiente si la curva es suave entre sus tres meses. La del gas tiene un salto entre octubre y noviembre (y otro entre marzo y abril): cualquier butterfly que lo cruce queda expuesta a ese factor. Las cuatro que lo cruzan dan entre 391 y 511 USD; las ocho que no, entre 31 y 71.

4. En CME, comprar el spread `ESU9-ESZ9` (calendario de índice bursátil, tipo EQ) significa:

   - A. Comprar septiembre y vender diciembre; el precio es septiembre menos diciembre
   - B. Vender septiembre y comprar diciembre; el precio es diciembre menos septiembre
   - C. Comprar los dos contratos
   - D. Lo mismo que comprar `NGZ9-NGF0`: comprar la primera pata

   *Respuesta B: Vender septiembre y comprar diciembre; el precio es diciembre menos septiembre.* La documentación de Globex lo señala como excepción: en el calendario estándar (SP, p. ej. `NGZ9-NGF0`) comprar el spread compra la primera pata y el precio es pata 1 − pata 2; en el calendario de índices bursátiles (EQ), comprar compra la pata lejana y el precio es lejana − cercana. Leer mal la convención invierte la posición.

5. En los índices, los metales y la divisa de los datos, el margen del calendario es el 3 % del margen simple, aunque su riesgo sea solo del 0,4 al 2,2 % del de la posición simple. ¿Qué indica?

   - A. Un error en los datos
   - B. Que el riesgo de esos spreads es mayor de lo que dicen las desviaciones típicas
   - C. Un suelo: el margen no baja de un mínimo, así que en esos mercados cubre muchas más desviaciones diarias del spread que en el resto
   - D. Que esos mercados no admiten spreads de calendario

   *Respuesta C: Un suelo: el margen no baja de un mínimo, así que en esos mercados cubre muchas más desviaciones diarias del spread que en el resto.* El generador fija el margen del spread con el mismo número de desviaciones que el simple y un suelo del 3 % del margen simple. Donde el spread casi no se mueve (financiación pura en índices, oro y divisa) manda el suelo: el margen del calendario del índice RVA cubre unas 15 desviaciones diarias de su P&L, frente a 5 de la posición simple.

## Ideas clave

- Un spread de calendario compra un mes y vende otro del mismo mercado: elimina casi toda la dirección y deja la pendiente de la curva. En los datos, su riesgo diario va del 0,4 % (índices) al 39 % (electricidad) del de la posición simple.
- El P&L de una estructura se calcula con los mismos contratos de un día a otro; la serie de niveles 1.º − 2.º salta en cada roll.
- Butterfly (+1 −2 +1) y condor (+1 −1 −1 +1) neutralizan también casi toda la pendiente: apuestan por la curvatura. En el gas, la que cruza el paso entre estaciones tiene siete u ocho veces más riesgo que las demás.
- El margen del spread sigue a su riesgo (12 % del simple en el crudo) con un suelo; el apalancamiento nominal es enorme y el peor día de 2016–2025 de 10 calendarios de crudo costó 1,9 veces su margen.
- En un índice, el calendario es financiación: la diferencia 2.º − 1.º sigue a S·(r − q)·Δτ con una correlación de 0,9997.
- Las convenciones de signo cambian según el producto: en CME el calendario estándar compra la pata cercana; el de índices bursátiles, la lejana.

## Recursos

### Documentación

- [CME Group Client Systems Wiki: Spreads and Combinations Available on CME Globex (SP, EQ, BF, CF: patas, signo y precio)](https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457089763/Spreads+and+Combinations+Available+on+CME+Globex) · cmegroupclientsite.atlassian.net
- [CME Group: SOFR Futures and Options Globex Strategy Guide (calendarios, butterflies y condors como instrumentos)](https://www.cmegroup.com/articles/2024/sofr-futures-and-options-globex-strategy-guide.html) · cmegroup.com

### Datos

- [Datos del nivel 3: curvas completas de 23 mercados de futuros, 2010-2025 (Parquet)](https://pythonparatrading.com/curso/datos/nivel-3/futuros3_curvas.parquet) · Descarga · futuros3_curvas.parquet
- [Datos del nivel 3: especificaciones y márgenes, también del spread de calendario (CSV)](https://pythonparatrading.com/curso/datos/nivel-3/futuros3_especificaciones.csv) · Descarga · futuros3_especificaciones.csv
- [Datos del nivel 3: spreads de calendario cotizados con su libro (Parquet)](https://pythonparatrading.com/curso/datos/nivel-3/spreads3_cotizados.parquet) · Descarga · spreads3_cotizados.parquet

Lección anterior: [3.1.4 · Sistemas de futuros diversificados: el enfoque de Carver](https://pythonparatrading.com/curso-python-trading/nivel-3/sistemas-de-futuros-diversificados-carver/)

Lección siguiente: [3.2.2 · Spreads intercommodity: crack, spark y crush](https://pythonparatrading.com/curso-python-trading/nivel-3/spreads-intercommodity-crack-spark-y-crush/)
