Lección 3.5.1 · 75 min
Estructuras direccionales y verticales: call, put, covered call, collar y spreads
Una estructura de opciones es una suma de patas, y todo lo que importa de ella sale de esa suma: lo que cuesta abrirla, lo que puede ganar o perder, dónde están sus puntos muertos y cómo responde al precio, al tiempo y a la volatilidad. Esta lección construye las estructuras direccionales y las verticales con la cadena sintética del índice ORX y las sigue durante 143 vencimientos.
- Módulo
- 3.5 · Estructuras de opciones en Python
- Duración
- 75 min
Lecciones del nivel 3
3.1 · Futuros en profundidad
3.2 · Spreads de futuros
- 3.2.1 Spreads de calendario, butterflies y condors
- 3.2.2 Spreads intercommodity: crack, spark y crush
- 3.2.3 Spreads de tipos y de índices: 2s10s, NOB, NQ/ES y Europa frente a EE. UU.
- 3.2.4 Ratios de cobertura: por nominal, por DV01 y por volatilidad
- 3.2.5 Datos y backtesting de spreads: cotizados, sintéticos y por patas
- 3.2.6 Estacionalidad de spreads: análisis multi-año, patrones y trampas
3.3 · Forex avanzado
3.4 · Teoría y valoración de opciones
- 3.4.1 Payoffs, paridad put-call y límites de arbitraje
- 3.4.2 Árboles binomiales, Black-Scholes-Merton, Black-76 y Monte Carlo
- 3.4.3 Griegas: delta, gamma, vega, theta, rho, vanna, volga y charm
- 3.4.4 Volatilidad implícita: Newton-Raphson, Brent, py_vollib y QuantLib
- 3.4.5 Sonrisa, skew y estructura temporal; superficie de volatilidad con SVI
- 3.4.6 Volatilidad realizada frente a implícita; prima de riesgo de volatilidad; VIX y VSTOXX
- 3.4.7 Modelos avanzados: Heston, SABR y volatilidad local
3.5 · Estructuras de opciones en Python
- 3.5.1 Estructuras direccionales y verticales: call, put, covered call, collar y spreads
- 3.5.2 Estructuras de volatilidad y rango: straddles, strangles, cóndores y mariposas
- 3.5.3 Calendarios, diagonales, ratios, backspreads, risk reversals y jade lizard
- 3.5.4 Herramienta propia: payoff, griegas agregadas y escenarios
- 3.5.5 Gestión: ajustes, roll, cierre anticipado, asignación temprana y pin risk
3.6 · Estrategias sistemáticas de volatilidad y opciones
3.7 · Cripto derivados y estrategias específicas
Una estructura es una suma de patas
Una call comprada es una apuesta direccional con la pérdida limitada a la prima. Casi todo lo demás que se hace con opciones son combinaciones: una call comprada y otra vendida de strike mayor, una acción con una call vendida encima, una put comprada para poner un suelo. En el módulo 3.4 se valoró cada opción por separado; este módulo las junta. La idea que hace manejable cualquier estructura es la linealidad: el payoff, el valor antes del vencimiento y cada griega de una estructura son la suma de los de sus patas, cada una con su signo (comprada o vendida) y su cantidad.
Las estructuras de esta lección se agrupan por lo que necesitan que pase:
Fuente Mermaid
flowchart LR V[Visión] --> A[Alcista] V --> B[Bajista] V --> C[Ya tengo el índice] A --> A1[Call comprada] A --> A2[Bull call o put] B --> B1[Put comprada] B --> B2[Bear put o call] C --> C1[Covered call] C --> C2[Protective put] C --> C3[Collar]
- Direccionales simples: una call o una put compradas. Riesgo limitado a la prima, ganancia sin tope (la put, hasta que el índice llega a cero).
- Sobre el subyacente: el índice (en la práctica, un ETF o un futuro que lo replica) con una opción encima. La covered call vende una call y cambia la subida por encima del strike por una prima; la protective put compra una put y paga por un suelo; el collar hace las dos cosas y usa la prima de la call para pagar la put.
- Verticales: dos opciones del mismo tipo y vencimiento con strikes distintos, una comprada y otra vendida. Acotan la ganancia y la pérdida. Según qué pata sea más cara, se abren con débito (se paga) o con crédito (se cobra).
El resto del módulo sigue la misma plantilla con estructuras de volatilidad (3.5.2) y de varios vencimientos (3.5.3); la lección 3.5.4 reúne estas funciones en una herramienta y la 3.5.5 trata la gestión de las posiciones abiertas.
La cadena del 31 de diciembre de 2025
Los datos son la cadena diaria del índice ficticio ORX (opciones3_cadena.parquet), que imita a las opciones SPX:
europeas, liquidación en efectivo, multiplicador de 100 USD por punto (el mismo que el de las SPX según la ficha de
Cboe), tres vencimientos mensuales listados cada día. Son datos sintéticos con una superficie de volatilidad conocida y
una prima de riesgo de volatilidad plantada (la implícita cotiza de media por encima de la volatilidad que se realiza
después); nada de lo que se mida aquí es evidencia de que una estructura funcione en el mercado real.
Antes de valorar nada conviene fijar las convenciones, porque cada librería y cada bróker usan las suyas:
| Magnitud | Convención de la lección |
|---|---|
| Precio de la opción | En puntos de índice por unidad; por contrato, × 100 USD |
| Plazo T | Días naturales hasta el vencimiento / 365 (las opciones vencen al cierre) |
| Tipo r | Continuo, en tanto por uno, de la curva interpolada en T (tipo_libre de opciones3_verdad) |
| Dividendo q | Rendimiento continuo, implícito en el forward: q = r − ln(F/S)/T |
| Volatilidad | Anual, en tanto por uno (0,1258 = 12,58 %) |
| Delta | Puntos de opción por punto de índice; por contrato, × 100 = USD por punto |
| Gamma | Cambio de delta por punto de índice |
| Vega | Puntos de opción por punto de volatilidad ( de 0,1258 a 0,1358) |
| Theta | Puntos de opción por día natural |
import numpy as np
import pandas as pd
from scipy.stats import norm
cadena = pd.read_parquet("opciones3_cadena.parquet")
indice = pd.read_csv("opciones3_indice.csv", parse_dates=["fecha"],
index_col="fecha")
verdad = pd.read_parquet("opciones3_verdad.parquet")
HOY = pd.Timestamp("2025-12-31")
VTO = pd.Timestamp("2026-02-20")
S0 = indice.loc[HOY, "cierre"]
def mercado(vto, fecha=HOY):
"""Tipo r y dividendo q continuos (tanto por uno) de un
vencimiento: r de la curva; q implícito en el forward."""
v = verdad[(verdad.fecha == fecha)
& (verdad.vencimiento == vto)].iloc[0]
T = v.dias / 365 # días naturales / 365
S = indice.loc[fecha, "cierre"]
return v.tipo_libre, v.tipo_libre - np.log(v.forward / S) / T
r, q = mercado(VTO)
dias = (VTO - HOY).days
print(f"ORX {S0} días {dias} r {r:.4f} q {q:.4f}")
print("q publicada:", indice.loc[HOY, "rentabilidad_dividendo"] / 100)ORX 6089.45 días 51 r 0.0368 q 0.0117
q publicada: 0.011732El índice cierra en 6.089,45 y el vencimiento de febrero queda a 51 días naturales. El dividendo implícito en el
forward (0,0117) coincide con la rentabilidad por dividendo publicada en opciones3_indice.csv (1,1732 % anual): el
forward de la verdad se construyó con ella, así que las dos vías dan lo mismo. En una cadena real no existe esa
columna de verdad y q (o directamente el forward) se saca de la paridad put-call de los medios (lección 3.4.1).
La valoración es la de Black-Scholes-Merton con dividendo continuo de la lección 3.4.2, con las griegas analíticas de la 3.4.3, escritas para que acepten un vector de precios del índice (lo que hace falta para dibujar un payoff) y para que, con plazo cero, devuelvan el valor al vencimiento:
def bsm(S, K, T, sig, tipo, r, q):
"""Precio (puntos), delta, gamma (por punto), vega (por
punto de volatilidad) y theta (por día natural).
S puede ser un array; con T = 0 devuelve el payoff."""
S = np.asarray(S, dtype=float)
if T <= 0:
pago = np.maximum(S - K, 0) if tipo == "C" else \
np.maximum(K - S, 0)
signo = 1.0 if tipo == "C" else -1.0
delta = np.where(signo * (S - K) > 0, signo, 0.0)
cero = np.zeros_like(S)
return dict(precio=pago, delta=delta, gamma=cero,
vega=cero, theta=cero)
raiz = sig * np.sqrt(T)
d1 = (np.log(S / K) + (r - q + sig**2 / 2) * T) / raiz
d2 = d1 - raiz
dq, dr = np.exp(-q * T), np.exp(-r * T)
gamma = dq * norm.pdf(d1) / (S * raiz)
vega = S * dq * norm.pdf(d1) * np.sqrt(T)
decay = -S * dq * norm.pdf(d1) * sig / (2 * np.sqrt(T))
if tipo == "C":
precio = S * dq * norm.cdf(d1) - K * dr * norm.cdf(d2)
delta = dq * norm.cdf(d1)
theta = (decay - r * K * dr * norm.cdf(d2)
+ q * S * dq * norm.cdf(d1))
else:
precio = K * dr * norm.cdf(-d2) - S * dq * norm.cdf(-d1)
delta = -dq * norm.cdf(-d1)
theta = (decay + r * K * dr * norm.cdf(-d2)
- q * S * dq * norm.cdf(-d1))
return dict(precio=precio, delta=delta, gamma=gamma,
vega=vega / 100, theta=theta / 365)
fila = cadena[(cadena.fecha == HOY) & (cadena.vencimiento == VTO)
& (cadena.tipo == "C") & (cadena.strike == 6100)]
fila = fila.iloc[0]
g = bsm(S0, 6100, dias / 365, fila.iv_modelo, "C", r, q)
print(f"bid {fila.bid} ask {fila.ask} iv {fila.iv_modelo}")
{k: round(float(x), 4) for k, x in g.items()}bid 118.8 ask 119.8 iv 0.1258
{'precio': 119.3813, 'delta': 0.5235, 'gamma': 0.0014, 'vega': 9.0491, 'theta': -1.3226}La call 6.100 cotiza a 118,8-119,8 y BSM con su volatilidad implícita da 119,38, dentro de la horquilla. La columna
iv_modelo de los datos es la implícita verdadera, sin ruido; en una cadena real se calcula invirtiendo el medio
(lección 3.4.4) y la diferencia es pequeña frente a la horquilla. Las griegas, con las unidades de la tabla: delta
0,5235 (52 USD por punto y contrato), vega 9,05 puntos por punto de volatilidad (905 USD por contrato) y theta −1,32
puntos por día natural (132 USD diarios por contrato). La comprobación con QuantLib, con curvas planas al mismo r y q y
el mismo calendario Actual/365, coincide en las cuatro cifras decimales; vega() de QuantLib es por unidad de
volatilidad (hay que dividir entre 100) y thetaPerDay() divide la theta anual entre 365:
import QuantLib as ql
hoy = ql.Date(31, 12, 2025)
ql.Settings.instance().evaluationDate = hoy
dc = ql.Actual365Fixed()
proceso = ql.BlackScholesMertonProcess(
ql.QuoteHandle(ql.SimpleQuote(S0)),
ql.YieldTermStructureHandle(ql.FlatForward(hoy, q, dc)),
ql.YieldTermStructureHandle(ql.FlatForward(hoy, r, dc)),
ql.BlackVolTermStructureHandle(
ql.BlackConstantVol(hoy, ql.TARGET(), fila.iv_modelo, dc)))
opcion = ql.EuropeanOption(
ql.PlainVanillaPayoff(ql.Option.Call, 6100),
ql.EuropeanExercise(ql.Date(20, 2, 2026)))
opcion.setPricingEngine(ql.AnalyticEuropeanEngine(proceso))
print(f"precio {opcion.NPV():.4f} delta {opcion.delta():.4f}"
f" gamma {opcion.gamma():.4f}")
print(f"vega/100 {opcion.vega() / 100:.4f}"
f" theta/día {opcion.thetaPerDay():.4f}")precio 119.3813 delta 0.5235 gamma 0.0014
vega/100 9.0491 theta/día -1.3226Patas, apertura y valoración
Una pata es un diccionario con el tipo, el strike, la cantidad (positiva comprada, negativa vendida), el bid y el ask
del día, la volatilidad implícita, el vencimiento y su r y su q. El índice se representa como una pata más, de tipo
"S", con delta 1 y sin opcionalidad. Con eso bastan tres funciones:
apertura: lo que cuesta abrir la estructura, al medio y cruzando la horquilla (cada compra al ask, cada venta al bid). Esta segunda cifra es la que cuenta: es la que pagaría una orden que se ejecuta ya. Un precio positivo es un débito; uno negativo, un crédito.valor: el valor de la estructura (o cualquiera de sus griegas) si el índice valieraSen una fecha. Para fechas anteriores al vencimiento supone que la volatilidad implícita de cada pata no cambia (sticky strike); qué pasa cuando sí cambia se ve en la 3.5.3 y, con escenarios de precio × volatilidad × tiempo, en la 3.5.4.resumen: el P&L al vencimiento sobre una rejilla de 1 a 3 veces el índice, con el máximo, el mínimo y los puntos muertos (los cruces por cero, interpolados). Si la pendiente al final de la rejilla no es cero, el máximo o el mínimo son ilimitados.
def pata(tipo, K, n, vto=VTO, fecha=HOY):
"""Una pata: n > 0 comprada, n < 0 vendida. tipo "S" es
el propio índice (una cartera que lo replica)."""
if tipo == "S":
return dict(tipo="S", K=0.0, n=n, bid=S0, ask=S0,
iv=0.0, vto=vto, r=0.0, q=0.0)
o = cadena[(cadena.fecha == fecha)
& (cadena.vencimiento == vto)
& (cadena.tipo == tipo)
& (cadena.strike == K)].iloc[0]
rr, qq = mercado(vto, fecha)
return dict(tipo=tipo, K=K, n=n, bid=o.bid, ask=o.ask,
iv=o.iv_modelo, vto=vto, r=rr, q=qq)
def apertura(patas):
"""Coste en puntos al medio y al cruzar la horquilla:
las compradas al ask, las vendidas al bid (> 0 = débito)."""
medio = sum(p["n"] * (p["bid"] + p["ask"]) / 2 for p in patas)
real = sum(p["n"] * (p["ask"] if p["n"] > 0 else p["bid"])
for p in patas)
return medio, real
def valor(patas, S, fecha, griega="precio"):
"""Valor (o griega) de la estructura si el índice vale S
en `fecha`, con la IV de cada pata congelada."""
S = np.asarray(S, dtype=float)
total = np.zeros_like(S)
for p in patas:
if p["tipo"] == "S":
x = {"precio": S, "delta": np.ones_like(S)}
total += p["n"] * x.get(griega, np.zeros_like(S))
continue
T = (p["vto"] - fecha).days / 365
g = bsm(S, p["K"], T, p["iv"], p["tipo"], p["r"], p["q"])
total += p["n"] * g[griega]
return totalREJILLA = np.arange(1.0, 3 * S0, 1.0) # de 1 punto a 3 veces S0
def resumen(patas):
"""Coste, máximo, mínimo y puntos muertos al vencimiento
(el primero de la estructura), en puntos por unidad."""
medio, real = apertura(patas)
fin = min(p["vto"] for p in patas)
pnl = valor(patas, REJILLA, fin) - real
i = np.nonzero(np.diff(np.sign(pnl)))[0]
muertos = REJILLA[i] - pnl[i] / (pnl[i + 1] - pnl[i])
muertos = np.unique(np.round(muertos, 1))
final = pnl[-1] - pnl[-2] # pendiente hacia S grande
return {"medio": round(float(medio), 2),
"real": round(float(real), 2),
"horquilla": round(float(real - medio), 2),
"maximo": "ilimitado" if final > 1e-9
else round(float(pnl.max()), 2),
"minimo": "ilimitado" if final < -1e-9
else round(float(pnl.min()), 2),
"muertos": [round(float(x), 1) for x in muertos]}
def griegas(patas, S=S0, fecha=HOY):
"""Griegas agregadas por unidad (× 100 USD por contrato)."""
g = {k: float(valor(patas, S, fecha, k))
for k in ["delta", "gamma", "vega", "theta"]}
return {"delta": round(g["delta"], 3),
"gamma": round(g["gamma"], 5),
"vega": round(g["vega"], 2),
"theta": round(g["theta"], 2)}
call = [pata("C", 6100, 1)]
put = [pata("P", 6100, 1)]
for nombre, e in [("call 6100", call), ("put 6100", put)]:
print(nombre, resumen(e))
print(" ", griegas(e))call 6100 {'medio': 119.3, 'real': 119.8, 'horquilla': 0.5, 'maximo': 'ilimitado', 'minimo': -119.8, 'muertos': [6219.8]}
{'delta': 0.523, 'gamma': 0.00139, 'vega': 9.05, 'theta': -1.32}
put 6100 {'medio': 108.8, 'real': 109.3, 'horquilla': 0.5, 'maximo': 5989.7, 'minimo': -109.3, 'muertos': [5990.7]}
{'delta': -0.475, 'gamma': 0.00139, 'vega': 9.05, 'theta': -0.91}La call comprada cuesta 119,8 al ask (medio punto más que al medio) y esa es su pérdida máxima; su punto muerto es el strike más lo pagado, 6.219,8, un 2,1 % por encima del índice. La put cuesta 109,3 y su punto muerto está en 5.990,7; su ganancia máxima no es ilimitada sino el strike menos la prima si el índice fuera a cero (la rejilla empieza en 1 punto, de ahí el 5.989,7). Las dos tienen la misma gamma y la misma vega (es la paridad: call − put es lineal en S) y deltas que se separan exactamente en : 0,523 − (−0,475) = 0,998. La theta de la put (−0,91) es menor en valor absoluto que la de la call (−1,32) porque con r > q el término de financiación juega a su favor.
El P&L antes del vencimiento
El payoff al vencimiento es una línea quebrada; antes, la estructura vale el payoff más el valor temporal, y la curva es suave. La figura de la cabecera muestra las tres curvas del bull call spread de la sección siguiente; con la call sola se ve en una tabla:
coste = apertura(call)[1]
S = np.array([5700.0, 5900, 6100, 6300, 6500])
antes = pd.DataFrame({
"hoy": valor(call, S, HOY) - coste,
"en 25 días": valor(call, S, HOY + pd.Timedelta(days=25))
- coste,
"vencimiento": valor(call, S, VTO) - coste}, index=S)
antes.index.name = "ORX"
antes.round(1) hoy en 25 días vencimiento
ORX
5700.0 -108.9 -118.0 -119.8
5900.0 -75.0 -101.0 -119.8
6100.0 5.2 -32.7 -119.8
6300.0 138.5 107.7 80.2
6500.0 311.0 292.8 280.2Con el índice en 6.100 la call ganaría 5,2 puntos hoy (está a 10 puntos de S0 y su delta es 0,52), perdería 32,7 si se llega a mediados de enero en el mismo nivel y perdería toda la prima al vencimiento. Esa diferencia es la theta acumulada: en 25 días se pierden 38 puntos a precio constante, algo más de lo que dice 25 × 1,32 porque la theta de una opción en el dinero crece a medida que se acerca el vencimiento (lección 1.2.5). En 6.300 la call gana 138,5 hoy y 80,2 al vencimiento: subir rápido vale más que subir tarde.
Covered call, protective put y collar
Con el índice en cartera hay tres estructuras clásicas. Los strikes se eligen por delta (la convención de los operadores: una call de «25 delta», 25D en las tablas), con una función que añade a la cadena la delta BSM de cada fila. Con una separación de 100 puntos entre strikes, la delta que se obtiene es la más cercana a la buscada, no la exacta:
def con_delta(fecha=HOY, vto=VTO):
"""La cadena de un vencimiento con la delta BSM de cada fila."""
d = cadena[(cadena.fecha == fecha)
& (cadena.vencimiento == vto)].copy()
rr, qq = mercado(vto, fecha)
S, T = indice.loc[fecha, "cierre"], (vto - fecha).days / 365
for t in ("C", "P"):
m = d.tipo == t
d.loc[m, "delta"] = bsm(S, d.strike[m].to_numpy(), T,
d.iv_modelo[m].to_numpy(), t,
rr, qq)["delta"]
return d
def strike_delta(d, tipo, objetivo):
x = d[d.tipo == tipo]
return float(x.strike.iloc[(x.delta - objetivo).abs().argmin()])
hoy = con_delta()
for t, obj in [("C", 0.25), ("P", -0.25), ("P", -0.10)]:
k = strike_delta(hoy, t, obj)
fila = hoy[(hoy.tipo == t) & (hoy.strike == k)].iloc[0]
print(t, obj, "->", k, f"delta {fila.delta:.3f}",
f"bid {fila.bid} ask {fila.ask}")C 0.25 -> 6300.0 delta 0.214 bid 27.1 ask 27.7
P -0.25 -> 5900.0 delta -0.261 bid 56.5 ask 57.3
P -0.1 -> 5600.0 delta -0.105 bid 22.5 ask 22.9La call de 25D es la 6.300 (delta 0,214, a un 3,5 % del índice) y la put de 25D es la 5.900 (−0,261, a un 3,1 %). Las dos alas no están a la misma distancia aunque tengan la misma delta: la sonrisa del índice tiene skew (la volatilidad de la put 5.900 es mayor que la de la call 6.300), y la deriva r − q mueve el forward hacia arriba.
cubierta = [pata("S", 0, 1), pata("C", 6300, -1)]
protegida = [pata("S", 0, 1), pata("P", 5900, 1)]
collar = [pata("S", 0, 1), pata("P", 5900, 1), pata("C", 6300, -1)]
for nombre, e in [("covered call", cubierta),
("protective put", protegida), ("collar", collar)]:
res = resumen(e)
res["real"] = round(float(res["real"] - S0), 2) # sin S0
res["medio"] = round(float(res["medio"] - S0), 2)
print(nombre, res)
print(" ", griegas(e))covered call {'medio': -27.4, 'real': -27.1, 'horquilla': 0.3, 'maximo': 237.65, 'minimo': -6061.35, 'muertos': [6062.3]}
{'delta': 0.786, 'gamma': -0.00127, 'vega': -6.63, 'theta': 0.74}
protective put {'medio': 56.9, 'real': 57.3, 'horquilla': 0.4, 'maximo': 'ilimitado', 'minimo': -246.75, 'muertos': [6146.8]}
{'delta': 0.739, 'gamma': 0.00093, 'vega': 7.39, 'theta': -1.0}
collar {'medio': 29.5, 'real': 30.2, 'horquilla': 0.7, 'maximo': 180.35, 'minimo': -219.65, 'muertos': [6119.6]}
{'delta': 0.525, 'gamma': -0.00034, 'vega': 0.76, 'theta': -0.26}- Covered call 6.300. Se cobran 27,1 puntos (al bid). La ganancia queda topada en 237,65 (los 210,55 puntos hasta el strike más la prima); por debajo, se pierde lo mismo que con el índice menos 27,1. El punto muerto baja de 6.089,45 a 6.062,3, un 0,4 %. Sus griegas lo dicen todo: delta 0,786 (menos que el índice solo), gamma y vega negativas y theta positiva (+0,74 puntos al día). Es una posición corta en volatilidad.
- Protective put 5.900. Se pagan 57,3. Por debajo de 5.900 la pérdida se queda en un suelo de 246,75 puntos (un 4,1 % del índice: los 189,45 hasta el strike más la prima); por encima, se gana como el índice menos 57,3. Es una posición larga en volatilidad: gamma y vega positivas, theta de −1,0.
- Collar 5.900/6.300. Las dos cosas a la vez. Cuesta 30,2 puntos (57,3 − 27,1), pierde como mucho 219,65 y gana como mucho 180,35. La vega casi desaparece (0,76): la put comprada y la call vendida se compensan.
La paridad put-call ordena las tres. Como , el índice más una call vendida es, con el mismo strike, una put vendida más un bono: la covered call es una venta de put con otro nombre. Del mismo modo, el índice más una put comprada es una call comprada más un bono, y el collar es un bull spread más un bono:
Fuente Mermaid
flowchart LR CC[Covered call] --- PV[Put corta + bono] PP[Protective put] --- CCo[Call larga + bono] CO[Collar] --- BS[Vertical + bono]
Un collar de coste cero es el que elige la call para que su bid pague el ask de la put:
puts = hoy[(hoy.tipo == "P") & (hoy.strike == 5900)].iloc[0]
calls = hoy[hoy.tipo == "C"].set_index("strike")
print("ask de la put 5900:", puts.ask)
calls.loc[6200:6600, ["bid", "ask", "delta"]].round(3)ask de la put 5900: 57.3
bid ask delta
strike
6200.0 63.60 64.50 0.372
6300.0 27.10 27.70 0.214
6400.0 9.30 9.70 0.096
6600.0 0.85 0.95 0.013La put 5.900 cuesta 57,3. La call 6.300 solo paga 27,1; la 6.200 paga 63,6. Un collar 5.900/6.200 se abre con un crédito de 6,3 puntos: protege por debajo de un 3,1 % de caída a cambio de renunciar a todo lo que pase de un 1,8 % de subida. El skew es lo que encarece la protección: a la misma distancia, la put cuesta más que la call, y para pagarla hay que vender una call más cercana.
Verticales: débito y crédito
Un vertical alcista se puede montar con calls (comprar la de strike bajo, vender la de strike alto: se paga) o con puts (comprar la de strike bajo, vender la de strike alto: se cobra). Con los mismos strikes, los dos pagan lo mismo al vencimiento salvo una constante: el bull put es el bull call menos el ancho, .
bull_call = [pata("C", 6100, 1), pata("C", 6300, -1)]
bull_put = [pata("P", 6100, 1), pata("P", 6300, -1)]
for nombre, e in [("bull call 6100/6300", bull_call),
("bull put 6100/6300", bull_put)]:
print(nombre, resumen(e))
print(" ", griegas(e))
ancho = 200 * np.exp(-r * dias / 365)
m_call, m_put = apertura(bull_call)[0], apertura(bull_put)[0]
print(f"paridad: débito {m_call:.2f}"
f" ancho descontado − crédito {ancho + m_put:.2f}")bull call 6100/6300 {'medio': 91.9, 'real': 92.7, 'horquilla': 0.8, 'maximo': 107.3, 'minimo': -92.7, 'muertos': [6192.7]}
{'delta': 0.309, 'gamma': 0.00012, 'vega': 2.42, 'theta': -0.58}
bull put 6100/6300 {'medio': -106.9, 'real': -105.7, 'horquilla': 1.2, 'maximo': 105.7, 'minimo': -94.3, 'muertos': [6194.3]}
{'delta': 0.309, 'gamma': 0.00012, 'vega': 2.42, 'theta': -0.6}
paridad: débito 91.90 ancho descontado − crédito 92.08Los dos verticales 6.100/6.300 tienen las mismas griegas (delta 0,309, vega 2,42; la theta difiere en 0,02 por la financiación de la put dentro del dinero) y casi el mismo perfil: el de calls cuesta 92,7 y gana como mucho 107,3; el de puts cobra 105,7, gana como mucho eso y pierde como mucho 94,3. La paridad se cumple al medio: el débito de las calls (91,90) es el ancho descontado menos el crédito de las puts (92,08), con una diferencia de 0,18 puntos, dentro de las horquillas. Que uno «cobre» y el otro «pague» es contabilidad: quien vende el bull put no recibe un regalo, recibe una prima que tiene que devolver con una probabilidad alta. La diferencia real está en la horquilla: el bull put pierde 1,2 puntos al cruzarla y el bull call 0,8, porque la put 6.300 está dentro del dinero y su horquilla es más ancha en puntos.
La figura de la cabecera muestra el bull call spread: al vencimiento, la línea quebrada entre −92,7 y +107,3 con el punto muerto en 6.192,7 (el strike bajo más el débito); hoy, una curva suave y aplanada, porque las dos patas se compensan. Las griegas de un vertical son pequeñas comparadas con las de cada pata: la vega de la estructura es 2,42 frente a 9,05 de la call comprada. Es una posición sobre la dirección, con poco de volatilidad.
Los verticales bajistas son el espejo, y lo habitual en la operativa es el vertical de crédito fuera del dinero: vender una put de 25D y comprar otra de 10D para acotar la pérdida.
bear_put = [pata("P", 6100, 1), pata("P", 5900, -1)]
bear_call = [pata("C", 5900, -1), pata("C", 6100, 1)]
put_credito = [pata("P", 5900, -1), pata("P", 5600, 1)]
for nombre, e in [("bear put 6100/5900", bear_put),
("bear call 5900/6100", bear_call),
("bull put 5900/5600", put_credito)]:
print(nombre, resumen(e))
print(" ", griegas(e))bear put 6100/5900 {'medio': 51.9, 'real': 52.8, 'horquilla': 0.9, 'maximo': 147.2, 'minimo': -52.8, 'muertos': [6047.2]}
{'delta': -0.214, 'gamma': 0.00046, 'vega': 1.66, 'theta': 0.09}
bear call 5900/6100 {'medio': -147.35, 'real': -146.0, 'horquilla': 1.35, 'maximo': 146.0, 'minimo': -54.0, 'muertos': [6046.0]}
{'delta': -0.214, 'gamma': 0.00046, 'vega': 1.66, 'theta': 0.07}
bull put 5900/5600 {'medio': -34.2, 'real': -33.6, 'horquilla': 0.6, 'maximo': 33.6, 'minimo': -266.4, 'muertos': [5866.4]}
{'delta': 0.156, 'gamma': -0.00051, 'vega': -3.25, 'theta': 0.27}El bear put 6.100/5.900 cuesta 52,8 y gana hasta 147,2; el bear call 5.900/6.100 es su gemelo de crédito (cobra 146,0 y pierde como mucho 54,0). El bull put 5.900/5.600 es otro animal: cobra 33,6 y puede perder 266,4, casi ocho veces más. Gana si el índice no cae más de un 3,7 % en 51 días (punto muerto 5.866,4). Sus griegas son las de una venta de volatilidad acotada: gamma y vega negativas (−3,25), theta positiva (+0,27).
Lo que cuesta cruzar la horquilla
Cada pata se abre cruzando su horquilla y, si se cierra antes del vencimiento, se vuelve a cruzar. En el índice, con horquillas del 1-3 % del medio cerca del dinero, una pata cuesta poco; en una estructura de varias patas y prima neta pequeña, el coste relativo se multiplica:
estructuras = {"call 6100": call, "put 6100": put,
"covered call": cubierta, "collar": collar,
"bull call 6100/6300": bull_call,
"bull put 6100/6300": bull_put,
"bull put 5900/5600": put_credito}
filas = []
for nombre, e in estructuras.items():
opciones = [p for p in e if p["tipo"] != "S"]
medio, real = apertura(opciones)
tope = resumen(e)["maximo"]
tope = np.nan if tope == "ilimitado" or tope > 1000 else tope
filas.append({"estructura": nombre, "patas": len(opciones),
"prima_medio": medio, "horquilla": real - medio,
"usd_contrato": 100 * (real - medio),
"pct_prima": 100 * (real - medio) / abs(medio),
"pct_max_ganancia": 100 * (real - medio) / tope})
pd.DataFrame(filas).set_index("estructura").round(2) patas prima_medio horquilla usd_contrato pct_prima pct_max_ganancia
estructura
call 6100 1 119.3 0.5 50.0 0.42 NaN
put 6100 1 108.8 0.5 50.0 0.46 NaN
covered call 1 -27.4 0.3 30.0 1.09 0.13
collar 2 29.5 0.7 70.0 2.37 0.39
bull call 6100/6300 2 91.9 0.8 80.0 0.87 0.75
bull put 6100/6300 2 -106.9 1.2 120.0 1.12 1.14
bull put 5900/5600 2 -34.2 0.6 60.0 1.75 1.79La call en el dinero pierde un 0,42 % de su prima al abrirse; el collar, que paga la diferencia entre dos primas, un 2,4 %; el vertical de crédito fuera del dinero, un 1,75 % de lo que cobra y un 1,79 % de lo que puede ganar. Son cifras del 31 de diciembre de 2025, un día tranquilo. Con estrés las horquillas de los datos se ensanchan (por un factor 1 + 2,5 × estrés en la fórmula del generador) y en las estructuras de cuatro patas de la lección 3.5.2 el coste relativo es mayor. Abrir y cerrar antes del vencimiento lo duplica; una orden de spread al medio (las combinaciones cotizan como un solo instrumento en los mercados reales) recupera parte, sin garantía de ejecución.
Doce años de cada estructura
¿Cómo se comportan estas estructuras si se abren todos los meses? La historia es la más sencilla posible: la sesión siguiente a cada vencimiento mensual se abre la estructura con el vencimiento siguiente (unos 28-35 días), con los strikes elegidos por delta, compras al ask y ventas al bid; se mantiene hasta el vencimiento y se liquida al cierre del índice. El P&L se mide en % del índice el día de la entrada, sin intereses sobre la prima. Las patas de índice usan el de rentabilidad total, con dividendos.
vtos = np.sort(cadena.vencimiento.unique())
sesiones = indice.index
por_dia = dict(tuple(cadena.groupby(["fecha", "vencimiento"])))
entradas = [] # (sesión, vencimiento, cadena)
for ant, vto in zip(vtos[:-1], vtos[1:]):
if vto > sesiones[-1]:
break
f = sesiones[sesiones.searchsorted(ant, side="right")]
if (f, vto) in por_dia:
entradas.append((f, vto, con_delta(f, vto)))
def historia(receta):
"""Abre la estructura la sesión siguiente a cada vencimiento
mensual con el vencimiento siguiente, al bid/ask, y la
liquida al cierre del vencimiento. P&L en % del índice."""
filas = []
for f, vto, d in entradas:
S, ST = indice.loc[f, "cierre"], indice.loc[vto, "cierre"]
crece = (indice.loc[vto, "cierre_rt"]
/ indice.loc[f, "cierre_rt"])
coste = pago = 0.0
for tipo, K, n in receta(d):
if tipo == "S": # índice con dividendos
coste, pago = coste + n * S, pago + n * S * crece
continue
o = d[(d.tipo == tipo) & (d.strike == K)].iloc[0]
coste += n * (o.ask if n > 0 else o.bid)
pago += n * (max(ST - K, 0) if tipo == "C"
else max(K - ST, 0))
filas.append({"entrada": f, "vto": vto,
"pnl": 100 * (pago - coste) / S})
return pd.DataFrame(filas).set_index("entrada")
def atm(d):
return strike_delta(d, "C", 0.50)
recetas = {
"índice": lambda d: [("S", 0, 1)],
"call ATM": lambda d: [("C", atm(d), 1)],
"put ATM": lambda d: [("P", atm(d), 1)],
"covered call 25D": lambda d: [
("S", 0, 1), ("C", strike_delta(d, "C", 0.25), -1)],
"protective put 25D": lambda d: [
("S", 0, 1), ("P", strike_delta(d, "P", -0.25), 1)],
"collar 25D": lambda d: [
("S", 0, 1), ("P", strike_delta(d, "P", -0.25), 1),
("C", strike_delta(d, "C", 0.25), -1)],
"bull call ATM/25D": lambda d: [
("C", atm(d), 1), ("C", strike_delta(d, "C", 0.25), -1)],
"bull put, mismos strikes": lambda d: [
("P", atm(d), 1), ("P", strike_delta(d, "C", 0.25), -1)],
"bull put 25D/10D": lambda d: [
("P", strike_delta(d, "P", -0.25), -1),
("P", strike_delta(d, "P", -0.10), 1)],
}
hist = pd.DataFrame({k: historia(v)["pnl"]
for k, v in recetas.items()})
print(len(hist), "entradas", hist.index[0].date(), "a",
hist.index[-1].date())143 entradas 2014-01-21 a 2025-11-24tabla = pd.DataFrame({
"media": hist.mean(), "mediana": hist.median(),
"pct_pos": 100 * (hist > 0).mean(), "desv": hist.std(),
"peor": hist.min(),
"fecha_peor": hist.idxmin().dt.strftime("%Y-%m-%d"),
"mejor": hist.max()})
tabla.round(2) media mediana pct_pos desv peor fecha_peor mejor
índice 1.05 1.33 63.64 5.91 -28.13 2020-02-24 30.06
call ATM 0.51 -0.44 46.15 3.58 -5.05 2020-05-18 22.43
put ATM -0.40 -1.38 27.27 3.47 -7.60 2020-03-23 26.49
covered call 25D 0.65 1.72 68.53 4.38 -27.41 2020-02-24 13.57
protective put 25D 0.67 0.56 56.64 4.69 -11.46 2020-04-20 26.86
collar 25D 0.27 1.07 62.24 2.84 -10.02 2020-04-20 10.37
bull call ATM/25D 0.11 0.06 50.35 1.42 -3.52 2020-05-18 5.94
bull put, mismos strikes 0.09 0.05 50.35 1.41 -3.58 2020-04-20 5.85
bull put 25D/10D 0.23 0.42 88.11 1.08 -8.50 2020-04-20 1.97Con 143 entradas, y recordando que son datos sintéticos con una prima de volatilidad plantada:
- Comprar opciones pierde de media lo que se paga por la volatilidad. La put ATM pierde un 0,40 % del índice por entrada y solo gana en el 27 % de los meses. La call ATM gana de media un 0,51 % porque el índice sube (un 1,05 % al mes con dividendos), pero su mediana es negativa (−0,44 %): gana poco a menudo y mucho de vez en cuando.
- La covered call cambia la cola derecha por frecuencia. Gana en el 69 % de los meses (el índice, en el 64 %), con una media algo menor que el índice (0,65 % frente a 1,05 %) y una mejor entrada de +13,6 % frente a +30,1 %. Su peor entrada, la del 24 de febrero de 2020, pierde un 27,4 %: casi lo mismo que el índice (−28,1 %). Es la paridad en acción: una put vendida no protege de nada.
- La protective put y el collar sí recortan la cola, a −11,5 % y −10,0 %, pero su peor entrada no es la del crash de marzo sino la del 20 de abril de 2020: tras el rebote, con la volatilidad todavía muy alta, la put de 25D quedó lejos del índice y la caída del 19 % hasta el vencimiento de mayo cayó casi entera en la zona sin cubrir.
- El bull call y el bull put con los mismos strikes son la misma posición: medias de 0,11 % y 0,09 %, el mismo porcentaje de meses positivos (50,35 %) y peores entradas de −3,5 % y −3,6 %. La pequeña diferencia de media es la horquilla de la put dentro del dinero.
- El vertical de crédito 25D/10D es la venta de prima con red. Gana en el 88 % de las entradas, 0,23 % de media, y su peor entrada pierde un 8,5 %: casi cuarenta meses de ganancia media en uno. Su mejor entrada no pasa del 1,97 %.
La peor entrada del vertical de crédito enseña algo más que la cola. Con strikes elegidos por delta, el ancho entre las dos puts depende de la volatilidad del día:
for dia in ["2020-02-24", "2020-04-20"]:
f, vto, d = next(e for e in entradas
if e[0] == pd.Timestamp(dia))
k1 = strike_delta(d, "P", -0.25)
k2 = strike_delta(d, "P", -0.10)
x = d[d.tipo == "P"].set_index("strike")
S = indice.loc[f, "cierre"]
iv_atm = d.iv_modelo[d.strike == atm(d)].iloc[0]
credito = x.loc[k1, "bid"] - x.loc[k2, "ask"]
print(f.date(), f"ORX {S:.0f} iv ATM {iv_atm:.3f}",
f"strikes {k1:.0f}/{k2:.0f}",
f"ancho {100 * (k1 - k2) / S:.1f} %",
f"crédito {credito:.2f}",
f"al vto {indice.loc[vto, 'cierre']:.0f}")2020-02-24 ORX 2960 iv ATM 0.147 strikes 2850/2750 ancho 3.4 % crédito 9.60 al vto 2124
2020-04-20 ORX 2667 iv ATM 0.489 strikes 2425/2125 ancho 11.2 % crédito 39.00 al vto 2159El 24 de febrero de 2020, con la volatilidad ATM en 0,147, las puts de 25D y 10D estaban a 100 puntos una de otra (un 3,4 % del índice) y el vertical cobró 9,60. El índice cayó hasta 2.124 y se perdió el máximo: 90,4 puntos, un 3,1 %. El 20 de abril, con la volatilidad en 0,489, las mismas deltas quedaban a 300 puntos (un 11,2 %) y el vertical cobró 39,00; el índice terminó en 2.159, por debajo de las dos, y la pérdida fue de 227 puntos, un 8,5 %. Una pérdida máxima «definida» es tan grande como el ancho que se elige, y un ancho fijado por delta se ensancha justo cuando el mercado es más peligroso. Fijar el ancho en puntos o en % del índice, o dimensionar por la pérdida máxima y no por el número de contratos, son las respuestas habituales; la 3.6.1 trata el dimensionamiento de la venta sistemática de prima por margen y por estrés.
Errores típicos
- Valorar al medio. El backtest que abre al medio gana la horquilla que nunca cobraría. Abrir al ask y al bid es lo mínimo; cerrar antes del vencimiento cuesta otra horquilla.
- Confundir crédito con riesgo bajo. Con los mismos strikes, débito y crédito son la misma posición. Lo que importa es la pérdida máxima y la probabilidad de llegar a ella.
- Creer que la covered call protege. Amortigua con la prima, pero la caída del índice se queda entera.
- Olvidar el multiplicador y las unidades. Una theta de −1,32 es por unidad y día natural: 132 USD por contrato y día, también en sábado y domingo. Una vega de 9,05 es por punto de volatilidad.
- Elegir strikes por delta sin mirar el ancho. La misma delta es otra distancia cuando la volatilidad cambia; el riesgo de un vertical se mide en puntos, no en deltas.
- Ignorar los dividendos y el tipo. El forward de febrero está un 0,35 % por encima del índice; con r y q mal puestos, las deltas y la paridad salen mal (lección 3.4.1).
- Las opciones sobre acciones son americanas. Una call vendida dentro del dinero antes de un dividendo, o una put vendida muy dentro del dinero, pueden asignarse antes del vencimiento (lección 3.5.5); las del ORX son europeas.
Ejercicios
- Construye un bear call spread de crédito fuera del dinero con las calls 6.300 (vendida) y 6.400 (comprada) del vencimiento de febrero. ¿Cuánto cobra, cuánto puede perder, dónde está su punto muerto y qué griegas tiene?
Solución
bear_call_otm = [pata("C", 6300, -1), pata("C", 6400, 1)]
print(resumen(bear_call_otm))
griegas(bear_call_otm){'medio': -17.9, 'real': -17.4, 'horquilla': 0.5, 'maximo': 17.4, 'minimo': -82.6, 'muertos': [6317.4]}
{'delta': -0.118, 'gamma': -0.00047, 'vega': -2.75, 'theta': 0.35}Cobra 17,4 puntos (27,1 de la 6.300 al bid menos 9,7 de la 6.400 al ask; al medio serían 17,9) y puede perder 82,6: el ancho de 100 menos el crédito, 4,7 veces lo que gana. Gana mientras el índice no suba más de un 3,7 % hasta el punto muerto, 6.317,4. Es una posición bajista y vendida en volatilidad: delta −0,118, gamma y vega negativas (−2,75) y theta positiva, +0,35 puntos al día (35 USD por contrato). La relación entre lo que cobra y lo que arriesga es la de cualquier vertical de crédito fuera del dinero: probable y pequeño contra improbable y grande.
- Repite la historia de la covered call con calls de 10D, 25D y 40D. ¿Cómo cambian la media, el porcentaje de meses positivos y la peor entrada?
Solución
cc = {f"cc {int(100 * x)}D": historia(
lambda d, x=x: [("S", 0, 1),
("C", strike_delta(d, "C", x), -1)])["pnl"]
for x in (0.10, 0.25, 0.40)}
cc = pd.DataFrame(cc)
pd.DataFrame({"media": cc.mean(), "pct_pos": 100 * (cc > 0).mean(),
"peor": cc.min(), "mejor": cc.max()}).round(2) media pct_pos peor mejor
cc 10D 0.78 65.03 -27.91 20.83
cc 25D 0.65 68.53 -27.41 13.57
cc 40D 0.51 70.63 -27.41 9.45Cuanto más cerca del dinero se vende la call (40D), más meses positivos (70,6 %) y menos media (0,51 %): se cobra más prima, pero se renuncia antes a la subida, y en un índice que sube eso pesa más. La de 10D se parece al índice solo (media 0,78 %, mejor entrada +20,8 %). La peor entrada apenas cambia con la delta: −27,9 %, −27,4 % y −27,4 %. Ninguna prima de una call cubre una caída del 28 %: el strike de la call vendida decide cuánta subida se cede, no cuánta bajada se evita.
- Un compañero dice que su covered call «no puede perder mucho porque ya cobró la prima» y que la protective put «es dinero tirado porque casi nunca se usa». Con los resultados de la lección, ¿qué le contestarías?
Solución
Que la covered call es, por paridad, una put vendida: su pérdida al bajar el índice es la del índice menos la prima, y la prima de una call de 25D es un 0,4 % del índice. Su peor mes en los datos pierde un 27,4 %, siete décimas menos que el índice. La protective put, en cambio, cuesta de media algo de rentabilidad (es una compra de volatilidad, que tiene una prima en contra) pero recorta la peor entrada a −11,5 %. Ninguna de las dos es «mejor»: una vende cola derecha y cobra por ello, la otra compra protección de la cola izquierda y paga por ella. Lo que no se puede decir es que la covered call proteja. Y la protección de una put de 25D depende de la volatilidad del día: tras el crash de 2020 quedaba tan lejos que la peor entrada llegó con la cobertura puesta.
Respuesta plegada en cada pregunta
Autoevaluación
Un bull call spread 6.100/6.300 se abre pagando 119,8 por la call comprada y cobrando 27,1 por la vendida. ¿Cuál es su pérdida máxima por contrato de multiplicador 100?
- A11.980 USD, la prima de la call comprada
- B9.270 USD, el débito neto
- C20.000 USD, el ancho entre strikes
- DIlimitada, porque hay una call vendida
Ver respuesta
Respuesta B. 9.270 USD, el débito neto
La pérdida máxima de un vertical de débito es lo pagado: 119,8 − 27,1 = 92,7 puntos, 9.270 USD por contrato. La call vendida está cubierta por la comprada de strike menor, así que no hay riesgo ilimitado; la ganancia máxima es el ancho menos el débito, 107,3 puntos.
Con los mismos strikes 6.100 y 6.300, el bull call spread es de débito y el bull put spread de crédito. ¿Qué los diferencia de verdad?
- AEl de crédito es más seguro porque cobra al abrir
- BEl de débito no puede perder más que lo pagado y el de crédito sí
- CCasi nada: por la paridad put-call tienen el mismo payoff salvo el ancho descontado; cambian la horquilla que se paga y la financiación de la prima
- DEl de crédito tiene vega positiva
Ver respuesta
Respuesta C. Casi nada: por la paridad put-call tienen el mismo payoff salvo el ancho descontado; cambian la horquilla que se paga y la financiación de la prima
Bull put = bull call − (K2 − K1), y el ancho descontado (200·e^(−rT)) iguala las primas: al medio, 91,90 frente a 92,08. Griegas y riesgo coinciden. En los datos, el de puts cuesta más horquilla (1,2 frente a 0,8 puntos) porque su put vendida está dentro del dinero.
En la historia de 2014-2025, la peor entrada de la covered call de 25D pierde un 27,4 % y la del índice solo un 28,1 %. ¿Por qué tan parecidas?
- APorque la call vendida se ejerció
- BPorque una covered call es, por paridad, una put vendida: conserva toda la caída del índice y solo la amortigua con la prima cobrada
- CPorque la horquilla de la call es muy ancha en las crisis
- DPor un error en los datos de marzo de 2020
Ver respuesta
Respuesta B. Porque una covered call es, por paridad, una put vendida: conserva toda la caída del índice y solo la amortigua con la prima cobrada
Vender una call limita la subida, no la bajada. La prima de una call de 25D es pequeña (27 puntos en el ejemplo, un 0,4 % del índice), así que en una caída del 28 % apenas se nota. Para limitar la bajada hace falta una put comprada: la protective put y el collar se quedan en −11,5 % y −10,0 %.
El bull put spread 25D/10D abierto el 24 de febrero de 2020 pierde un 3,1 % del índice y el del 20 de abril de 2020, un 8,5 %. ¿Qué explica la diferencia?
- AQue el índice cayó más en abril
- BQue con strikes elegidos por delta el ancho entre ellos crece con la volatilidad: 3,4 % del índice con una IV ATM de 0,147 y 11,2 % con 0,489
- CQue en abril la horquilla era más ancha
- DQue en febrero la put comprada no se pudo ejercer
Ver respuesta
Respuesta B. Que con strikes elegidos por delta el ancho entre ellos crece con la volatilidad: 3,4 % del índice con una IV ATM de 0,147 y 11,2 % con 0,489
La delta depende de la distancia al strike medida en desviaciones típicas del plazo (la volatilidad por la raíz de T). Con la volatilidad tres veces mayor, las puts de 25D y 10D quedan tres veces más separadas, y la pérdida máxima (ancho − crédito) crece con ellas. «Riesgo definido» no quiere decir «riesgo pequeño».
La call 6.100 tiene una theta de −1,32 con las unidades de la lección. ¿Qué significa?
- AQue pierde 1,32 USD al año
- BQue pierde un 1,32 % al día
- CQue, con todo lo demás igual, pierde 1,32 puntos por día natural: 132 USD por contrato
- DQue pierde 1,32 puntos por sesión de negociación
Ver respuesta
Respuesta C. Que, con todo lo demás igual, pierde 1,32 puntos por día natural: 132 USD por contrato
La theta se expresa aquí por día natural (la anual entre 365, como
thetaPerDayde QuantLib con Actual/365) y por unidad de índice. Por contrato se multiplica por 100. Un fin de semana cuenta dos días naturales aunque no haya sesión.
Ideas clave
- Una estructura es una lista de patas; su coste, payoff, P&L y griegas son la suma de los de cada pata con su signo y su cantidad.
- El coste real es el de cruzar la horquilla: compras al ask y ventas al bid. En la cadena del ejemplo va del 0,4 % de la prima en una call en el dinero al 1,8 % en un vertical de crédito fuera del dinero.
- Por paridad put-call, una covered call equivale a una put vendida y una protective put a una call comprada: vender una call no protege de la caída, como mostró su peor mes de la historia, −27,4 % frente a −28,1 % del índice.
- Débito o crédito es contabilidad: con los mismos strikes, el bull call y el bull put tienen el mismo payoff salvo el ancho descontado y las mismas griegas.
- Los verticales de crédito ganan a menudo y pierden de golpe: el 25D/10D es positivo en el 88 % de las entradas y su peor entrada pierde 37 veces su ganancia media; con strikes por delta, la pérdida máxima crece con la volatilidad.