⚠ El trading implica un riesgo significativo de pérdida. Todo el contenido de este sitio es únicamente educativo y no constituye asesoramiento financiero.
Lección 4 de 13 · Gratis

Cargar datos de precios: archivos CSV y API gratuitas, precios ajustados frente a no ajustados, valores faltantes y zonas horarias

Lee archivos de precios y descargas de API en un DataFrame limpio, entiende cómo funcionan los ajustes por splits y dividendos, y gestiona correctamente los huecos y las zonas horarias.

Autor: Moustafa HijaziContenido revisado: 2026-10-307 min de lecturaCurso de autoaprendizaje

Qué aprenderás

  • Cómo leer un archivo CSV en un DataFrame con fechas correctas, y los argumentos que resuelven los problemas de importación habituales.
  • Qué te ofrecen las API de datos gratuitas, qué significan sus licencias y sus valores por defecto, y cómo guardar en caché las descargas.
  • Cómo se calculan los factores de ajuste por splits y dividendos y por qué un backtest necesita precios ajustados, pero una orden real necesita precios no ajustados.
  • Cómo encontrar y tratar los valores faltantes, y cómo asignar y convertir zonas horarias sin desplazar tus barras.

Explicación

Archivos CSV. Un archivo CSV (comma-separated values, valores separados por comas) es texto plano con una fila por barra. La llamada clave es:

df = pd.read_csv("data/raw/xyz.csv", parse_dates=["Date"], index_col="Date")

parse_dates convierte la columna de texto en marcas temporales e index_col la convierte en el índice. Soluciones habituales: sep=";" y decimal="," para exportaciones alemanas, dayfirst=True para fechas como 03.04.2025, y date_format="%d.%m.%Y" cuando el análisis de fechas falla. Tras cargar, ejecuta df = df.sort_index() (algunas exportaciones van de lo más reciente a lo más antiguo), comprueba df.index.is_unique y pasa los nombres de columna a minúsculas con df.columns = df.columns.str.lower().

API gratuitas. Una API (application programming interface, interfaz de programación de aplicaciones) permite que el código solicite datos a un servidor. Para un primer proyecto, la biblioteca yfinance (datos de Yahoo Finance) es la opción habitual: yf.download("SAP.DE", start="2015-01-01"); está pensada para la investigación personal y no se garantiza su exactitud. Un valor por defecto es importante: en 2026, auto_adjust=True, de modo que la apertura, el máximo, el mínimo y el cierre ya están ajustados por splits y dividendos y no hay columna «Adj Close»; con auto_adjust=False obtienes OHLC ajustado por splits más un «Adj Close» que también incluye los dividendos. Entre las alternativas con planes gratuitos están Stooq (descargas en CSV), Alpha Vantage y Tiingo (requieren registro y una clave de API, con límites estrictos de solicitudes); las condiciones cambian, así que consulta las vigentes, y la lección 12 trata la gestión de claves y los límites de solicitudes. Sea cual sea la fuente, guarda la descarga bruta una sola vez en data/raw/ (CSV o Parquet) y trabaja a partir del archivo; los proveedores revisan el historial y los límites son escasos.

Ajustados frente a no ajustados. El curso Trading sistemático y backtesting explicó por qué los splits y los dividendos distorsionan los backtests; aquí ves cómo funciona la corrección. En un split de n por 1, cada precio anterior se divide entre n (y el volumen se multiplica por n). En un dividendo en efectivo D cuya fecha ex-dividendo es el día t, el método estándar multiplica todos los precios anteriores al día t por el factor 1 − D ÷ C, donde C es el cierre del último día antes de la fecha ex-dividendo. Los ajustes se acumulan hacia atrás. Consecuencias: el historial ajustado cambia con cada nuevo dividendo, y las rentabilidades porcentuales son correctas, mientras que los niveles de precio en euros no lo son. Regla: haz el backtest con datos ajustados, coloca las órdenes reales a precios no ajustados y nunca mezcles ambos en un mismo cálculo.

Valores faltantes. pandas marca los huecos como NaN. Encuéntralos con df.isna().sum(). Rellenar hacia delante unos pocos huecos de precio con df["close"].ffill() es aceptable, pero nunca rellenes hacia delante el volumen, y nunca interpoles precios, porque la interpolación usa el valor futuro e introduce sesgo de anticipación (lección 7). En los demás casos, elimina las filas con df.dropna(subset=["close"]) y anota cuántas fueron. Ten en cuenta que la antigua sintaxis fillna(method="ffill") está obsoleta desde pandas 2.1 y no debe usarse en código nuevo; escribe .ffill().

Zonas horarias. Las barras diarias rara vez las necesitan; los datos intradía, siempre. tz_localize("Europe/Berlin") asigna una zona a un índice sin zona sin cambiar las horas; tz_convert("America/New_York") cambia las horas. Asignar por error la zona de Berlín a datos en UTC desplaza en silencio cada barra una o dos horas, así que consulta la documentación del proveedor. Las fechas de cambio al horario de verano difieren entre Europa y EE. UU., y es entonces cuando las marcas temporales mal gestionadas desalinean los instrumentos.

Ejemplo práctico

