Lección 1.2.5 · 60 min

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.

Fig. — La cadena de opciones de FIX con vencimiento el 18 de julio de 2025 como escalera de strikes: bid y ask de cada call y de cada put al cierre del 2 de junio. Sombreadas, las opciones dentro del dinero
Lecciones del nivel 1
  1. 1.1 · Cómo funcionan los mercados

    1. 1.1.1 Participantes y centros de negociación
    2. 1.1.2 Sesiones, subastas, festivos y calendarios
    3. 1.1.3 Libro de órdenes: bid, ask, spread y profundidad
    4. 1.1.4 Tipos de órdenes
    5. 1.1.5 Costes, liquidación, apalancamiento y margen
  2. 1.2 · Clases de activos

    1. 1.2.1 Acciones: splits, dividendos y eventos corporativos
    2. 1.2.2 ETFs: réplica, tracking error, apalancados y UCITS
    3. 1.2.3 Futuros: especificaciones, margen, roll y contango
    4. 1.2.4 Forex: pares, pips, lotes, rollover y CFD
    5. 1.2.5 Opciones: call, put, valor intrínseco y valor temporal
    6. 1.2.6 Cripto: spot, perpetuos, funding y custodia
    7. 1.2.7 Renta fija y tipos de interés; CFDs y productos apalancados
  3. 1.3 · Fuentes de datos de mercado

    1. 1.3.1 Tipos de datos de mercado: EOD, barras, ticks, libro y referencia
    2. 1.3.2 Fuentes de datos gratuitas
    3. 1.3.3 APIs de datos retail y prosumer
    4. 1.3.4 Proveedores de datos profesionales
    5. 1.3.5 Datos de cripto y on-chain
    6. 1.3.6 Brókeres como fuente de datos
    7. 1.3.7 Licencias y términos de uso de datos
    8. 1.3.8 Cómo elegir proveedor de datos
  4. 1.4 · Ingeniería de datos financieros

    1. 1.4.1 Descarga por REST y websockets: paginación, límites y reintentos
    2. 1.4.2 Limpieza de datos: faltantes, ticks erróneos, huecos y zonas horarias
    3. 1.4.3 Ajustes por splits y dividendos: precios ajustados y sin ajustar
    4. 1.4.4 Universos sin sesgo de supervivencia: deslistados, fusiones y cambios de símbolo
    5. 1.4.5 Construcción de barras: tiempo, ticks, volumen, dólar y desequilibrio
    6. 1.4.6 Series continuas de futuros: reglas de roll, ajuste por diferencia y ajuste por ratio
    7. 1.4.7 Almacenamiento: CSV, Parquet, particionado, DuckDB, TimescaleDB y ArcticDB
    8. 1.4.8 Pipeline reproducible: descarga, validación, actualización incremental y tests de calidad
  5. 1.5 · Datos fundamentales y macro

    1. 1.5.1 Estados financieros, ratios, XBRL y SEC EDGAR
    2. 1.5.2 Datos macro, calendarios económicos, estimaciones y transcripciones
  6. 1.6 · Análisis exploratorio financiero

    1. 1.6.1 Rentabilidades, volatilidad, correlaciones móviles y drawdown
    2. 1.6.2 Hechos estilizados: colas gruesas, agrupamiento, autocorrelación y apalancamiento
    3. 1.6.3 Estacionalidad: día de la semana, mes, cambio de mes y sesiones intradía
  7. 1.7 · Análisis técnico programado

    1. 1.7.1 Indicadores técnicos en Python
    2. 1.7.2 Implementación propia frente a TA-Lib: validar resultados
    3. 1.7.3 Patrones de velas y soportes y resistencias
    4. 1.7.4 Multi-timeframe sin anticipación

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.

primasínoCompradorVendedor¿Acaba dentro?EjerceExpira sin valorVendedor paga
Fuente 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 5001Nota 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.: 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.

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

IN [01]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"))
OUT [01]La cadena de opciones de FIX
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.

