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 anyoneAjustar 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.003close 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