---
title: "3.5.5 Gestión de posiciones de opciones"
description: "Ajustes, roll, cierre anticipado, asignación temprana con opciones americanas y dividendos, y pin risk al vencimiento, medidos en datos con opciones."
url: "https://pythonparatrading.com/curso-python-trading/nivel-3/gestion-de-posiciones-de-opciones/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-3/gestion-de-posiciones-de-opciones.png"
---

# 3.5.5 · Gestión: ajustes, roll, cierre anticipado, asignación temprana y pin risk

> Abrir una posición de opciones es la mitad de la operación; la otra mitad son las decisiones mientras vive: cerrarla antes, rodarla, ajustarla o dejarla vencer. Esta lección mide en los datos sintéticos del nivel cinco reglas de gestión de una venta de puts, enseña qué es y qué no es un roll, cuándo conviene ejercer una opción americana antes del vencimiento y por qué un cierre pegado al strike es un riesgo.

- Curso: [Nivel 3: Derivados: futuros, spreads, forex y opciones](https://pythonparatrading.com/curso-python-trading/nivel-3/)
- Módulo: 3.5 · Estructuras de opciones en Python
- Duración: 65 min
- Requisitos: [3.4.2 · Árboles binomiales, Black-Scholes-Merton, Black-76 y Monte Carlo](https://pythonparatrading.com/curso-python-trading/nivel-3/binomial-black-scholes-black-76-y-monte-carlo/), [3.4.3 · Griegas: delta, gamma, vega, theta, rho, vanna, volga y charm](https://pythonparatrading.com/curso-python-trading/nivel-3/griegas-de-primer-y-segundo-orden/), [3.5.1 · Estructuras direccionales y verticales: call, put, covered call, collar y spreads](https://pythonparatrading.com/curso-python-trading/nivel-3/opciones-direccionales-y-verticales/), [3.5.4 · Herramienta propia: payoff, griegas agregadas y escenarios](https://pythonparatrading.com/curso-python-trading/nivel-3/herramienta-de-payoff-griegas-y-escenarios/)

## Al terminar esta lección

- Medir reglas de gestión (cierre por beneficio, por tiempo y por pérdida) sobre una venta sistemática de puts, con recompra al ask, y reconocer qué operaciones deciden la comparación.
- Calcular un roll como lo que es: un cierre y una apertura, y separar su resultado del de la operación original.
- Identificar con datos de opciones americanas cuándo es óptimo el ejercicio anticipado (calls antes de la fecha ex, puts muy dentro del dinero) y qué significa para quien está vendido.
- Cuantificar el pin risk: cuántos vencimientos cierran pegados a un strike y qué posición en acciones puede aparecer el lunes.

## Una posición viva: qué se puede decidir

Entre la apertura y el vencimiento de una posición de opciones hay cuatro decisiones posibles, y cada día que pasa
se toma una de ellas, aunque sea no hacer nada:

```mermaid
stateDiagram-v2
  [*] --> Abierta
  Abierta --> Ajustada: ajuste
  Ajustada --> Abierta
  Abierta --> Cerrada: cierre
  Abierta --> Rodada: roll
  Rodada --> Abierta: nueva posición
  Abierta --> Vencida: vencimiento
  Abierta --> Asignada: ejercicio
  Cerrada --> [*]
  Vencida --> [*]
  Asignada --> [*]
```

| Decisión | Qué es | Qué cambia en las griegas | Coste |
|---|---|---|---|
| Dejar vencer | No hacer nada hasta el vencimiento | Nada; la gamma crece al acercarse | Ninguno, salvo liquidación o entrega |
| Cerrar antes | Recomprar lo vendido (o vender lo comprado) | Todo a cero | Horquilla de salida |
| Rodar | Cerrar y abrir otra posición más lejos en el tiempo o en el strike | Las de la nueva posición | Dos horquillas |
| Ajustar | Añadir o quitar patas (alas, coberturas con subyacente, cambiar un strike) | Las que se buscan corregir | Una o varias horquillas |
| Asignación o ejercicio | La contraparte ejerce (opciones americanas) o se llega al vencimiento dentro del dinero | Opción sustituida por subyacente o efectivo | Dividendo perdido, entrega, financiación |

La lección usa dos conjuntos de datos sintéticos del nivel. Las opciones de ORX (lecciones 3.5.4 y 3.6.1) son
europeas y se liquidan en efectivo: sirven para medir reglas de cierre y de roll. Las de KRN, una acción ficticia con
dividendo trimestral, son americanas y se valoran con un árbol binomial con dividendos discretos (lección 3.4.2 y README de los
datos): sirven para el ejercicio anticipado y el pin risk. Los resultados de los datos no dicen qué regla funciona en
un mercado real; enseñan cómo medirla y dónde están las trampas.

## Cerrar antes: cinco reglas medidas en ORX

La estrategia base es sencilla: el día de cada vencimiento mensual se vende al bid una put de delta −0,16 del
vencimiento siguiente (con 20 días o más) y se gestiona con una regla. Es la pata de puts del strangle de la lección
3.6.1, sin apalancamiento: el resultado se mide en % del strike de cada operación.

```python
import numpy as np
import pandas as pd
from scipy.special import ndtr

ind = pd.read_csv("opciones3_indice.csv", parse_dates=["fecha"])
ind = ind.set_index("fecha")
S, r = ind["cierre"], ind["tipo_1m"] / 100
q = ind["rentabilidad_dividendo"] / 100
cad = pd.read_parquet(
    "opciones3_cadena.parquet",
    columns=["fecha", "vencimiento", "tipo", "strike", "bid", "ask",
             "iv_modelo"])
puts = cad[cad["tipo"] == "P"]
por_dia = dict(tuple(puts.groupby("fecha")))
series = {k: g.set_index("fecha")[["bid", "ask"]]
          for k, g in puts.groupby(["vencimiento", "strike"])}
vencs = sorted(puts["vencimiento"].unique())
print(len(por_dia), "días con cadena ·", len(vencs), "vencimientos")
```
```output
3017 días con cadena · 147 vencimientos
```

```python
def delta_bsm(tipo, S, K, T, iv, r, q):
    d1 = (np.log(S / K) + (r - q + iv**2 / 2) * T) / (iv * np.sqrt(T))
    w = 1.0 if tipo == "C" else -1.0
    return w * np.exp(-q * T) * ndtr(w * d1)


def put_por_delta(f, v, objetivo):
    """Put del vencimiento v con |delta| más cercana al objetivo."""
    g = por_dia[f]
    g = g[g["vencimiento"] == v]
    T = (v - f).days / 365
    d = delta_bsm("P", S[f], g["strike"].to_numpy(), T,
                  g["iv_modelo"].to_numpy(), r[f], q[f])
    return g.iloc[int(np.argmin(np.abs(np.abs(d) - objetivo)))]


def ciclo(objetivo=0.16):
    """Vende una put al bid el día de cada vencimiento mensual
    (o el primer día con cadena), del vencimiento siguiente con
    20 días o más. Devuelve una operación por ciclo."""
    ops, f = [], S.index[0]
    while True:
        while f not in por_dia:
            f = S.index[S.index.get_loc(f) + 1]
        v = next((x for x in vencs if (x - f).days >= 20), None)
        if v is None or v > S.index[-1]:
            return ops
        fila = put_por_delta(f, v, objetivo)
        k = fila["strike"]
        ops.append({"entrada": f, "venc": v, "strike": k,
                    "credito": fila["bid"], "ST": S[v],
                    "cot": series[(v, k)].loc[f:v].iloc[1:]})
        f = v


ops = ciclo(0.16)
cred = pd.Series([100 * o["credito"] / o["strike"] for o in ops])
print(len(ops), "operaciones · crédito medio",
      f"{cred.mean():.2f} % del strike")
pd.DataFrame(ops[:3]).drop(columns="cot")
```
```output
143 operaciones · crédito medio 0.65 % del strike
     entrada       venc  strike  credito       ST
0 2014-01-02 2014-02-21  1700.0      7.5  1882.25
1 2014-02-21 2014-03-21  1800.0      6.7  1839.01
2 2014-03-21 2014-04-17  1750.0      6.7  1793.62
```

Son 143 operaciones entre 2014 y 2025, con un crédito medio del 0,65 % del strike: unos 0,65 puntos por cada 100 de
nominal, cobrados a cambio de cubrir las caídas por debajo de un strike que queda, en mediana, un 5,8 % por debajo del
índice (entre el 4,1 y el 9,5 % en el 80 % central de las operaciones). Las reglas:

- **Mantener**: liquidación al vencimiento, sin hacer nada.
- **50 %**: recomprar en cuanto la put cueste la mitad del crédito (el beneficio objetivo más citado en la venta de
  prima).
- **21 días**: recomprar cuando queden 21 días naturales, antes de que la gamma crezca.
- **Stop 2×**: recomprar si la put llega a valer tres veces el crédito (pérdida de dos créditos).
- **50 % o 21 días**: la que llegue antes.

Todas recompran al ask del cierre del día en que se cumple la condición: es lo que se puede hacer con datos diarios,
y es menos favorable que una orden durante la sesión.

```python
def gestiona(op, objetivo=None, dias=None, stop=None):
    """P&L por unidad (puntos) y fecha de salida. Recompra al ask
    al cierre del primer día en que se cumple una regla; si no,
    liquidación al vencimiento."""
    for f, (bid, ask) in op["cot"].iterrows():
        if f >= op["venc"]:
            break
        if objetivo is not None and ask <= objetivo * op["credito"]:
            return op["credito"] - ask, f
        if stop is not None and ask >= stop * op["credito"]:
            return op["credito"] - ask, f
        if dias is not None and (op["venc"] - f).days <= dias:
            return op["credito"] - ask, f
    pago = max(op["strike"] - op["ST"], 0.0)
    return op["credito"] - pago, op["venc"]


REGLAS = {"mantener": {}, "50 %": {"objetivo": 0.5},
          "21 días": {"dias": 21}, "stop 2x": {"stop": 3.0},
          "50 % o 21 días": {"objetivo": 0.5, "dias": 21}}


def resultados(ops):
    pnl, dias = {}, {}
    for nombre, kw in REGLAS.items():
        filas = [gestiona(o, **kw) for o in ops]
        pnl[nombre] = pd.Series(
            [100 * x / o["strike"] for (x, _), o in zip(filas, ops)],
            index=[o["entrada"] for o in ops])
        dias[nombre] = np.mean([(f - o["entrada"]).days
                                for (_, f), o in zip(filas, ops)])
    pnl = pd.DataFrame(pnl)  # % del strike por operación
    tabla = pd.DataFrame({
        "media": pnl.mean(), "mediana": pnl.median(),
        "ganadoras": (pnl > 0).mean(), "peor": pnl.min(),
        "dias": pd.Series(dias), "total": pnl.sum()})
    return pnl, tabla


pnl, tabla = resultados(ops)
tabla.round(2)
```
```output
                media  mediana  ganadoras   peor   dias  total
mantener         0.29     0.55       0.95 -24.97  30.55  41.18
50 %             0.17     0.33       0.98 -24.97  11.41  23.80
21 días          0.23     0.25       0.85  -2.10   9.66  33.06
stop 2x          0.46     0.55       0.93  -3.53  29.78  65.75
50 % o 21 días   0.22     0.24       0.87  -2.10   7.91  31.46
```

La tabla es el resumen que suele enseñarse para defender una regla, y cada columna cuenta una historia distinta.
Cerrar al 50 % sube las operaciones ganadoras del 95 al 98 % y reduce la permanencia de 30,6 a 11,4 días, pero baja la
media de 0,29 a 0,17 % por operación y conserva la peor, −24,97 %. Las reglas de 21 días y de stop recortan la peor
operación a −2,10 y −3,53 %, y el stop suma 65,75 frente a 41,18 de mantener. Leída así, el stop parecería la mejor
regla. Pero la tabla mezcla 140 meses normales con tres episodios:

```python
peores = pnl["mantener"].nsmallest(3).index
print("Peores con «mantener»:",
      [f.date().isoformat() for f in peores])
pd.DataFrame({"total": pnl.sum(),
              "sin las 3 peores": pnl.drop(peores).sum(),
              "en esas 3": pnl.loc[peores].sum()}).round(2)
```
```output
Peores con «mantener»: ['2020-02-21', '2018-01-19', '2018-09-21']
                total  sin las 3 peores  en esas 3
mantener        41.18             78.29     -37.12
50 %            23.80             48.29     -24.49
21 días         33.06             33.20      -0.15
stop 2x         65.75             72.99      -7.24
50 % o 21 días  31.46             31.60      -0.15
```

La figura de la cabecera separa las dos partes. Las tres peores operaciones de «mantener» son las abiertas en febrero
de 2020, enero de 2018 y septiembre de 2018: en ellas, mantener pierde en total 37,1 puntos porcentuales del strike, y
cualquier regla que salga antes pierde menos. En las otras 140, mantener es la que más suma (78,3), el stop queda cerca (73,0) y las reglas de tiempo
se quedan en 33: cerrar a 21 días renuncia a la mitad de la theta de cada mes. La comparación entre reglas, con 143
ciclos, la deciden tres. Si la próxima crisis llega en un salto y no en varias sesiones, o en la segunda mitad del
ciclo en vez de en la primera, el orden puede cambiar.

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

Una regla de gestión no crea ventaja: cambia la forma del resultado. El objetivo de beneficio convierte una
distribución con muchos pequeños aciertos en otra con más aciertos y más pequeños, sin tocar la cola. Las reglas de
tiempo y de pérdida cambian beneficio en los meses normales por protección en los malos. Cuál conviene depende de
cuánto pesa la cola en tu capital (lección 3.6.1), no del porcentaje de aciertos.

</aside>

El stop tiene además un problema propio: se comprueba al cierre y se ejecuta donde está el mercado, no donde se puso.

```python
salidas = []
for o in ops:
    x, f = gestiona(o, stop=3.0)
    if f < o["venc"]:
        salidas.append({"entrada": o["entrada"].date(),
                        "salida": f.date(),
                        "perdida_en_creditos": -x / o["credito"]})
pd.DataFrame(salidas).round(2)
```
```output
      entrada      salida  perdida_en_creditos
0  2014-02-21  2014-02-27                 2.12
1  2016-06-17  2016-06-24                 2.59
2  2018-01-19  2018-02-02                 2.03
3  2018-09-21  2018-10-18                 6.82
4  2020-02-21  2020-03-09                 6.88
5  2022-06-17  2022-07-07                 2.39
6  2025-02-21  2025-02-28                 2.24
7  2025-03-21  2025-04-04                 4.21
```

De ocho stops, cinco se ejecutan entre 2,03 y 2,59 créditos de pérdida, cerca de los 2 previstos. Los de las
operaciones abiertas en septiembre de 2018, febrero de 2020 y marzo de 2025 se ejecutan a 6,82, 6,88 y 4,21 créditos:
la put pasó en una sola sesión de valer menos de tres créditos a valer más de cinco, o casi ocho. El de 2020 salta el
9 de marzo, el día del −7,9 % del README: un stop comprobado al cierre llega después del salto. Y un stop dentro de la sesión, sobre un precio de opción con horquillas que se abren en el estrés, salta
con más facilidad por ruido.

## Rodar y ajustar

Rodar (*roll*) es cerrar una posición y abrir otra parecida más lejos en el tiempo, en otro strike o ambas cosas. Se
suele presentar como una forma de «dar tiempo» a una operación perdedora. Los números de los datos enseñan lo que es:
dos operaciones. La put 2525 vendida el 19-01-2018 queda dentro del dinero el 5 de febrero, el día del salto del
−4,2 % del README; se recompra al ask y se vende al bid una put de delta −0,16 del vencimiento siguiente:

```python
o = next(o for o in ops if o["entrada"] == pd.Timestamp("2018-01-19"))
tocada = next(f for f in o["cot"].index if S[f] < o["strike"])
cierre = o["cot"].at[tocada, "ask"]
nueva = put_por_delta(tocada, next(
    x for x in vencs if (x - tocada).days >= 20 and x > o["venc"]),
    0.16)
v2, k2 = nueva["vencimiento"], nueva["strike"]
pago2 = max(k2 - S[v2], 0.0)
print(f"Vendida {o['entrada'].date()}: put {o['strike']:.0f} a "
      f"{o['credito']}; tocada el {tocada.date()} con ORX {S[tocada]}")
print(f"Recompra al ask {cierre}; nueva put {k2:.0f} "
      f"({v2.date()}) al bid {nueva['bid']}")
pd.Series({
    "mantener": o["credito"] - max(o["strike"] - o["ST"], 0),
    "cerrar al tocar": o["credito"] - cierre,
    "rodar (cerrar + nueva)": (o["credito"] - cierre
                               + nueva["bid"] - pago2),
    "  de ello, la nueva": nueva["bid"] - pago2,
}).round(2)
```
```output
Vendida 2018-01-19: put 2525 a 9.9; tocada el 2018-02-05 con ORX 2440.24
Recompra al ask 106.5; nueva put 2150 (2018-03-16) al bid 30.2
mantener                 -194.87
cerrar al tocar           -96.60
rodar (cerrar + nueva)    -66.40
  de ello, la nueva        30.20
dtype: float64
```

Mantenida, la put vendida a 9,9 puntos pierde 194,87. Cerrada al tocar, 96,60. El roll suma −66,40, pero esa cifra
junta dos operaciones: la primera perdió 96,60 y quedó realizada en la recompra; la segunda, una put 2150 de marzo
vendida a 30,2 con la volatilidad disparada, venció sin valor y ganó 30,20. Que la segunda saliera bien no tiene nada
que ver con la primera: podría haberse abierto sin la primera, y habría ganado lo mismo. Juntarlas en un solo P&L
hace parecer que el roll recuperó parte de la pérdida.

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

El roll «a crédito» (recomprar y vender otra opción que cobre más de lo que cuesta la recompra) obliga a vender más
riesgo: un strike más cercano, un vencimiento más lejano o más contratos. Repetido después de cada pérdida, es una
martingala con opciones: la posición crece justo cuando el mercado va en contra. Se evalúa como una operación nueva,
con el tamaño y el riesgo que tendría si no existiera la anterior.

</aside>

Los ajustes son variantes de lo mismo: añadir o quitar patas para cambiar las griegas. Con la herramienta de la
lección 3.5.4 se pueden calcular antes de hacerlos:

| Ajuste | Ejemplo | Efecto principal |
|---|---|---|
| Comprar un ala | Convertir una put vendida en un put spread | Pérdida máxima acotada; menos theta y menos vega corta |
| Cubrir la delta | Vender o comprar subyacente o futuros | Delta a cero; gamma y vega sin cambios |
| Rodar la pata no tocada | En un strangle tras una caída, subir la call vendida | Recentra la delta cobrando algo más de prima; aumenta el riesgo si el mercado rebota |
| Reducir tamaño | Recomprar parte de los contratos | Todas las griegas en proporción; realiza parte de la pérdida |

## Asignación temprana: opciones americanas con dividendos

Las opciones sobre acciones de EE. UU. son americanas: el titular puede ejercerlas cualquier día. Quien las tiene
vendidas puede ser asignado antes del vencimiento. El reparto lo hace la cámara (OCC) entre sus miembros y cada bróker
entre sus clientes con un método fijo, FIFO o aleatorio, que debe comunicar por escrito (regla 2360 de FINRA). Para
saber cuándo ocurre, hay que saber cuándo le conviene al titular.

Una opción americana vale al menos su valor intrínseco. Si vale exactamente eso, ejercerla ya es óptimo: esperar no
añade nada. La cadena de KRN tiene, para cada opción, el precio americano (`precio_modelo`, árbol binomial de 150
pasos con dividendos discretos) y el de la misma opción europea (`europea_modelo`). La diferencia es la **prima de
ejercicio anticipado**:

```python
krn = pd.read_csv("accion3_diario.csv", parse_dates=["fecha"])
krn = krn.set_index("fecha")["cierre"]
ev = pd.read_csv("accion3_eventos.csv", parse_dates=["fecha"])
divs = ev[ev["evento"] == "dividendo"].set_index("fecha")["dividendo"]
op_a = pd.read_parquet("accion3_opciones.parquet")
op_a["S"] = krn.reindex(op_a["fecha"]).to_numpy()
w = np.where(op_a["tipo"] == "C", 1.0, -1.0)
op_a["intr"] = np.maximum(w * (op_a["S"] - op_a["strike"]), 0)
op_a["valor_temporal"] = op_a["precio_modelo"] - op_a["intr"]
op_a["prima_ejercicio"] = (op_a["precio_modelo"]
                           - op_a["europea_modelo"])
# precio = intrínseco (± el redondeo del cierre y del árbol):
# ejercer ya o en la próxima ocasión da lo mismo
op_a["ejercer"] = op_a["valor_temporal"] < 0.02
dentro = op_a[op_a["intr"] > 0]
dentro.groupby("tipo")[["prima_ejercicio", "ejercer"]].agg(
    ["mean", "max"]).round(3)
```
```output
     prima_ejercicio        ejercer
                mean    max    mean   max
tipo
C              0.188  1.019   0.022  True
P              0.335  2.348   0.229  True
```

Entre las opciones dentro del dinero, la prima de ejercicio anticipado media es de 0,19 USD en las calls y de 0,34 en
las puts, con máximos de 1,02 y 2,35 USD. La celda considera óptimo ejercer cuando el precio americano supera al
intrínseco en menos de 2 céntimos: el cierre está redondeado al céntimo y el árbol, con pasos de unas horas, deja
algún céntimo de valor a ejercer en el paso siguiente. Con ese criterio, ejercer ya es óptimo en el 2,2 % de las filas
de calls dentro del dinero y en el 22,9 % de las de puts. Son dos mecanismos distintos.

### Calls: el dividendo

Una call no paga dividendo; la acción sí. La víspera de la fecha ex, el titular de una call dentro del dinero compara
dos cosas: si ejerce, recibe la acción y cobra el dividendo $D$; si no, la acción cae $D$ al día siguiente y él
conserva el valor temporal de la opción. Por la paridad put-call, ese valor temporal es aproximadamente el de la put
del mismo strike más el interés del strike hasta el vencimiento. Ejercer solo puede convenir si

$$
D > P(K) + K\left(1 - e^{-r\tau}\right)
$$

con $\tau$ el tiempo desde la fecha ex hasta el vencimiento. La celda lo contrasta con el árbol en todas las vísperas
de fecha ex de los datos:

```python
sesiones = krn.index
vispera = {sesiones[sesiones.get_loc(d) - 1]: d for d in divs.index}
c = dentro[(dentro["tipo"] == "C")
           & dentro["fecha"].isin(list(vispera))].copy()
c["ex"] = c["fecha"].map(vispera)
c = c[c["vencimiento"] >= c["ex"]]
c["D"] = c["ex"].map(divs)
eu_put = op_a[op_a["tipo"] == "P"].set_index(
    ["fecha", "vencimiento", "strike"])["europea_modelo"]
c["put"] = eu_put.reindex(
    pd.MultiIndex.from_frame(c[["fecha", "vencimiento", "strike"]])
).to_numpy()
tau = (c["vencimiento"] - c["ex"]).dt.days / 365
r_c = ind["tipo_1m"].reindex(c["fecha"]).to_numpy() / 100
# lo que se pierde al ejercer: el seguro de la put y el interés
# del strike hasta el vencimiento
c["umbral"] = c["put"] + c["strike"] * (1 - np.exp(-r_c * tau))
c["regla"] = c["D"] > c["umbral"]
print(len(c), "calls dentro del dinero en las vísperas")
print(pd.crosstab(c["ejercer"], c["regla"],
                  rownames=["árbol: ejercer"], colnames=["regla"]))
c[c["ejercer"]].groupby(c["fecha"].dt.year).size()
```
```output
494 calls dentro del dinero en las vísperas
regla           False  True
árbol: ejercer
False             324     66
True                0    104
fecha
2022    46
2023    22
2024    14
2025    22
dtype: int64
```

De 494 calls dentro del dinero en las vísperas, el árbol ejerce 104 y la regla marca esas 104 y 66 más. Es una
condición necesaria, no suficiente: en las 66 restantes el árbol todavía encuentra valor temporal (la aproximación
ignora la volatilidad que queda hasta el vencimiento, más allá del seguro de la put). Los ejercicios óptimos aparecen
todos los años (46 en 2022, 22 en 2023, 14 en 2024 y 22 en 2025) y siempre en la serie que vence una o dos semanas
después de la fecha ex: cuanto menos tiempo queda, menos valor temporal se sacrifica. Un ejemplo, la call 95 que vence
el 18-02-2022 con la acción en 106-110 USD:

```python
ej = op_a[(op_a["tipo"] == "C") & (op_a["strike"] == 95)
          & (op_a["vencimiento"] == pd.Timestamp("2022-02-18"))]
ej = ej.set_index("fecha").loc["2022-01-27":"2022-02-17"]
ej = ej.assign(europea_menos_intr=ej["europea_modelo"] - ej["intr"])
ej[["S", "precio_modelo", "intr", "valor_temporal",
    "europea_menos_intr"]].iloc[[0, 5, 8, 9, 10, 12]].round(3)
```
```output
                 S  precio_modelo   intr  valor_temporal  europea_menos_intr
fecha
2022-01-27  109.79         14.806  14.79           0.016              -0.821
2022-02-03  110.43         15.436  15.43           0.006              -0.850
2022-02-08  106.78         11.779  11.78          -0.001              -0.847
2022-02-09  106.84         11.835  11.84          -0.005              -0.857
2022-02-10  106.62         11.639  11.62           0.019               0.019
2022-02-14  105.60         10.606  10.60           0.006               0.006
```

*Fig. — Call 95 de KRN con vencimiento el 18-02-2022 (acción en 106-110 USD): precio menos valor intrínseco de la americana y de la europea antes y después de la fecha ex del 10-02-2022 (dividendo de 0,88 USD).* Dos líneas de 2022-01-21 a 2022-02-17. La americana vale casi exactamente su valor intrínseco: +0,04 USD al principio y 0 en las sesiones anteriores a la fecha ex (ejercer es óptimo). La europea (destacada) vale entre 0,78 y 0,86 USD menos que su intrínseco antes de la fecha ex, casi el dividendo de 0,88 que perderá, y a partir del 10 de febrero coincide con la americana.

La americana vale su intrínseco más 0,016 USD el 27 de enero y prácticamente nada en la semana anterior a la fecha ex
(0,006 el 3 de febrero; −0,001 y −0,005 en las dos vísperas, por el redondeo del cierre). La europea vale entre 0,82 y 0,86 USD menos que su intrínseco: no puede
ejercerse y perderá el dividendo de 0,88. Desde el 10 de febrero, sin dividendos pendientes, las dos coinciden. Quien
tenga esa call vendida debe contar con ser asignado la víspera: entregará 100 acciones por contrato y, si no las
tenía, quedará corto en la fecha ex y deberá el dividendo. El diagrama resume la comprobación que hace un vendedor
de calls antes de cada fecha ex (VT es el valor temporal de la call, D el dividendo):

```mermaid
flowchart TB
  A{Call corta ITM} --> B{Fecha ex antes}
  B -- no --> C[Riesgo bajo]
  B -- sí --> D{VT menor que D}
  D -- no --> C
  D -- sí --> E[Espera asignación]
  E --> F[Cerrar o rodar]
```

### Puts: el interés del strike

Una put muy dentro del dinero es casi una venta a plazo de la acción a precio K. Ejercerla adelanta el cobro de K, que
rinde intereses; esperar conserva un seguro contra que la acción vuelva a subir por encima de K, que vale poco si la
put está muy dentro del dinero. Con tipos positivos, a partir de cierta distancia ejercer es óptimo:

```python
p = dentro[dentro["tipo"] == "P"].copy()
p["dentro_pct"] = 100 * (p["strike"] / p["S"] - 1)
tramo = pd.cut(p["dentro_pct"], [0, 2, 5, 10, 20, 60])
p.groupby(tramo, observed=True).agg(
    filas=("ejercer", "size"), ejercer=("ejercer", "mean"),
    prima_media=("prima_ejercicio", "mean")).round(3)
```
```output
            filas  ejercer  prima_media
dentro_pct
(0, 2]       3594    0.001        0.065
(2, 5]       5412    0.034        0.099
(5, 10]      8991    0.122        0.184
(10, 20]     9438    0.337        0.377
(20, 60]     7396    0.476        0.767
```

Cerca del dinero el ejercicio casi nunca es óptimo (0,1 % de las filas). A más de un 10 % dentro del dinero lo es en
un tercio de las filas (33,7 %), y a más de un 20 % en casi la mitad (47,6 %). La prima de ejercicio anticipado crece con la distancia, de 0,07 a
0,77 USD de media. Para quien vende puts sobre acciones, una caída fuerte trae una asignación anticipada probable: la
compra de 100 acciones por contrato antes de lo previsto, que hay que financiar.

## Pin risk en el vencimiento

En las opciones con entrega física, el día del vencimiento las que acaban dentro del dinero se ejercen
automáticamente salvo instrucción contraria (el procedimiento de ejercicio por excepción de la regla 805 de la OCC) y
el titular tiene hasta las 17:30 ET para decidir (regla 2360 de FINRA). Si la acción cierra justo en el strike, quien
vendió no sabe hasta el día siguiente si será asignado: depende de lo que haga el precio después del cierre y de lo
que decidan los titulares. Es el **pin risk**.

```python
filas = []
for v in sorted(op_a["vencimiento"].unique()):
    if v > sesiones[-1]:
        continue
    ultimo = op_a.loc[op_a["vencimiento"] == v, "fecha"].max()
    ks = op_a[(op_a["fecha"] == ultimo) & (op_a["vencimiento"] == v)
              & (op_a["tipo"] == "C")].set_index("strike")
    k = ks.index[np.abs(ks.index - krn[v]).argmin()]
    filas.append({"vencimiento": v.date(), "cierre": krn[v],
                  "strike": k, "distancia": krn[v] - k,
                  "interes_abierto": ks.at[k, "interes_abierto"]})
pin = pd.DataFrame(filas)
cerca = pin["distancia"].abs() <= 0.25
print(f"{cerca.sum()} de {len(pin)} vencimientos a 0,25 USD o menos "
      f"de un strike (al azar: {len(pin) * 0.5 / 2.5:.1f})")
pin[cerca].tail(4)
```
```output
11 de 48 vencimientos a 0,25 USD o menos de un strike (al azar: 9.6)
   vencimiento  cierre  strike  distancia  interes_abierto
28  2024-05-17  137.35   137.5      -0.15             5368
30  2024-07-19  159.84   160.0      -0.16             4967
37  2025-02-21  192.32   192.5      -0.18             6418
46  2025-11-21  172.67   172.5       0.17             4853
```

En los datos, 11 de los 48 vencimientos de KRN cierran a 0,25 USD o menos de un strike, frente a 9,6 que daría el
azar con strikes de 2,5 en 2,5: en los datos no hay atracción hacia los strikes, solo aritmética. En mercados reales
la literatura documenta que los cierres de las acciones con opciones listadas se agrupan cerca de los strikes los días
de vencimiento (Ni, Pearson y Poteshman, 2005, en los recursos). Uno de los casos de los datos, el 19-07-2024:

```python
rv = np.log(krn).diff().std()  # desviación típica diaria
S_v, K_v, n = 159.84, 160.0, 10
print(f"Volatilidad diaria de KRN: {rv:.2%}")
print(f"Si no hay asignación: 0 acciones. Si la hay: "
      f"{-100 * n} acciones a {K_v}")
print(f"Riesgo de un día de 1000 acciones: "
      f"{1000 * S_v * rv:,.0f} USD (1 desviación típica)")
```
```output
Volatilidad diaria de KRN: 1.69%
Si no hay asignación: 0 acciones. Si la hay: -1000 acciones a 160.0
Riesgo de un día de 1000 acciones: 2,708 USD (1 desviación típica)
```

KRN cierra a 159,84 con 4.967 contratos abiertos en el strike 160. Con 10 calls 160 vendidas, el lunes la posición
puede ser cero acciones o −1.000. Si hay noticias después del cierre y la acción sube, los titulares ejercerán. Un
día de 1.000 acciones de KRN es un riesgo de unos 2.700 USD por desviación típica; un resultado o una noticia de fin
de semana, varias veces eso. El mismo problema, al revés, tienen las puts vendidas.

La delta explica por qué no se puede cubrir con antelación:

```python
Sg = np.array([155.0, 158.0, 159.0, 159.5, 160.0, 160.5, 161.0,
               162.0, 165.0])
perfil = {f"{d} días": delta_bsm("C", Sg, 160.0, d / 365, 0.25,
                                  0.04, 0.0)
          for d in (10, 2, 0.25)}
pd.DataFrame(perfil, index=Sg).round(3)
```
```output
       10 días  2 días  0.25 días
155.0    0.236   0.045      0.000
158.0    0.399   0.255      0.028
159.0    0.458   0.375      0.171
159.5    0.489   0.441      0.319
160.0    0.519   0.508      0.503
160.5    0.549   0.575      0.686
161.0    0.578   0.640      0.831
162.0    0.636   0.756      0.972
165.0    0.785   0.954      1.000
```

*Fig. — Delta de Black-Scholes de una call de strike 160 (volatilidad del 25 %, tipo del 4 %) a 10 días, 2 días y 6 horas del vencimiento: cerca del vencimiento, la delta salta de 0 a 1 en pocos dólares.* Tres curvas de delta frente al precio de KRN, de 150 a 170 USD. A 10 días la curva es suave: 0,24 en 155, 0,52 en 160 y 0,79 en 165. A 2 días es más empinada: 0,05 en 155 y 0,95 en 165. A 6 horas (destacada) es casi un escalón: 0,03 en 158, 0,50 en 160 y 0,97 en 162.

A 10 días, la delta de la call 160 pasa de 0,24 a 0,79 entre 155 y 165. A 6 horas del vencimiento es casi un escalón:
0,03 en 158, 0,50 en 160 y 0,97 en 162. Cubrir la delta de una opción pegada al strike en la última sesión obliga a
comprar y vender casi todo el nominal con cada movimiento de un dólar (lección 3.6.2). La solución práctica es cerrar
las posiciones vendidas cercanas al strike antes del cierre del día del vencimiento, aceptando la horquilla.

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

El calendario de los datos del curso tiene una particularidad: la cadena de KRN no incluye la serie que vence el
propio día del vencimiento; su última fila es la sesión anterior. Las celdas usan el cierre del día del vencimiento
para el subyacente y los strikes listados la víspera.

</aside>

## Índices con liquidación en efectivo

Las opciones sobre índices como las SPX son europeas y se liquidan en efectivo: no hay asignación anticipada ni
entrega de acciones, y desaparecen los dos riesgos anteriores. Queda otro: el precio de liquidación. En las SPX
estándar, según la ficha de Cboe, la negociación termina la víspera (normalmente un jueves) y el valor de liquidación
(SET) se calcula con los precios de apertura de los componentes el día del vencimiento: una posición mantenida hasta
el final queda expuesta a la apertura del viernes sin poder cerrarse. En los datos de ORX se liquida al cierre del
día del vencimiento, por simplicidad. Antes de mantener una posición hasta el vencimiento hay que leer en la ficha
del contrato cómo y cuándo se fija el precio de liquidación.

## Ejercicios

1. **Otra delta.** Repite la tabla de reglas y la separación de las tres peores operaciones con puts de delta −0,30.
   ¿Cambia la conclusión?

**Solución.**

Con puts más cercanas al dinero el crédito es mayor y la conclusión se mantiene. En total, el stop suma 90,05 y
mantener 68,41; sin las tres peores operaciones, mantener suma 113,62 y el stop 105,94. Las reglas de tiempo se quedan
en 48-49 con o sin esos episodios: cortan la cola y renuncian a buena parte de la theta. La peor operación de
mantener empeora a −26,01 % y la del stop a −10,02 %: con más delta, el salto que se come el stop es mayor.

```python
ops30 = ciclo(0.30)
pnl30, tabla30 = resultados(ops30)
peores30 = pnl30["mantener"].nsmallest(3).index
print(tabla30.round(2))
pd.DataFrame({"total": pnl30.sum(),
              "sin las 3 peores": pnl30.drop(peores30).sum()}).round(2)
```
```output
                media  mediana  ganadoras   peor   dias  total
mantener         0.48     0.98       0.89 -26.01  30.55  68.41
50 %             0.27     0.59       0.93 -26.01  13.58  39.12
21 días          0.35     0.39       0.83  -4.73   9.66  49.47
stop 2x          0.63     0.96       0.86 -10.02  29.65  90.05
50 % o 21 días   0.32     0.39       0.83  -4.73   8.32  45.27
                total  sin las 3 peores
mantener        68.41            113.62
50 %            39.12             62.82
21 días         49.47             48.26
stop 2x         90.05            105.94
50 % o 21 días  45.27             44.07
```

2. **Rodar sin bajar el strike.** En el ejemplo de 2018, en vez de vender la put de delta −0,16 de marzo, vende la put
   2525 de marzo (mismo strike, más tiempo). Calcula el crédito del roll y el resultado de la nueva operación.

**Solución.**

Vender el mismo strike un mes más lejos cobra 32,6 puntos más de lo que cuesta la recompra (un roll a crédito), pero
la nueva put está dentro del dinero: es una apuesta mucho mayor que la de delta −0,16. ORX vence en marzo a 2315,19 y
la nueva operación pierde 70,71 puntos. Sumadas, las dos operaciones pierden 167,3 (−96,6 de la primera y −70,7 de la
segunda), casi tanto como mantener la original (−194,87). El crédito del roll no era una ganancia: era la prima de
un riesgo nuevo.

```python
fila = por_dia[tocada]
fila = fila[(fila["vencimiento"] == v2)
            & (fila["strike"] == o["strike"])].iloc[0]
pago = max(o["strike"] - S[v2], 0.0)
print(f"Recompra {cierre} · venta de la 2525 de marzo a "
      f"{fila['bid']} · crédito del roll {fila['bid'] - cierre:.1f}")
print(f"ORX el {v2.date()}: {S[v2]} · resultado de la nueva: "
      f"{fila['bid'] - pago:.2f}")
```
```output
Recompra 106.5 · venta de la 2525 de marzo a 139.1 · crédito del roll 32.6
ORX el 2018-03-16: 2315.19 · resultado de la nueva: -70.71
```

3. **Pin risk.** Tienes 10 calls 160 de KRN vendidas y la acción cotiza a 159,90 a falta de una hora para el cierre
   del día del vencimiento. Enumera tus opciones y qué riesgo deja cada una.

**Solución.**

Recomprar las calls: paga la horquilla y elimina el riesgo. No hacer nada: si la acción cierra por debajo de 160 y no
hay noticias, vencen sin valor; si sube después del cierre, pueden asignarte y el lunes estarás corto de 1.000
acciones (unos 2.700 USD de riesgo por desviación típica de un día, más si hay noticias). Comprar 500 acciones como
cobertura parcial: deja una posición de +500 o −500 acciones según haya o no asignación, la misma incertidumbre con
otro signo. Rodar al vencimiento siguiente: cierra el riesgo de hoy y abre una posición nueva, que se evalúa como tal.
La opción más común en una mesa es recomprar las posiciones vendidas a menos de un strike del precio antes del cierre.

## Autoevaluación

1. En la venta mensual de puts de delta −0,16, la regla «cerrar al 50 % del crédito» gana más a menudo (98 % de operaciones ganadoras) pero suma menos que mantener (23,8 frente a 41,2 % del strike). ¿Por qué?

   - A. Porque paga más comisiones
   - B. Porque renuncia a la theta de los días que quedan en las operaciones normales y no protege de las caídas que llegan antes de alcanzar el objetivo: su peor operación es la misma, −25,0 %
   - C. Porque el 50 % es un objetivo demasiado ambicioso
   - D. Porque el cierre al ask es gratuito

   *Respuesta B: Porque renuncia a la theta de los días que quedan en las operaciones normales y no protege de las caídas que llegan antes de alcanzar el objetivo: su peor operación es la misma, −25,0 %.* Un objetivo de beneficio solo actúa cuando la operación va bien. La caída de febrero de 2020 llegó antes de que la put perdiera la mitad de su valor, así que la regla la sufre entera. En las 140 operaciones normales suma 48,3 frente a 78,3 de mantener.

2. El stop al doble del crédito suma 65,8 frente a 41,2 de mantener. ¿Qué conclusión es correcta?

   - A. Que el stop es una ventaja demostrada en ventas de prima
   - B. Que la diferencia la deciden tres operaciones: sin ellas, mantener suma 78,3 y el stop 73,0; con 143 ciclos, la comparación depende de cómo se desarrollaron tres episodios
   - C. Que mantener tiene un error de cálculo
   - D. Que el stop elimina el riesgo de cola

   *Respuesta B: Que la diferencia la deciden tres operaciones: sin ellas, mantener suma 78,3 y el stop 73,0; con 143 ciclos, la comparación depende de cómo se desarrollaron tres episodios.* En las 140 operaciones normales el stop salta alguna vez y pierde lo que mantener habría recuperado. Su ventaja total sale de 2018 y 2020, cuando la caída se desarrolló en varias sesiones. En un salto de apertura, un stop se ejecuta mucho más lejos: en los datos, hasta 6,9 veces el crédito en vez de 2.

3. Una put vendida se recompra a 106,5 y en el mismo momento se vende otra de un vencimiento posterior a 30,2. ¿Cuál es el resultado de la operación original?

   - A. −66,4 puntos, porque el roll se cobra a crédito
   - B. El crédito inicial menos 106,5 (−96,6 puntos): el roll es un cierre y una apertura; los 30,2 son la prima de una operación nueva, con su propio riesgo
   - C. Cero, porque se ha rodado
   - D. No se sabe hasta el nuevo vencimiento

   *Respuesta B: El crédito inicial menos 106,5 (−96,6 puntos): el roll es un cierre y una apertura; los 30,2 son la prima de una operación nueva, con su propio riesgo.* Rodar no repara una pérdida: la realiza y abre otra posición. En el ejemplo de 2018, la nueva put venció sin valor y sumó 30,2 puntos, pero podría no haber sido así; juntar las dos operaciones esconde la pérdida de la primera.

4. La víspera de la fecha ex, una call americana de KRN muy dentro del dinero vale exactamente su intrínseco y la europea equivalente 0,86 USD menos. ¿Qué hace un titular racional y qué le pasa a quien la tiene vendida?

   - A. Nada: las opciones no tienen dividendos
   - B. Ejerce para cobrar el dividendo de 0,88 USD; el vendedor es asignado, entrega las acciones y pierde ese dividendo
   - C. Vende la acción
   - D. Espera al vencimiento, porque ejercer antes nunca es óptimo

   *Respuesta B: Ejerce para cobrar el dividendo de 0,88 USD; el vendedor es asignado, entrega las acciones y pierde ese dividendo.* Ejercer antes de la fecha ex da derecho al dividendo; esperar conserva un valor temporal que aquí es casi nulo. Para el vendedor, la asignación llega antes de la fecha ex y tiene que entregar las acciones (o queda corto de ellas y debe el dividendo).

5. KRN cierra a 159,84 USD el día del vencimiento y tienes 10 calls 160 vendidas. ¿Cuál es el riesgo?

   - A. Ninguno: las calls vencen fuera del dinero
   - B. No saber hasta después del cierre si te asignarán: el titular puede decidir ejercer hasta las 17:30 ET; el lunes puedes amanecer corto de 1.000 acciones, con un riesgo de un día de unos 2.700 USD por desviación típica
   - C. Que el bróker cobre una comisión
   - D. Que las calls valgan más de 160

   *Respuesta B: No saber hasta después del cierre si te asignarán: el titular puede decidir ejercer hasta las 17:30 ET; el lunes puedes amanecer corto de 1.000 acciones, con un riesgo de un día de unos 2.700 USD por desviación típica.* Las opciones fuera del dinero por céntimos no se ejercen automáticamente, pero el titular puede presentar una instrucción contraria hasta el corte de las 17:30 ET (regla 2360 de FINRA). Con noticias después del cierre, lo hará. El vendedor no lo sabrá hasta el día siguiente.

## Ideas clave

- Las reglas de gestión cambian la forma del resultado, no crean ventaja: cerrar al 50 % sube el porcentaje de aciertos y baja la suma; cerrar por tiempo o por pérdida corta la cola a costa de las operaciones normales.
- En una venta de prima la comparación entre reglas la deciden muy pocas operaciones (aquí, 3 de 143): antes de elegir una regla, mira de dónde sale la diferencia.
- Un stop en opciones se comprueba al cierre y se ejecuta al ask: en los saltos se ejecuta mucho más lejos de donde se puso.
- Rodar es cerrar y abrir. La pérdida de la primera operación queda realizada; la segunda es una apuesta nueva.
- Las opciones americanas sobre acciones pueden ejercerse antes del vencimiento: calls muy dentro del dinero antes de la fecha ex y puts muy dentro del dinero con tipos positivos. El vendedor debe vigilarlo.
- Un cierre pegado al strike de una opción con entrega física deja la posición del lunes en el aire: ciérrala antes del vencimiento si no aceptas la incertidumbre.

## Recursos

### Documentación

- [FINRA: regla 2360 (ejercicio por excepción, corte de las 17:30 ET y asignación aleatoria o FIFO)](https://www.finra.org/rules-guidance/rulebooks/finra-rules/2360) · finra.org
- [Cboe: especificaciones de las opciones sobre el S&P 500 (estilo europeo, liquidación SET)](https://www.cboe.com/tradable_products/sp_500/spx_options/specifications/) · cboe.com
- [Ni, Pearson y Poteshman (2005), Stock price clustering on option expiration dates, Journal of Financial Economics 78](https://doi.org/10.1016/j.jfineco.2004.08.005) · doi.org

### Libros

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

### Datos

- [Datos del nivel 3: cadena de opciones americanas de KRN (Parquet)](https://pythonparatrading.com/curso/datos/nivel-3/accion3_opciones.parquet) · Descarga · accion3_opciones.parquet
- [Datos del nivel 3: cadena diaria de opciones de ORX (Parquet)](https://pythonparatrading.com/curso/datos/nivel-3/opciones3_cadena.parquet) · Descarga · opciones3_cadena.parquet

Lección anterior: [3.5.4 · Herramienta propia: payoff, griegas agregadas y escenarios](https://pythonparatrading.com/curso-python-trading/nivel-3/herramienta-de-payoff-griegas-y-escenarios/)

Lección siguiente: [3.6.1 · Venta sistemática de prima: put-write, strangles y su riesgo de cola](https://pythonparatrading.com/curso-python-trading/nivel-3/venta-sistematica-de-prima-y-riesgo-de-cola/)