IN [02]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]
OUT [02]Vencimiento de julio, en formato de cadena
        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 STS_T el subyacente al vencimiento y KK el strike:

call: max⁡(ST−K, 0)put: max⁡(K−ST, 0)\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:

IN [03]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"))
OUT [03]P&L al vencimiento de las cuatro posiciones básicas
{'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)

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ónVisiónGanancia máximaPérdida máximaPunto muerto
Call compradaAlcistaIlimitadaLa primaK+primaK + \text{prima}
Call vendidaNo alcistaLa primaIlimitadaK+primaK + \text{prima}
Put compradaBajistaK−primaK - \text{prima}La primaK−primaK - \text{prima}
Put vendidaNo bajistaLa primaK−primaK - \text{prima}K−primaK - \text{prima}
IN [04]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%}")
OUT [04]Puntos muertos y tamaño en dólares
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.

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)\max(S - K, 0) en una call y max⁡(K−S,0)\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íaCallPutValor intrínseco
Dentro del dinero (ITM)K<SK < SK>SK > SPositivo
En el dinero (ATM)K≈SK \approx SK≈SK \approx SCasi cero
Fuera del dinero (OTM)K>SK > SK<SK < SCero
IN [05]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)
OUT [05]Intrínseco, extrínseco y moneyness
     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

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.

IN [06]python
idx = cad.groupby(["vencimiento", "tipo"])["extrinseco"].idxmax()
maximos = cad.loc[idx].set_index(["vencimiento", "tipo"])
maximos[["strike", "extrinseco"]].round(2)
OUT [06]Dónde es máximo el valor extrínseco
                  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.

IN [07]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)
OUT [07]Valor temporal en el dinero por vencimiento
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 (200/18\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=adiasV = 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:

IN [08]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)")
OUT [08]Cómo se gasta el valor temporal
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

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, ST−KS_T - K en todos los escenarios: es lo mismo que un futuro comprado a KK. 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),F=S e(r−q)TC - P = e^{-rT}\,(F - K), \qquad F = S\,e^{(r - q)T}

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

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

IN [09]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)
OUT [09]Paridad put-call dentro de la horquilla
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−PC - 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:

IN [10]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)
OUT [10]El forward implícito en la cadena
             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.

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

IN [11]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)
OUT [11]Puts europeas por debajo de su valor intrínseco
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−STK - 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:

putsínocallsínoOpción americana¿Tipo?¿Muy dentro?Ejercer yaEsperar¿Dividendo antes?Ejercer la víspera
Fuente 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:

IN [12]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)
OUT [12]Dónde está la liquidez
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:

IN [13]python
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
IN [14]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%}")
OUT [14]Straddle en el dinero de julio
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.

  1. Usa la paridad put-call para deducir, en cada vencimiento, qué rendimiento por dividendo qq descuenta la cadena (supón que rr = 4,354 % es conocido). Pista: con el forward implícito, q=r−ln⁡(F/S)/Tq = r - \ln(F/S)/T.
Solución
IN [15]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)
OUT [15]Dividendo implícito
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 TT 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.

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

Footnotes

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

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

Respuesta plegada en cada pregunta

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?

    • A205,35 puntos: toda la prima
    • B59,10 puntos
    • C146,25 puntos
    • DCero, porque está dentro del dinero
    Ver respuesta

    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?

    • ACall comprada
    • BPut comprada
    • CCall vendida
    • DPut vendida
    Ver respuesta

    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?

    • AEn las más dentro del dinero
    • BEn las más fuera del dinero
    • CEs igual en todos los strikes
    • DCerca del dinero, con el strike próximo al subyacente
    Ver respuesta

    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?

    • APorque los datos están mal
    • BPorque 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
    • CPorque las puts no tienen valor intrínseco
    • DPorque el multiplicador es 100
    Ver respuesta

    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?

    • ALos de compra y venta: C_bid − P_ask y C_ask − P_bid acotan lo que se puede hacer de verdad
    • BEl último precio negociado de la call y de la put
    • CSolo el precio medio de la call
    • DEl precio de cierre del índice
    Ver respuesta

    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