Mayor ganancia y pérdida diaria: guía técnica con Python y SQL
Cómo identificar la mayor variación diaria en series de precios con herramientas reales
Por Jose Luis Rueda · 11 min lectura · 2026-07-25
Todo analista de datos o trader se ha hecho esta pregunta en algún momento: ¿cuál fue el día de mayor ganancia para un activo? Y lo contrario: ¿cuándo ocurrió la peor pérdida? Encontrar esos extremos no es solo curiosidad estadística. Sirve para medir la volatilidad, calibrar estrategias de riesgo y detectar eventos anómalos en series temporales financieras.
Este artículo te entrega una solución completa, desde el concepto hasta el código, para calcular el mayor retorno diario positivo y negativo sobre un conjunto de precios históricos. Usaremos Python con pandas, SQL con funciones ventana y mostraremos ejemplos con datos reales de acciones y criptomonedas.
La guía está pensada para profesionales que ya trabajan con datos, pero quieren un método directo y productivo. Si al final quieres automatizar todo el proceso, una plataforma como HolaGPT puede asistirte en la generación de consultas y scripts adaptados a tu stack.
1. Qué significa “mayor ganancia y pérdida en un solo día”
Antes de escribir código hay que definir el concepto. La ganancia o pérdida diaria se refiere a la variación del precio de cierre de un activo entre dos días consecutivos. Se puede expresar en términos absolutos (diferencia en dólares, euros o pesos) o en términos porcentuales. Casi siempre el porcentaje es más útil porque permite comparar activos con distinto valor nominal.
La fórmula del retorno diario simple es:
retorno = (precio_hoy - precio_ayer) / precio_ayerMultiplicado por 100 da el porcentaje. El retorno logarítmico, común en finanzas cuantitativas, usa ln(precio_hoy / precio_ayer). Para este análisis nos quedamos con el retorno simple, más intuitivo para la mayoría de los profesionales.
El objetivo es escanear toda la serie de precios (que puede tener miles de días) y extraer dos números: el retorno porcentual máximo positivo (la mayor ganancia en un día) y el retorno porcentual mínimo (la mayor pérdida, que será el número más negativo). También interesa conocer la fecha exacta en que sucedió cada uno, porque el contexto histórico importa.
2. Datos necesarios y su preparación
Para ejecutar el cálculo se necesita una tabla con al menos dos columnas: fecha y precio de cierre. Si trabajas con acciones, el precio ajustado por splits y dividendos es obligatorio; de lo contrario, un split de 2 por 1 falsearía el retorno. Las fuentes típicas son:
- Yahoo Finance (con yfinance en Python)
- Alpha Vantage, Polygon, IEX Cloud
- Bases de datos internas de la empresa
- Archivos CSV de proveedores de datos de mercado
Asegúrate de que los datos estén ordenados por fecha ascendente y sin duplicados. Los días no bursátiles (fines de semana, festivos) simplemente no aparecen; eso no afecta el cálculo porque el retorno se mide entre días consecutivos de negociación.
Ejemplo de carga de datos con pandas desde un CSV:
import pandas as pd
df = pd.read_csv('precios.csv', parse_dates=['fecha'])
df = df.sort_values('fecha')
df['retorno'] = df['cierre'].pct_change()El método pct_change() de pandas calcula exactamente la fórmula del retorno simple para toda la columna de golpe. La primera fila queda con NaN porque no hay día anterior.
3. Cálculo en Python con pandas
El flujo es directo. Supongamos que ya tenemos el DataFrame df con columnas fecha, cierre y la columna retorno recién creada.
3.1 Encontrar el máximo y mínimo
# Fila con mayor ganancia
max_gan = df.loc[df['retorno'].idxmax()]
# Fila con mayor pérdida (retorno más negativo)
max_per = df.loc[df['retorno'].idxmin()]
print(f"Mayor ganancia: {max_gan['fecha'].date()} con {max_gan['retorno']:.2%}")
print(f"Mayor pérdida: {max_per['fecha'].date()} con {max_per['retorno']:.2%}")El resultado entrega fecha y retorno en porcentaje. Como idxmax() devuelve el índice de la primera ocurrencia del máximo, si hay empates (dos días con igual retorno) tomará el primero cronológicamente por el orden del DataFrame.
3.2 Agregar contexto visual
Un análisis decente incluye un gráfico que muestre la serie de retornos y destaque los extremos. Con matplotlib:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12,5))
ax.plot(df['fecha'], df['retorno'], linewidth=0.5, color='gray')
ax.scatter(max_gan['fecha'], max_gan['retorno'], color='green', s=100, label='Máx. ganancia')
ax.scatter(max_per['fecha'], max_per['retorno'], color='red', s=100, label='Máx. pérdida')
ax.axhline(0, color='black', linewidth=0.5)
ax.set_title('Retornos diarios con extremos')
ax.legend()
plt.tight_layout()
plt.show()Este gráfico te permite ver si el día extremo fue un outlier aislado o si hubo periodos de alta volatilidad alrededor. La visualización es clave para comunicar hallazgos a equipos no técnicos.
4. Cálculo en SQL
Muchas organizaciones guardan los precios históricos en bases de datos relacionales. Extraer la mayor ganancia y pérdida diaria con SQL es eficiente si se usan funciones ventana.
4.1 Tabla de ejemplo
Imagina una tabla precios con columnas activo_id, fecha, cierre_ajustado. Necesitamos el retorno entre la fila actual y la anterior para cada activo. En SQL estándar (PostgreSQL, MySQL 8.0+, SQL Server, Oracle):
WITH retornos AS (
SELECT
activo_id,
fecha,
cierre_ajustado,
(cierre_ajustado / LAG(cierre_ajustado) OVER (
PARTITION BY activo_id ORDER BY fecha
) - 1) AS retorno
FROM precios
)
SELECT
activo_id,
MAX(retorno) AS mayor_ganancia,
MIN(retorno) AS mayor_perdida
FROM retornos
GROUP BY activo_id;Si además quieres las fechas, puedes usar ROW_NUMBER() o una subconsulta con ORDER BY retorno DESC LIMIT 1 por activo. El enfoque con CTE y LAG es limpio y corre en una sola pasada sobre los datos ordenados.
4.2 Consideraciones de rendimiento
Para tablas con cientos de millones de filas, asegúrate de tener un índice en (activo_id, fecha). La función ventana escaneará secuencialmente por partición, y el orden correcto es indispensable. Si trabajas con BigQuery o Redshift, la sintaxis es similar, aunque puede haber pequeñas variaciones en el manejo de nulos.
5. Interpretar los resultados: más allá del número
Encontrar que la mayor ganancia de Tesla fue un +19.64 % el 3 de febrero de 2020 (dato real) o que la mayor pérdida del S&P 500 fue un -11.98 % el 16 de marzo de 2020, es solo el punto de partida. Esos números se explican por eventos: anuncios de resultados, decisiones de la Fed, crisis sanitarias. La interpretación correcta vincula el dato con el contexto macro y la microestructura del mercado.
Un error común es usar precios no ajustados. Si miras Apple y ves un salto “milagroso”, casi seguro es un split. Siempre trabaja con precios ajustados. Otro escollo es no filtrar días con volumen cero o errores de datos; un precio mal registrado puede generar un retorno espurio. Vale la pena agregar una validación rápida: si el retorno absoluto supera un umbral (ej. 50 %), revisa manualmente la fuente.
En carteras de inversión, la mayor pérdida diaria de cada activo te ayuda a estimar el Value at Risk (VaR) histórico y a definir stops loss. Para análisis de riesgo sistémico, los días de caída extrema coinciden en múltiples activos; detectarlos te permite preparar coberturas.
6. Casos prácticos con datos reales
Para aterrizar los conceptos, tomemos dos ejemplos: una acción tecnológica (Apple, ticker AAPL) y una criptomoneda (Bitcoin, BTC-USD). Usaremos yfinance para bajar datos desde Yahoo Finance de forma gratuita.
6.1 Apple (AAPL)
import yfinance as yf
aapl = yf.download('AAPL', start='2010-01-01', end='2024-12-31')
aapl['retorno'] = aapl['Adj Close'].pct_change()
max_gan = aapl.loc[aapl['retorno'].idxmax()]
max_per = aapl.loc[aapl['retorno'].idxmin()]El resultado para el periodo muestra la mayor ganancia cerca del 10 % en un solo día (durante la pandemia) y la mayor pérdida en torno al -12 % en marzo de 2020. Estas cifras reflejan la alta volatilidad del mercado tecnológico en esa época.
6.2 Bitcoin (BTC-USD)
Bitcoin opera 24/7, por lo que sus retornos diarios se calculan sobre el cierre UTC. Con datos desde 2015:
btc = yf.download('BTC-USD', start='2015-01-01')
btc['retorno'] = btc['Adj Close'].pct_change()Los extremos son mucho más amplios: ganancias superiores al 20 % en un día no son raras, y pérdidas de hasta el 30-40 % han ocurrido. Esto ilustra por qué las métricas de riesgo clásicas a veces fallan con criptoactivos.
El código es exactamente el mismo; la diferencia está en la interpretación. Para un equipo de cumplimiento, estos números son vitales para establecer límites de exposición.
7. Errores frecuentes al calcular extremos diarios
- No ordenar los datos:
pct_change()yLAGdependen del orden. Si las fechas están desordenadas, obtienes basura. Siempre ordena por fecha ascendente. - Ignorar nulos:
idxmax()eidxmin()ignoran NaN en pandas, pero en SQL debes filtrarWHERE retorno IS NOT NULLen la consulta final; de lo contrario, el MIN o MAX puede devolver NULL. - Confundir precio de cierre con precio ajustado: Ya lo dijimos, pero se repite: el precio ajustado es el que incorpora dividendos y splits. Sin él, los retornos están distorsionados.
- No validar datos: Un pico por error de carga puede aparecer como la mayor ganancia. Añade una regla de alerta si el retorno supera 3 desviaciones estándar o un umbral absoluto.
- Usar el retorno aritmético para periodos largos: Para un solo día no hay problema, pero si luego encadenas retornos para calcular rendimientos acumulados, el retorno logarítmico es más preciso.
8. Automatización y monitoreo continuo
Identificar el mayor movimiento diario es útil, pero en trading y gestión de riesgos necesitas saber si el día de hoy es el peor o el mejor desde que empezó el año, o si se acerca a los extremos históricos. Eso pide un cálculo incremental.
Puedes programar un script en Python (con Apache Airflow, cron o un job en la nube) que cada noche descargue los nuevos precios, calcule el retorno del día y lo compare con el máximo y mínimo guardados hasta la fecha. Si hay récord, envía una notificación por Slack o correo. La lógica es trivial: mantenemos en un archivo o base de datos el valor récord y su fecha; al final del día, comparamos y actualizamos si se rompe.
Para equipos que usan dashboards (Tableau, Power BI, Grafana), una tabla con los extremos históricos y los movimientos recientes sirve para monitorear anomalías en tiempo real. Una consulta SQL sencilla que devuelva los últimos 30 días junto con las marcas de máximo/mínimo histórico permite al analista ver si el mercado está excepcionalmente volátil.
9. Cuándo el dato diario no es suficiente
En mercados extremadamente líquidos, como el forex durante anuncios de tipos de interés, el movimiento intradía puede ser mucho mayor que el cierre a cierre. En esos casos, la mayor ganancia y pérdida diaria medida con precios de cierre subestima el riesgo real. Si tu estrategia opera intradía, debes trabajar con datos tick a tick o barras de minutos. El concepto es el mismo: calcular el retorno entre periodos consecutivos y buscar máximos y mínimos. La complejidad crece por el volumen de datos, pero la lógica es la misma.
También hay que considerar eventos overnight. Un gap de apertura puede implicar una pérdida para un inversor apalancado aunque el cierre diario no lo refleje. En esos escenarios, conviene medir el retorno de cierre a apertura y de apertura a cierre por separado, y buscar máximos en cada segmento.
10. Conclusión y siguientes pasos
Calcular la mayor ganancia y pérdida diaria es uno de esos ejercicios que todo analista debe tener en su caja de herramientas. Con menos de diez líneas de Python o una CTE en SQL resuelves el problema técnico. La verdadera inteligencia está en elegir los datos adecuados, validarlos y leer los resultados con criterio financiero.
Te animo a replicar los ejemplos con tus propios activos de interés. Si trabajas en un equipo de datos, este flujo puede integrarse en pipelines más grandes de monitoreo de riesgos o de reporting automático. Y si necesitas acelerar la construcción de consultas o scripts, herramientas como HolaGPT te pueden asistir con plantillas y generación de código contextualizado, especialmente útil cuando combinas múltiples fuentes de datos o quieres personalizar el análisis por sector.