---
title: "1.2.5 Opciones: call, put, prima y cadenas"
description: "Qué es una call y una put, cómo se reparte la prima entre valor intrínseco y extrínseco, americanas frente a europeas y cómo leer una cadena."
url: "https://pythonparatrading.com/curso-python-trading/nivel-1/opciones-call-put-y-valor-temporal/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-1/opciones-call-put-y-valor-temporal.png"
---

# 1.2.5 · Opciones: call, put, valor intrínseco y valor temporal

> Una opción es un derecho con fecha de caducidad, y su precio se divide en lo que vale ejercerla hoy y lo que vale esperar. La lección lo mide sobre la cadena completa de opciones del índice ficticio FIX de un día: 584 contratos, cuatro vencimientos.

- Curso: [Nivel 1: Datos financieros, mercados y análisis](https://pythonparatrading.com/curso-python-trading/nivel-1/)
- Módulo: 1.2 · Clases de activos
- Duración: 60 min
- Requisitos: [1.1.3 · Libro de órdenes: bid, ask, spread y profundidad](https://pythonparatrading.com/curso-python-trading/nivel-1/libro-de-ordenes-bid-ask-y-profundidad/), [1.2.3 · Futuros: especificaciones, margen, roll y contango](https://pythonparatrading.com/curso-python-trading/nivel-1/futuros-especificaciones-margen-y-roll/)

## Al terminar esta lección

- Explicar qué compra y qué vende cada parte de una call y de una put, y dibujar su resultado al vencimiento.
- Separar la prima de cada opción de una cadena en valor intrínseco y valor extrínseco, y clasificarla por su relación con el subyacente (dentro, en o fuera del dinero).
- Leer una cadena de opciones como una escalera de strikes y comprobar con pandas la paridad put-call dentro de la horquilla.
- Distinguir opciones americanas y europeas y reconocer en los datos una put europea que cotiza por debajo de su valor intrínseco.

## Un derecho con fecha de caducidad

Una **opción** es un contrato que da a quien la compra el derecho, pero no la obligación, de comprar o vender un activo
(el **subyacente**) a un precio fijado de antemano (el **strike** o precio de ejercicio) hasta una fecha (el
**vencimiento**). Hay dos tipos:

- Una **call** da el derecho a **comprar** el subyacente al strike. Le interesa a quien espera que suba.
- Una **put** da el derecho a **vender** el subyacente al strike. Le interesa a quien espera que baje o quiere
  protegerse de una caída.

Por ese derecho, el comprador paga una **prima** al vendedor en el momento de la compra. El vendedor (también llamado
emisor o *writer*) cobra la prima y asume la obligación contraria: si el comprador ejerce, tiene que vender (en la call)
o comprar (en la put) al strike. La asimetría es la clave de todo lo que sigue: el comprador arriesga como mucho la
prima; el vendedor cobra poco y seguro a cambio de un riesgo que puede ser grande.

```mermaid
flowchart TB
  C[Comprador] -- prima --> V[Vendedor]
  C --> X{¿Acaba dentro?}
  X -- sí --> E[Ejerce]
  X -- no --> N[Expira sin valor]
  E --> L[Vendedor paga]
```

Al vencimiento, el comprador ejerce solo si le conviene: una call si el subyacente está por encima del strike, una put
si está por debajo. La **liquidación** puede ser física (se entregan las acciones o el futuro subyacente) o **en
efectivo** (se paga la diferencia entre el precio de liquidación y el strike). Las opciones sobre índices, como las
de esta lección, se liquidan en efectivo: no se puede entregar un índice.

Cada contrato tiene un **multiplicador**: cuántas unidades de dinero vale un punto de prima. En las opciones de la
lección es de 100 USD por punto, como en las opciones SPX de Cboe sobre el S&P 500[^1]: una prima de 174,05 puntos
cuesta 17.405 USD por contrato. Olvidar el multiplicador es el error más barato de cometer en un notebook y el más
caro en una cuenta real.

[^1]: Especificaciones de las opciones SPX en la página de Cboe enlazada en los recursos: multiplicador de 100 USD,
estilo europeo y liquidación en efectivo.

## La cadena de FIX

Los datos son una foto de la **cadena de opciones** de un índice ficticio, FIX, al cierre del 2 de junio de 2025:
todas las calls y puts cotizadas, para cuatro vencimientos y decenas de strikes, con su mejor precio de compra (bid) y
de venta (ask), el volumen del día y el **interés abierto** (contratos vivos). Son opciones europeas con liquidación en
efectivo. El índice cerró ese día en 6.359,10 (`fix_indice_diario.csv`, el mismo índice de los futuros de la lección
1.2.3).

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

cad = pd.read_csv("opciones_cadena_fix.csv",
                  parse_dates=["fecha", "vencimiento"])
indice = pd.read_csv("fix_indice_diario.csv", parse_dates=["fecha"])
S = indice.set_index("fecha").loc["2025-06-02", "indice"]
print(f"{len(cad)} opciones; FIX al cierre: {S}")
cad.groupby(["vencimiento", "tipo"]).agg(
    strikes=("strike", "size"), desde=("strike", "min"),
    hasta=("strike", "max"), interes=("interes_abierto", "sum"))
```
```output
584 opciones; FIX al cierre: 6359.1
                  strikes  desde  hasta  interes
vencimiento tipo
2025-06-20  call       50   5675   6900   412880
            put        50   5675   6900   621931
2025-07-18  call       82   5275   7300   574545
            put        82   5275   7300   863427
2025-09-19  call       66   4700   7950   414879
            put        66   4700   7950   622741
2025-12-19  call       94   4150   8800   497606
            put        94   4150   8800   746209
```

Cuatro vencimientos, el tercer viernes de junio, julio, septiembre y diciembre, y en cada uno el mismo número de calls
y de puts: cada strike tiene su pareja. Cuanto más largo es el plazo, más amplio es el abanico de strikes, porque el
índice puede alejarse más. El interés abierto de las puts es mayor que el de las calls: en un índice de acciones, las
puts son el seguro de las carteras, y hay más demanda de seguro que de apuestas al alza.

Un listado así es poco legible. La forma habitual de mirar una cadena es la que usan las plataformas de los brokers:
una fila por strike, las calls a la izquierda y las puts a la derecha.

```python
cad["medio"] = (cad["bid"] + cad["ask"]) / 2
jul = cad[cad["vencimiento"] == "2025-07-18"]
tabla = jul.pivot(index="strike", columns="tipo",
                  values=["bid", "ask"])
tabla.columns = [f"{t}_{c}" for c, t in tabla.columns]
tabla = tabla[["call_bid", "call_ask", "put_bid", "put_ask"]]
tabla.loc[6200:6500:2]
```
```output
        call_bid  call_ask  put_bid  put_ask
strike
6200       274.0     275.2     92.1     92.6
6250       238.4     239.5    106.1    106.7
6300       204.9     205.8    122.3    122.9
6350       173.6     174.5    140.7    141.4
6400       144.9     145.6    161.5    162.3
6450       118.8     119.4    185.1    185.9
6500        95.5      96.0    211.4    212.4
```

La figura de la cabecera dibuja la misma cadena como una **escalera de strikes**: cada peldaño es un strike, con el
bid y el ask de su call a la izquierda y los de su put a la derecha, y la línea ámbar marca dónde está el índice. Las
zonas sombreadas son las opciones **dentro del dinero**: las calls con strike por debajo del índice (arriba a la
izquierda) y las puts con strike por encima (abajo a la derecha). Al bajar por la escalera, hacia strikes más altos,
las calls se abaratan y las puts se encarecen. Cada peldaño de 50 puntos cambia el precio medio de la call en menos de
50 puntos: unos 41 entre 6.050 y 6.100, unos 29 entre 6.350 y 6.400 y unos 15 entre 6.600 y 6.650. Esa sensibilidad
de la prima al strike se relaciona con la probabilidad de acabar dentro del dinero (nivel 3).

## Lo que paga cada posición al vencimiento

Al vencimiento, una opción ya no tiene incertidumbre: vale lo que da ejercerla. Con $S_T$ el subyacente al vencimiento
y $K$ el strike:

$$
\text{call: } \max(S_T - K,\ 0) \qquad \text{put: } \max(K - S_T,\ 0)
$$

Ese es el **payoff**. El resultado de la posición (P&L) resta lo pagado por la prima, o suma lo cobrado si se ha
vendido. Con las cuatro combinaciones —call o put, comprada o vendida— salen las cuatro posiciones básicas, y todas
las estrategias con opciones (diferenciales, *straddles*, cóndores) son sumas de ellas. Se calculan con las opciones
del dinero de julio, strike 6.350, compradas o vendidas al precio medio:

```python
def pnl_vencimiento(s_t, strike, prima, tipo, lado=1):
    """P&L por unidad de subyacente; lado 1 compra, -1 venta."""
    s_t = np.asarray(s_t, dtype=float)
    if tipo == "call":
        payoff = np.maximum(s_t - strike, 0)
    else:
        payoff = np.maximum(strike - s_t, 0)
    return lado * (payoff - prima)

K = 6350
prima = jul[jul["strike"] == K].set_index("tipo")["medio"]
print(prima.to_dict())
escenarios = [6000, 6200, 6350, 6500, 6700]
pd.DataFrame({
    "call comprada": pnl_vencimiento(escenarios, K,
                                     prima["call"], "call"),
    "call vendida": pnl_vencimiento(escenarios, K,
                                    prima["call"], "call", -1),
    "put comprada": pnl_vencimiento(escenarios, K,
                                    prima["put"], "put"),
    "put vendida": pnl_vencimiento(escenarios, K,
                                   prima["put"], "put", -1),
}, index=pd.Index(escenarios, name="FIX al vencimiento"))
```
```output
{'call': 174.05, 'put': 141.05}
                    call comprada  call vendida  put comprada  put vendida
FIX al vencimiento
6000                      -174.05        174.05        208.95      -208.95
6200                      -174.05        174.05          8.95        -8.95
6350                      -174.05        174.05       -141.05       141.05
6500                       -24.05         24.05       -141.05       141.05
6700                       175.95       -175.95       -141.05       141.05
```

*Fig. — Resultado al vencimiento de las cuatro posiciones básicas con las opciones de strike 6.350 de julio, al precio medio del 2 de junio de 2025 (línea continua, comprada; discontinua, vendida).* Dos paneles. Izquierda, call de strike 6.350 con prima 174,05: la call comprada pierde la prima hasta 6.350 y gana a partir del punto muerto 6.524,05, destacado; la vendida es su imagen especular. Derecha, put de strike 6.350 con prima 141,05: la put comprada gana por debajo del punto muerto 6.208,95 y pierde la prima por encima de 6.350; la vendida, al revés.

Cada columna es la imagen especular de su vecina: lo que gana el comprador lo pierde el vendedor, punto por punto.
Conviene reconocer las cuatro formas a simple vista:

| Posición | Visión | Ganancia máxima | Pérdida máxima | Punto muerto |
|---|---|---|---|---|
| Call comprada | Alcista | Ilimitada | La prima | $K + \text{prima}$ |
| Call vendida | No alcista | La prima | Ilimitada | $K + \text{prima}$ |
| Put comprada | Bajista | $K - \text{prima}$ | La prima | $K - \text{prima}$ |
| Put vendida | No bajista | La prima | $K - \text{prima}$ | $K - \text{prima}$ |

```python
mult = 100  # USD por punto de prima
print(f"Punto muerto de la call: {K + prima['call']:.2f}")
print(f"Punto muerto de la put:  {K - prima['put']:.2f}")
print(f"Una call cuesta {prima['call'] * mult:,.0f} USD")
subida = (K + prima["call"]) / S - 1
print(f"La call gana si FIX sube más de un {subida:.2%}")
```
```output
Punto muerto de la call: 6524.05
Punto muerto de la put:  6208.95
Una call cuesta 17,405 USD
La call gana si FIX sube más de un 2.59%
```

Comprar la call del dinero solo da beneficio si el índice sube más de un 2,59 % en las seis semanas que quedan
hasta el vencimiento. Esa es la otra cara de la pérdida limitada: la prima hay que recuperarla antes de ganar nada. El
vendedor de la call gana mientras el índice no pase de 6.524,05: en la mayoría de los escenarios gana poco, como mucho
la prima; en unos pocos pierde mucho más de lo que podía ganar.

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

Vender opciones sin cubrir (sin tener el subyacente o una opción que limite la pérdida) da beneficios pequeños y
frecuentes y pérdidas grandes y raras. Un backtest corto suele mostrar solo los primeros. Los brokers exigen márgenes
altos para estas posiciones y, en una caída brusca, pueden cerrarlas a cualquier precio. La pérdida de una call
vendida no tiene techo.

</aside>

## Valor intrínseco y valor extrínseco

Antes del vencimiento, la prima de una opción es mayor que su payoff inmediato. Se divide en dos partes:

- **Valor intrínseco**: lo que daría ejercerla ahora, $\max(S - K, 0)$ en una call y $\max(K - S, 0)$ en una put. Nunca
  es negativo.
- **Valor extrínseco** o **valor temporal**: el resto, prima menos valor intrínseco. Es lo que se paga por la
  posibilidad de que el subyacente se mueva a favor antes del vencimiento.

La relación entre strike y subyacente se llama **moneyness** y da tres categorías:

| Categoría | Call | Put | Valor intrínseco |
|---|---|---|---|
| Dentro del dinero (ITM) | $K < S$ | $K > S$ | Positivo |
| En el dinero (ATM) | $K \approx S$ | $K \approx S$ | Casi cero |
| Fuera del dinero (OTM) | $K > S$ | $K < S$ | Cero |

```python
def moneyness(tipo, strike, s, banda=0.005):
    """ITM, ATM (a menos de un 0,5 % del índice) u OTM."""
    dist = (s - strike) / s if tipo == "call" else (strike - s) / s
    if abs(dist) < banda:
        return "ATM"
    return "ITM" if dist > 0 else "OTM"

es_call = cad["tipo"] == "call"
cad["intrinseco"] = np.where(es_call, S - cad["strike"],
                             cad["strike"] - S).clip(min=0)
cad["extrinseco"] = cad["medio"] - cad["intrinseco"]
cad["moneyness"] = [moneyness(t, k, S) for t, k in
                    zip(cad["tipo"], cad["strike"])]
cols = ["tipo", "strike", "medio", "intrinseco", "extrinseco",
        "moneyness"]
jul = cad[cad["vencimiento"] == "2025-07-18"]
jul[jul["strike"].isin([6000, 6350, 6700])][cols].round(2)
```
```output
     tipo  strike   medio  intrinseco  extrinseco moneyness
158  call    6000  433.75       359.1       74.65       ITM
159   put    6000   52.65         0.0       52.65       OTM
186  call    6350  174.05         9.1      164.95       ATM
187   put    6350  141.05         0.0      141.05       ATM
214  call    6700   31.15         0.0       31.15       OTM
215   put    6700  346.20       340.9        5.30       ITM
```

Las seis filas resumen la idea. La call de 6.000 está dentro del dinero: de su prima de 433,75 puntos, 359,10 son valor
intrínseco y 74,65, valor temporal. La de 6.700 está fuera: toda su prima es valor temporal. Las dos del strike
6.350 están en el dinero, con un intrínseco de 9,10 puntos en la call y cero en la put, y son las que más valor
temporal tienen de las seis.

*Fig. — Prima de las calls de FIX con vencimiento en julio frente a su valor intrínseco, por strike, al cierre del 2 de junio de 2025. La distancia entre las dos es el valor extrínseco.* Línea de la prima de las calls, de 5.700 a 7.100, sobre la zona del valor intrínseco, que baja en recta desde 659,10 en el strike 5.700 hasta cero en el índice, 6.359,10. Lejos del índice, la línea se pega a la zona o a cero; cerca de él se separa más: en el strike 6.350, destacado, la prima es 174,05 y el valor extrínseco, 164,95.

La figura lo extiende a todas las calls de julio. La zona gris es el valor intrínseco, la recta que sale del strike
igual al índice; la línea, la prima. Lo que queda entre las dos es el valor extrínseco, y tiene forma de campana
centrada en el índice. Muy dentro del dinero la call se comporta casi como el propio índice; muy fuera, casi no vale
nada; cerca del dinero, el resultado final es más incierto, y la incertidumbre es lo que se paga.

```python
idx = cad.groupby(["vencimiento", "tipo"])["extrinseco"].idxmax()
maximos = cad.loc[idx].set_index(["vencimiento", "tipo"])
maximos[["strike", "extrinseco"]].round(2)
```
```output
                  strike  extrinseco
vencimiento tipo
2025-06-20  call    6350       94.40
            put     6350       85.05
2025-07-18  call    6350      164.95
            put     6350      141.05
2025-09-19  call    6350      280.35
            put     6350      223.95
2025-12-19  call    6350      414.10
            put     6350      311.30
```

En los cuatro vencimientos y en los dos tipos, el máximo cae en el strike 6.350, el más próximo al índice. Las calls
y las puts del mismo strike no tienen el mismo valor extrínseco: en julio, 164,95 puntos la call y 141,05 la put. La
diferencia viene del forward, que está por encima del índice (sección de la paridad), pero la forma de campana es la
misma en las dos.

## El valor temporal se va acelerando

El valor extrínseco depende del plazo. Más tiempo es más margen para que el subyacente se mueva, y por tanto más
valor. Pero la relación no es lineal: con un modelo de precios con movimientos aleatorios independientes, la
dispersión del subyacente al vencimiento crece con la raíz cuadrada del plazo (lección 0.7.1), y el valor temporal de
una opción del dinero, aproximadamente también.

Para medirlo sin la distorsión del forward, se toma la media del valor extrínseco de la call y de la put del strike
6.350: la call tiene más valor extrínseco que la put porque el forward está por encima del índice (la call ya está
dentro del dinero respecto al forward), y la media de las dos compensa ese efecto.

```python
del_dinero = cad[cad["strike"] == 6350]
atm = del_dinero.pivot(index="vencimiento", columns="tipo",
                       values="extrinseco")
atm["medio"] = (atm["call"] + atm["put"]) / 2
atm["dias"] = (atm.index - pd.Timestamp("2025-06-02")).days
atm["por_raiz_dia"] = atm["medio"] / np.sqrt(atm["dias"])
atm.round(2)
```
```output
tipo           call     put   medio  dias  por_raiz_dia
vencimiento
2025-06-20    94.40   85.05   89.72    18         21.15
2025-07-18   164.95  141.05  153.00    46         22.56
2025-09-19   280.35  223.95  252.15   109         24.15
2025-12-19   414.10  311.30  362.70   200         25.65
```

Si el valor temporal fuera proporcional al plazo, la última columna se multiplicaría por 3,3 del primer vencimiento al
último ($\sqrt{200/18}$); en cambio, pasa de 21 a 26 puntos por raíz de día. Que suba algo con el plazo se debe a que
la volatilidad implícita de esta cadena crece con el vencimiento, algo que se estudia en el nivel 3. Con una sola
constante ajustada a los cuatro puntos, la curva $V = a\sqrt{\text{dias}}$ permite ver cómo se gasta el valor temporal
de una opción del dinero de 200 días si nada más cambia:

```python
a = (atm["medio"] * np.sqrt(atm["dias"])).sum() / atm["dias"].sum()
print(f"a = {a:.2f} puntos por raíz de día")
inicial = a * np.sqrt(200)
for desde, hasta in [(200, 170), (90, 60), (60, 30), (30, 0)]:
    perdida = a * (np.sqrt(desde) - np.sqrt(hasta))
    print(f"de {desde:>3} a {hasta:>3} días: pierde {perdida:6.1f}"
          f" puntos ({perdida / inicial:.0%} del valor inicial)")
```
```output
a = 24.61 puntos por raíz de día
de 200 a 170 días: pierde   27.2 puntos (8% del valor inicial)
de  90 a  60 días: pierde   42.8 puntos (12% del valor inicial)
de  60 a  30 días: pierde   55.8 puntos (16% del valor inicial)
de  30 a   0 días: pierde  134.8 puntos (39% del valor inicial)
```

*Fig. — Valor temporal de las opciones del strike 6.350 de FIX (media de call y put) en los cuatro vencimientos de la cadena del 2 de junio de 2025, con la curva a·√días ajustada a los cuatro puntos.* Cuatro puntos con el valor temporal según los días al vencimiento, con el eje de días de 200 a 0 para que el tiempo avance hacia la derecha: 362,70 a 200 días, 252,15 a 109, 153,00 a 46 y 89,72 a 18. La curva de raíz cuadrada que los une cae despacio al principio y deprisa al final; destacado, el último mes, en el que se pierde el 39 % del valor inicial.

Con la curva ajustada a la cadena, una opción del dinero de 200 días pierde en su primer mes 27 puntos, un 8 % de su
valor temporal; en el último mes pierde los 135 puntos que le quedan, un 39 % del valor inicial. Esa erosión diaria del valor temporal tiene nombre, **theta**,
y forma parte de las «griegas», las sensibilidades de la prima al subyacente, a la volatilidad, al tiempo y al tipo de
interés. Las griegas y la volatilidad implícita son materia del nivel 3; aquí basta la intuición: el comprador de una
opción paga el paso del tiempo y el vendedor lo cobra.

## La paridad put-call

Una call comprada y una put vendida del mismo strike y vencimiento dan, al vencimiento, $S_T - K$ en todos los
escenarios: es lo mismo que un futuro comprado a $K$. Si dos carteras pagan lo mismo en el futuro, hoy tienen que
costar lo mismo, y de ahí sale la **paridad put-call** de las opciones europeas:

$$
C - P = e^{-rT}\,(F - K), \qquad F = S\,e^{(r - q)T}
$$

con $r$ el tipo de interés, $q$ el rendimiento por dividendo del índice (los dos en tasa continua) y $F$ el forward,
el precio teórico de un futuro con el mismo vencimiento (lección 1.2.3). Para la fecha de los datos, $r$ = 4,354 % y
$q$ = 1,350 % (README de los datos).

En una cadena real hay que comprobarla con precios ejecutables. Comprar la call y vender la put cuesta
$C_{ask} - P_{bid}$; vender la call y comprar la put ingresa $C_{bid} - P_{ask}$. Si el valor teórico cae entre los
dos, no hay arbitraje posible después de pagar las horquillas:

```python
r, q = 0.04354, 0.01350
ancho = cad.pivot_table(index=["vencimiento", "strike"],
                        columns="tipo", values=["bid", "ask"])
ancho.columns = [f"{t}_{c}" for c, t in ancho.columns]
venc = ancho.index.get_level_values("vencimiento")
k = ancho.index.get_level_values("strike")
T = (venc - pd.Timestamp("2025-06-02")).days / 365
F = S * np.exp((r - q) * T)
ancho["teorico"] = np.exp(-r * T) * (F - k)
ancho["minimo"] = ancho["call_bid"] - ancho["put_ask"]
ancho["maximo"] = ancho["call_ask"] - ancho["put_bid"]
dentro = ancho["teorico"].between(ancho["minimo"], ancho["maximo"])
print(f"Strikes que cumplen la paridad: {dentro.sum()} de "
      f"{len(ancho)}")
ancho.loc[("2025-07-18", 6350),
          ["minimo", "teorico", "maximo"]].round(2)
```
```output
Strikes que cumplen la paridad: 292 de 292
minimo     32.20
teorico    33.04
maximo     33.80
Name: (2025-07-18 00:00:00, 6350), dtype: float64
```

Los 292 pares cumplen la paridad dentro de la horquilla. En el strike del dinero de julio, el valor teórico de
$C - P$ es de 33,04 puntos y el intervalo ejecutable, de 32,20 a 33,80, mide 1,6. La paridad también funciona al revés: con los
precios medios de la call y de la put se puede **deducir el forward** que descuenta el mercado, sin necesidad de un
futuro. Es una forma habitual de estimar el dividendo implícito o de detectar datos defectuosos:

```python
ancho["medio_cp"] = ((ancho["call_bid"] + ancho["call_ask"])
                     - (ancho["put_bid"] + ancho["put_ask"])) / 2
ancho["F_implicito"] = k + ancho["medio_cp"] * np.exp(r * T)
resumen = ancho.groupby(level="vencimiento")["F_implicito"].median()
pd.DataFrame({"F implícito": resumen,
              "F teórico": S * np.exp((r - q) *
                  (resumen.index - pd.Timestamp("2025-06-02"))
                  .days.values / 365)}).round(2)
```
```output
             F implícito  F teórico
vencimiento
2025-06-20       6368.52    6368.53
2025-07-18       6383.22    6383.22
2025-09-19       6416.42    6416.40
2025-12-19       6464.65    6464.64
```

El forward implícito coincide con el teórico a menos de 0,02 puntos en los cuatro vencimientos, y está por encima del
índice porque el tipo de interés supera al rendimiento por dividendo: el mismo contango de los futuros de FIX.

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

Si al comprobar la paridad en datos reales muchos strikes la incumplen, lo primero que hay que sospechar son los
datos, no un arbitraje: precios de la call y de la put tomados en momentos distintos, un último precio en lugar del
bid y el ask, un vencimiento mal asignado o un dividendo que no se ha tenido en cuenta. En opciones americanas sobre
acciones la paridad es solo una desigualdad, porque el ejercicio anticipado tiene valor.

</aside>

## Americanas y europeas

La diferencia es cuándo se puede ejercer:

- Una opción **europea** solo se ejerce al vencimiento. Son europeas, por ejemplo, las opciones SPX sobre el S&P 500,
  las de esta lección y muchas opciones sobre índices.
- Una opción **americana** se puede ejercer cualquier día hasta el vencimiento. Lo son, por regla general, las opciones
  sobre acciones individuales y sobre ETFs cotizadas en EE. UU., que al ejercerse se liquidan entregando las
  acciones[^2].

[^2]: Cboe, en la página de especificaciones de las SPX: las opciones sobre índices (europeas) solo se ejercen al
vencimiento; las opciones sobre acciones y ETFs (americanas) pueden ejercerse en cualquier momento antes del
vencimiento. En su comparativa, las opciones sobre ETFs se liquidan con entrega de las acciones.

Poder ejercer antes nunca resta valor, así que una americana vale al menos lo que la europea equivalente. Y, sobre
todo, una americana **nunca puede valer menos que su valor intrínseco**: si costara menos, bastaría con comprarla y
ejercerla en el acto. Una europea sí puede, y la cadena de FIX lo muestra:

```python
bajo = cad[(cad["tipo"] == "put") & (cad["extrinseco"] < 0)]
print(f"Puts con prima menor que el intrínseco: {len(bajo)}")
print(bajo.groupby("vencimiento")["strike"].min())
peores = bajo.nsmallest(3, "extrinseco").set_index("vencimiento")
peores[["strike", "medio", "intrinseco", "extrinseco"]].round(2)
```
```output
Puts con prima menor que el intrínseco: 93
vencimiento
2025-06-20    6625
2025-07-18    6750
2025-09-19    6900
2025-12-19    7050
Name: strike, dtype: int64
             strike    medio  intrinseco  extrinseco
vencimiento
2025-12-19     8800  2280.35      2440.9     -160.55
2025-12-19     8750  2231.55      2390.9     -159.35
2025-12-19     8700  2182.75      2340.9     -158.15
```

Las 93 puts afectadas están todas muy dentro del dinero: desde el strike 6.625 en junio, un 4 % por encima del índice,
y desde el 7.050 en diciembre, un 11 % por encima. En los vencimientos largos hace falta estar más dentro del dinero
porque queda más valor temporal que compensar. La razón del fenómeno es el tipo de interés. Una put muy dentro del dinero casi seguro se ejercerá, y lo que
paga entonces es $K - S_T$: el strike se cobra al vencimiento, no hoy. Descontado con un tipo del 4,35 %, ese cobro
futuro vale menos que su importe nominal. La put de strike 8.800 de diciembre vale unos 160 puntos menos que si se
pudiera ejercer hoy.

Con una put americana, ese descuento es una razón para ejercer antes: cobrar el strike hoy y colocarlo al tipo de
interés vale más que esperar. Por eso el **ejercicio anticipado** tiene sentido sobre todo en dos casos:

```mermaid
flowchart TB
  A[Opción americana] --> T{¿Tipo?}
  T -- put --> P{¿Muy dentro?}
  P -- sí --> PI[Ejercer ya]
  P -- no --> NO[Esperar]
  T -- call --> D{¿Dividendo antes?}
  D -- sí --> CD[Ejercer la víspera]
  D -- no --> NO
```

- **Put muy dentro del dinero**: los intereses del strike cobrado hoy superan el valor temporal que queda.
- **Call justo antes de un dividendo**: el poseedor de la call no cobra dividendos. Si el dividendo es mayor que el
  valor temporal, compensa ejercer el día antes de la fecha *ex* para tener las acciones y cobrarlo (lección 1.2.1).
  Sin dividendos, ejercer una call americana antes de tiempo nunca compensa: venderla rinde más que ejercerla.

Para un sistema que vende opciones americanas, esto es un riesgo operativo: la contraparte puede ejercer contra la
posición en cualquier momento (la **asignación**), y el vendedor se encuentra con acciones compradas o vendidas que no
esperaba. Para un backtest, significa que una opción americana no puede valorarse con la fórmula de una europea.

## Lo que hay que vigilar en los datos de opciones

Una cadena tiene cientos de contratos por subyacente y día, y la mayoría apenas negocian. La liquidez se concentra en
unos pocos:

```python
jul = cad[cad["vencimiento"] == "2025-07-18"].copy()
jul["redondo"] = np.where(jul["strike"] % 100 == 0,
                          "múltiplo de 100", "resto")
jul["horquilla_pct"] = 100 * (jul["ask"] - jul["bid"]) / jul["medio"]
print(jul.groupby("redondo")["interes_abierto"].mean().round(0))
jul[jul["tipo"] == "call"].set_index("strike").loc[
    [6000, 6400, 6800, 7000, 7200],
    ["bid", "ask", "horquilla_pct"]].round(2)
```
```output
redondo
múltiplo de 100    17177.0
resto               5873.0
Name: interes_abierto, dtype: float64
           bid     ask  horquilla_pct
strike
6000    432.80  434.70           0.44
6400    144.90  145.60           0.48
6800     14.40   14.70           2.06
7000      1.75    1.90           8.22
7200      0.00    0.15         200.00
```

Los strikes múltiplos de 100 acumulan unas tres veces más interés abierto que los intermedios: es donde se concentra
la negociación. Y la horquilla, medida en porcentaje de la prima, se dispara lejos del dinero: en la call de 7.200 el
bid es cero y el ask, 0,15. En una opción así el «precio medio» no significa nada, y un backtest que compre y venda al
medio subestima los costes por completo.

Los errores más comunes al trabajar con datos de opciones:

- **Usar el último precio.** Una opción poco negociada puede tener su última operación de hace días, con el
  subyacente en otro sitio. Para valorar, bid y ask del mismo instante.
- **Mezclar horas.** El índice al cierre y las opciones a las 15:45 no son simultáneos. En la paridad, un minuto de
  diferencia con el subyacente moviéndose rompe la igualdad.
- **Olvidar el multiplicador o el estilo.** 100 USD por punto en la mayoría de opciones de EE. UU., otros valores en
  otros mercados; europea o americana; efectivo o entrega física. Todo está en la especificación del contrato.
- **Sesgo de supervivencia de contratos.** Las cadenas históricas solo tienen los strikes que existieron; los que se
  añadieron tras un movimiento fuerte no estaban antes. Y los contratos vencidos desaparecen de muchas APIs gratuitas.

Para cadenas reales, yfinance da la foto actual de la cadena de un subyacente de EE. UU., sin histórico (lección
1.3.2). No se ejecuta aquí porque necesita red:

```python skip
import yfinance as yf

spy = yf.Ticker("SPY")
print(spy.options[:4])             # vencimientos disponibles
cadena = spy.option_chain(spy.options[0])
calls, puts = cadena.calls, cadena.puts
calls[["strike", "bid", "ask", "lastPrice", "volume",
       "openInterest", "impliedVolatility", "inTheMoney"]]
```

`option_chain` devuelve dos tablas, calls y puts, con una fila por strike: precio, volumen, interés abierto y una
volatilidad implícita calculada por Yahoo. Las opciones de SPY son americanas y sobre un ETF que paga dividendos, así
que ni la paridad exacta ni la comprobación de puts por debajo del intrínseco se aplican tal cual.

## Ejercicios

1. Un **straddle** comprado es una call y una put compradas del mismo strike y vencimiento. Calcula, con los precios
   medios del strike 6.350 de julio, la prima total y los dos puntos muertos. ¿Cuánto tiene que moverse el índice, en
   porcentaje, para que la posición gane?

**Solución.**

```python
coste = prima["call"] + prima["put"]
arriba, abajo = K + coste, K - coste
print(f"Prima total: {coste:.2f} puntos "
      f"({coste * mult:,.0f} USD)")
print(f"Puntos muertos: {abajo:.2f} y {arriba:.2f}")
print(f"Movimiento necesario: {arriba / S - 1:+.2%} "
      f"o {abajo / S - 1:+.2%}")
```
```output
Prima total: 315.10 puntos (31,510 USD)
Puntos muertos: 6034.90 y 6665.10
Movimiento necesario: +4.81% o -5.10%
```

El straddle paga si el índice se mueve mucho en cualquier dirección, y pierde la prima entera si acaba justo en el
strike. Hace falta que el índice suba más de un 4,81 % o baje más de un 5,10 % en seis semanas. Es una apuesta a
que la volatilidad realizada será mayor que la que el mercado ha puesto en las primas.

2. Usa la paridad put-call para deducir, en cada vencimiento, qué rendimiento por dividendo $q$ descuenta la cadena
   (supón que $r$ = 4,354 % es conocido). Pista: con el forward implícito, $q = r - \ln(F/S)/T$.

**Solución.**

```python
dias = (resumen.index - pd.Timestamp("2025-06-02")).days.values
t = dias / 365
q_impl = r - np.log(resumen.values / S) / t
pd.Series(100 * q_impl, index=resumen.index,
          name="q implícito (%)").round(3)
```
```output
vencimiento
2025-06-20    1.353
2025-07-18    1.350
2025-09-19    1.349
2025-12-19    1.350
Name: q implícito (%), dtype: float64
```

Los cuatro vencimientos dan el 1,35 % con el que se generaron los datos, con diferencias de milésimas que salen del
redondeo de las primas al tick (0,05 o 0,10 puntos) y que pesan más cuando $T$ es pequeño, como en junio. Con datos reales, el dividendo implícito varía por vencimiento porque los dividendos no se
reparten uniformemente a lo largo del año.

3. Un compañero calcula el valor extrínseco de las opciones de una cadena con el último precio negociado y encuentra
   varias calls fuera del dinero con valor extrínseco negativo. ¿Qué explicaciones darías antes de pensar en un
   arbitraje?

**Solución.**

Una call fuera del dinero tiene valor intrínseco cero, así que un extrínseco negativo significa un precio negativo,
lo que es imposible: el error está en los datos o en el cálculo. Las causas habituales: el último precio es de una
operación antigua (o de otro contrato con el mismo símbolo tras un ajuste), el subyacente usado para calcular el
intrínseco no es del mismo instante, el strike está ajustado por un evento corporativo, o se ha mezclado call y put.
Con bid y ask simultáneos del mismo instante que el subyacente, la comprobación se repite y el problema suele
desaparecer.

## Autoevaluación

1. El índice está en 6.359,10. Una call de strike 6.300 cuesta 205,35 puntos. ¿Cuánto de esa prima es valor extrínseco?

   - A. 205,35 puntos: toda la prima
   - B. 59,10 puntos
   - C. 146,25 puntos
   - D. Cero, porque está dentro del dinero

   *Respuesta C: 146,25 puntos.* El valor intrínseco de la call es lo que daría ejercerla ahora: 6.359,10 − 6.300 = 59,10. El resto de la prima, 205,35 − 59,10 = 146,25 puntos, es valor extrínseco: lo que el mercado paga por la posibilidad de que el índice suba más antes del vencimiento.

2. ¿Qué posición tiene pérdida máxima ilimitada al vencimiento?

   - A. Call comprada
   - B. Put comprada
   - C. Call vendida
   - D. Put vendida

   *Respuesta C: Call vendida.* Quien vende una call se obliga a pagar `S − K` si el subyacente acaba por encima del strike, y el subyacente no tiene techo. La put vendida también puede perder mucho, pero como máximo `K` menos la prima, porque el precio no baja de cero.

3. ¿Dónde es mayor el valor extrínseco de las opciones de un mismo vencimiento?

   - A. En las más dentro del dinero
   - B. En las más fuera del dinero
   - C. Es igual en todos los strikes
   - D. Cerca del dinero, con el strike próximo al subyacente

   *Respuesta D: Cerca del dinero, con el strike próximo al subyacente.* Lejos del strike, el resultado está casi decidido: muy dentro del dinero la opción se comporta como el subyacente y muy fuera casi no vale nada. La incertidumbre sobre si acabará dentro o fuera, que es lo que se paga como valor extrínseco, es máxima cuando el strike está cerca del precio actual.

4. En la cadena de FIX, varias puts europeas muy dentro del dinero cotizan por debajo de su valor intrínseco. ¿Por qué no hay arbitraje?

   - A. Porque los datos están mal
   - B. Porque una opción europea solo se ejerce al vencimiento: el strike se cobra más tarde y hay que descontarlo con el tipo de interés
   - C. Porque las puts no tienen valor intrínseco
   - D. Porque el multiplicador es 100

   *Respuesta B: Porque una opción europea solo se ejerce al vencimiento: el strike se cobra más tarde y hay que descontarlo con el tipo de interés.* El valor de una put europea muy dentro del dinero se acerca a `K·e^(−rT) − S·e^(−qT)`, no a `K − S`. Con tipos del 4,35 %, cobrar el strike dentro de unos meses vale menos que cobrarlo hoy. Una put americana sí podría ejercerse ya, y por eso nunca vale menos que su valor intrínseco.

5. Para comprobar la paridad put-call en una cadena real, ¿qué precios hay que usar?

   - A. Los de compra y venta: `C_bid − P_ask` y `C_ask − P_bid` acotan lo que se puede hacer de verdad
   - B. El último precio negociado de la call y de la put
   - C. Solo el precio medio de la call
   - D. El precio de cierre del índice

   *Respuesta A: Los de compra y venta: `C_bid − P_ask` y `C_ask − P_bid` acotan lo que se puede hacer de verdad.* El último precio puede tener horas de antigüedad y no ser simultáneo en la call y en la put. Lo ejecutable son el bid y el ask: comprar la call y vender la put cuesta `C_ask − P_bid`; lo contrario ingresa `C_bid − P_ask`. Si el valor teórico cae entre los dos, no hay arbitraje después de horquillas.

## Ideas clave

- Una call da el derecho a comprar y una put el derecho a vender, a un precio fijado (strike) y hasta una fecha. El comprador paga la prima; el vendedor la cobra y asume la obligación.
- La prima se divide en valor intrínseco (lo que daría ejercer ahora) y valor extrínseco (lo que vale esperar). El extrínseco es máximo cerca del dinero y crece con el plazo.
- El valor temporal no se pierde a ritmo constante: crece más o menos con la raíz cuadrada del plazo, así que el último mes es el que más se lleva.
- En una cadena europea, `C − P = e^(−rT)(F − K)`: la paridad put-call liga calls y puts del mismo strike y sirve para validar los datos y para deducir el forward.
- Una opción americana se puede ejercer cualquier día y nunca vale menos que su valor intrínseco; una europea, solo al vencimiento, y puede valer menos.
- Los datos de opciones engañan con facilidad: último precio antiguo, horquillas anchas lejos del dinero, multiplicador y estilo de ejercicio distintos según el contrato.

## Recursos

### Research

- [Usos de la Volatilidad y Volatilidad Actual - VIX1D](https://pythonparatrading.com/usos-de-la-volatilidad/) · Research-0003 · 6 min

### Documentación

- [Cboe: especificaciones de las opciones SPX (europeas, liquidación en efectivo)](https://www.cboe.com/tradable_products/sp_500/spx_options/specifications/) · cboe.com

### Libros

- [John C. Hull, Options, Futures, and Other Derivatives (Pearson, 11.ª ed., 2021)](https://www.pearson.com/en-us/subject-catalog/p/options-futures-and-other-derivatives/P200000005938) · pearson.com

### Datos

- [Datos del nivel 1: cadena de opciones sobre FIX del 2 de junio de 2025 (CSV)](https://pythonparatrading.com/curso/datos/nivel-1/opciones_cadena_fix.csv) · Descarga · opciones_cadena_fix.csv

Lección anterior: [1.2.4 · Forex: pares, pips, lotes, rollover y CFD](https://pythonparatrading.com/curso-python-trading/nivel-1/forex-pares-pips-lotes-y-rollover/)

Lección siguiente: [1.2.6 · Cripto: spot, perpetuos, funding y custodia](https://pythonparatrading.com/curso-python-trading/nivel-1/cripto-spot-perpetuos-y-funding/)