Ejemplo hipotético: una acción cierra a €50.00 el lunes. Un dividendo de €1.00 tiene su fecha ex-dividendo el martes, día en que la acción cierra a €49.50. Se ignoran comisiones e impuestos.

Factor de ajuste = 1 − 1.00 ÷ 50.00 = 0.98. Todos los precios anteriores al martes se multiplican por 0.98: el cierre del lunes pasa a ser 50 × 0.98 = €49.00; un cierre de €48.00 de la semana anterior pasa a ser 48 × 0.98 = €47.04.

Rentabilidad a través de la fecha ex-dividendo: sin ajustar, (49.50 − 50.00) ÷ 50.00 = −1.0%, que parece erróneamente una pérdida. Ajustada, (49.50 − 49.00) ÷ 49.00 = +1.02%, que refleja correctamente €1.00 de efectivo recibido frente a una pérdida de precio de €0.50 (neto +€0.50 sobre €50; la pequeña diferencia surge porque la base ajustada es €49).

Ahora un split de 2 por 1: cierres brutos de 100, 102 y 104 antes, y 52 y 53 después. Dividir entre 2 los precios anteriores al split da 50, 51, 52, 52, 53, una serie continua. Sin ello, pct_change() indica una rentabilidad del −50% el día del split, un desplome que nunca ocurrió.

Error frecuente

Fiarse de una descarga sin inspeccionarlaUn primer notebook típico descarga datos y ejecuta un backtest sin mirar nunca el DataFrame. Entre los problemas ocultos están el orden de fechas invertido, una última fila duplicada, volúmenes a cero, precios almacenados como texto y columnas ajustadas y no ajustadas mezcladas. Dedica primero dos minutos a info(), head(), tail(), isna().sum() y a un gráfico de líneas del cierre.

Actividad práctica

En papel: una acción tiene cierres de €90.00 y €93.00 en dos días, después un split de 3 por 1 y después cierres de €31.00 y €30.38 (hipotético). El día del cierre de €30.38 es la fecha ex-dividendo de un dividendo de €0.60, y el cierre anterior fue de €31.00. (a) Escribe los valores ajustados por el split de los dos cierres anteriores al split. (b) Calcula el factor de ajuste por dividendo y aplícalo a los tres cierres anteriores a la fecha ex-dividendo. (c) Indica la rentabilidad bruta y la totalmente ajustada desde el cierre de €31.00 hasta el cierre de €30.38.

Mostrar solución

(a) Divide entre 3: €90.00 → €30.00 y €93.00 → €31.00.

(b) Factor = 1 − 0.60 ÷ 31.00 = 0.98065 (redondeado). Aplicándolo: 30.00 × 0.98065 = €29.42; 31.00 × 0.98065 = €30.40; y el cierre de €31.00 anterior a la fecha ex-dividendo también pasa a €30.40. El cierre de €30.38 no cambia.

(c) Bruta: (30.38 − 31.00) ÷ 31.00 = −2.00%. Ajustada: (30.38 − 30.40) ÷ 30.40 = −0.07%, prácticamente plana: el precio cayó aproximadamente el importe del dividendo, así que el accionista no perdió casi nada en rentabilidad total.

Limitaciones: los proveedores redondean los factores de forma distinta y algunos usan otro precio de referencia; usa de forma coherente la serie ajustada de un único proveedor.

Ideas clave

  • Carga con parse_dates e index_col, después ordena, comprueba la unicidad y normaliza los nombres de columna.
  • Descarga una vez, guarda los datos brutos en local y lee la licencia de la API y sus valores de ajuste por defecto (yfinance: auto_adjust=True en 2026).
  • Factor de split 1 ÷ n, factor de dividendo 1 − D ÷ C, aplicados hacia atrás; haz el backtest con precios ajustados y opera con precios no ajustados.
  • Rellena hacia delante como mucho unos pocos huecos de precio, no interpoles nunca, no rellenes nunca el volumen hacia delante, y asigna la zona horaria una sola vez con la zona real del proveedor.

Siguiente paso

La lección 5 convierte los precios en rentabilidades: rentabilidades simples frente a logarítmicas, rentabilidades acumuladas, rentabilidad y volatilidad anualizadas, y ventanas móviles.

Autoevaluación

Responde a las preguntas y luego comprueba tus respuestas. Puedes volver a intentarlo tantas veces como quieras.

1. Una acción cierra a €80.00 y al día siguiente cotiza ex-dividendo de €2.00. Con el método estándar, ¿qué factor de ajuste por dividendo se aplica a los precios anteriores?

2. Tu serie de cierres diarios tiene tres valores NaN aislados en días de negociación normales. ¿Qué tratamiento es aceptable para un backtest?

3. Descargaste datos con yfinance usando sus valores por defecto de 2026 y quieres colocar una orden stop real basada en el mínimo de la semana pasada. ¿Qué deberías hacer?

Autoevaluación automática para tu propio repaso. Tus respuestas se comprueban en tu navegador y no las vemos ni evaluamos. No es un examen ni una titulación.

Tu progreso

«Completada» solo significa que marcaste la lección como terminada. No es una prueba de tu comprensión. El progreso y las notas se guardan solo en este navegador y en este dispositivo, no en una cuenta.