σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademyRutas
Ctrl K
AO
+1,2 k estudiantes
Iniciar sesiónUnirse ↗
Rutas
AO
+1,2 k estudiantes
Iniciar sesión
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Ruta de Python›Módulo 2 · NumPy y pandas para datos de mercado›Tema 2.17·~45 minIntermedio

Eventos corporativos: splits y dividendos

Posición en la rutaMódulo 2 de 11 · Tema 17 de 20
2.17 Eventos corporativos: splits y dividendos
—Puntuación del lab— / 100XP total—Racha—

Un historial de precios que miente

Cuando una empresa divide sus acciones 4 por 1, cada titular recibe cuatro acciones por cada una y el precio cae a la cuarta parte. Nadie perdió nada, pero el historial en bruto muestra un día de -75 %. Un dividendo en efectivo hace lo mismo a menor escala: en la fecha ex-dividendo el precio baja aproximadamente el importe del dividendo. Una estrategia que lea precios en bruto verá desplomes que no dañaron a nadie. La solución es ajustar el historial: reescalar todos los días anteriores al evento para que la serie sea continua y comparable con los precios de hoy.

import pandas as pd

index = pd.bdate_range("2026-03-02", periods=6)
raw = pd.Series([480.0, 484.0, 488.0, 123.0, 124.5, 126.0], index=index, name="close")   # 4-for-1 split on 5 March

print(raw.pct_change().round(4).tolist())
# [nan, 0.0083, 0.0083, -0.748, 0.0122, 0.012]    the -74.8% day never happened to anyone

Ajustar un split

Solo cambian los días anteriores al split: divide sus precios por la razón (4 para un split 4 por 1). Los precios actuales se quedan como cotizan, así que la serie ajustada termina en el precio real de hoy. Construye una máscara Verdadero/Falso con index >= split_date (una cadena funciona frente a un DatetimeIndex) y usa where, que conserva un valor donde la máscara es Verdadera y toma el reemplazo en el resto. El volumen va al revés: tras el split se negocian cuatro veces más acciones, así que los volúmenes anteriores se multiplican por la razón. Un contrasplit usa una razón menor que 1 y las mismas fórmulas.

split_date = "2026-03-05"
adjusted = raw.where(raw.index >= split_date, raw / 4)    # the days before the split, divided by 4

print(adjusted.tolist())                      # [120.0, 121.0, 122.0, 123.0, 124.5, 126.0]
print(adjusted.pct_change().round(4).tolist())   # [nan, 0.0083, 0.0083, 0.0082, 0.0122, 0.012]   no more crash
# Volume goes the other way: older days are multiplied
volume = pd.Series([1000, 1100, 900, 4200, 4000, 4300], index=index)
print(volume.where(volume.index >= split_date, volume * 4).tolist())   # [4000, 4400, 3600, 4200, 4000, 4300]

Ajustar un dividendo

Un dividendo es menor que un split, así que el ajuste es un factor cercano a 1: 1 - dividendo / cierre anterior, donde el cierre anterior es el último cierre antes de la fecha ex-dividendo. Multiplica cada precio anterior a la fecha ex por ese factor. El cierre justo antes de la fecha ex baja entonces exactamente el dividendo, el movimiento del día ex muestra solo lo que hizo realmente el mercado, y los rendimientos calculados sobre la serie ajustada incluyen el dividendo. Ese cierre ajustado es el que deben usar los cálculos de rendimiento. Pon el factor en su propia función pequeña para poder probarlo y reutilizarlo.

def dividend_factor(prev_close, dividend):
    return 1 - dividend / prev_close


prices = pd.Series([100.0, 101.0, 102.0, 100.8, 101.5, 102.5], index=index)   # a 1.50 dividend, ex-date 5 March
ex_date, dividend = "2026-03-05", 1.5

prev_close = prices[prices.index < ex_date].iloc[-1]       # 102.0, the last close before the ex-date
factor = dividend_factor(prev_close, dividend)
print(round(factor, 6))                                    # 0.985294

adjusted = prices.where(prices.index >= ex_date, prices * factor)
print(adjusted.round(4).tolist())                          # [98.5294, 99.5147, 100.5, 100.8, 101.5, 102.5]
print(prices.pct_change().round(4).tolist()[3], adjusted.pct_change().round(4).tolist()[3])   # -0.0118 0.003
Ajustado para rendimientos, en bruto para operarLos precios ajustados sirven para medir rendimientos y comparar en el tiempo. No son lo que pagas: una orden se coloca al precio en bruto cotizado ese día, y un precio ajustado antiguo puede ser inferior al precio real al que cotizaba la acción. Conserva ambas columnas (close y adj_close) e indica cuál usa cada cálculo.
  • Un split divide los precios antiguos por la razón y multiplica los volúmenes antiguos por ella; solo cambian los días anteriores al split.
  • Un dividendo multiplica los precios anteriores a la fecha ex por 1 - dividendo / cierre anterior.
  • Usa where(index >= date, ajustado) con una máscara, no un bucle; calcula rendimientos con precios ajustados y opera con los brutos.

A continuación: los gráficos de líneas con matplotlib, para dibujar la serie de precios limpia que ya tienes.

Lab: qué se califica

  • Hacer comparables los precios a través de un split con adjust_for_split25 pts
  • Escalar los volúmenes antiguos con adjust_volume_for_split25 pts
  • Calcular el factor de ajuste de un dividendo con dividend_factor25 pts
  • Quitar la caída por dividendo del historial con adjust_for_dividend25 pts
Explorador · lab-50-1
▾ lab-50-1
…
bash · en el navegador
learner@quantcraft:~/lab-50-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-50-1 vuelve a los archivos iniciales y se limpia el terminal. Tu solución actual se perderá: no se puede deshacer.

Se restablecerá
  • main.py → código inicial
  • Historial del terminal y salida de pruebas
  • Cambios sin enviar
Se conservará
  • Mejor puntuación del lab
  • Tu XP y tu racha
  • Progreso de la lección y notas

Inicia sesión para ejecutar tu código.

Todas las clases se pueden leer gratis. Crea una cuenta o inicia sesión para ejecutar código, lanzar las pruebas y enviar este lab.

  • IDE en el navegador con terminal bash — sin instalar nada
  • Corrección instantánea, XP y tu lugar en la ruta
Crear una cuentaIniciar sesión
O
Continuar con GitHub