GaiaEx AcademyGaiaEx Academy
Análisis de datos con Pandas, NumPy y Matplotlib
DesarrolladorProgramación12 min read

Análisis de datos con Pandas, NumPy y Matplotlib

Limpia, transforma y visualiza datos financieros como un quant

Compartir Publicaciones

NumPy: el motor bajo el capó

Todo cálculo financiero serio en Python termina pasando por NumPy. Las listas de Python son flexibles, pero lentas —cada elemento es un objeto completo de Python con la sobrecarga del chequeo de tipos. Los arrays de NumPy almacenan números en bloques de memoria contiguos, lo que permite operaciones 100 veces más rápidas que los bucles en Python puro.

Esta es la diferencia en la práctica:

import numpy as np

# Crear un array de 1 millón de rendimientos diarios aleatorios
returns = np.random.normal(0.0005, 0.02, 1_000_000)

# Operaciones vectorizadas — sin bucles
cumulative = np.cumprod(1 + returns)  # Crecimiento de $1
sharpe = returns.mean() / returns.std() * np.sqrt(252)
max_drawdown = np.min(cumulative / np.maximum.accumulate(cumulative) - 1)

print(f"Sharpe Ratio: {sharpe:.3f}")
print(f"Max Drawdown: {max_drawdown:.2%}")

Conceptos clave de NumPy para finanzas:

  • Operaciones vectorizadas — Aplican una operación matemática a arrays enteros de golpe en lugar de recorrer elemento por elemento.
  • Broadcasting — Alinean automáticamente arrays de formas distintas para hacer aritmética (por ejemplo, restar una media escalar a cada elemento).
  • Álgebra linealnp.linalg ofrece multiplicación de matrices, descomposición en valores propios y solvers usados en la optimización de carteras.
  • Muestreo aleatorio — Las simulaciones de Monte Carlo, el muestreo bootstrap y el modelado estocástico dependen de np.random.

Consejo de rendimiento: prefiere siempre las operaciones vectorizadas de NumPy frente a los bucles for de Python. Una optimización de cartera sobre 500 activos que tarda 30 segundos con bucles puede terminar en menos de 50 milisegundos con NumPy vectorizado —una mejora de 600 veces.

NumPy: memoria contigua + operaciones vectorizadas ndarray — dtype, shape, strides (contiguo en C) un bucle en C/Fortran, no un millón de pasos de bytecode de Python broadcasting: alinear formas para operaciones elemento a elemento p. ej. vector de rendimientos − media escalar, o (n,) con filas de una matriz (n, m) linalg: cov, eig, solve — aquí vive el cálculo de carteras
Los arrays son el camino rápido; el broadcasting es cómo mantienes el código legible sin bucles.

Pandas: DataFrames para datos financieros

Si NumPy es el motor, pandas es el salpicadero. Envuelve los arrays de NumPy en estructuras etiquetadas e indexadas que hacen que manipular datos financieros sea intuitivo y expresivo.

Las dos estructuras centrales son:

  • Series — Una sola columna de datos con un índice (piensa: una serie temporal de precios de cierre).
  • DataFrame — Una tabla de columnas, cada una una Series, que comparten un índice común (piensa: datos de velas OHLCV).

Cargar e inspeccionar datos es sencillo:

import pandas as pd

# Leer desde CSV
df = pd.read_csv("btc_daily.csv", parse_dates=["date"], index_col="date")

# O desde JSON (habitual en respuestas de API)
df = pd.read_json("https://api.example.com/candles?symbol=ETH")

# Inspección rápida
print(df.shape)          # (365, 5)
print(df.dtypes)         # Tipos de columna
print(df.describe())     # Resumen estadístico
print(df.tail())         # Últimas 5 filas

Lo que hace a pandas imprescindible en finanzas es su DatetimeIndex. Una vez que tu índice es de tipo fecha/hora, desbloqueas operaciones potentes de series temporales:

# Recortar por rango de fechas
q1_data = df["2025-01":"2025-03"]

# Reagrupar datos diarios en OHLC semanal
weekly = df["close"].resample("W").ohlc()

# Relleno hacia delante de datos ausentes (fines de semana, festivos)
df = df.asfreq("D").ffill()

Estas operaciones gestionan las realidades desordenadas de los datos financieros —huecos, diferencias de zona horaria, marcas de tiempo irregulares— para que puedas centrarte en el análisis en lugar de en la fontanería de los datos.

Cálculos rolling: medias móviles y volatilidad

El análisis financiero es intrínsecamente por ventanas. Rara vez te interesa un único dato en aislamiento —el contexto viene de cómo se relaciona con la historia reciente. El método .rolling() de pandas es tu herramienta principal aquí.

import pandas as pd
import numpy as np

# Suponemos que df tiene una columna "close" con DatetimeIndex
df["sma_20"] = df["close"].rolling(20).mean()
df["sma_50"] = df["close"].rolling(50).mean()
df["ema_12"] = df["close"].ewm(span=12).mean()

# Rendimientos diarios y volatilidad rolling
df["returns"] = df["close"].pct_change()
df["vol_30d"] = df["returns"].rolling(30).std() * np.sqrt(365)

# Bandas de Bollinger
df["bb_upper"] = df["sma_20"] + 2 * df["close"].rolling(20).std()
df["bb_lower"] = df["sma_20"] - 2 * df["close"].rolling(20).std()

# Correlación rolling entre dos activos
df["corr_btc_eth"] = df["btc_returns"].rolling(60).corr(df["eth_returns"])

Cálculos rolling clave que todo trader debería conocer:

  • Media móvil simple (SMA) — Media con igual peso sobre N periodos. Rezagada pero estable.
  • Media móvil exponencial (EMA) — Pondera más los datos recientes mediante .ewm(). Más sensible a los cambios de precio.
  • Volatilidad rolling — Desviación típica de los rendimientos sobre una ventana, anualizada. Esencial para el dimensionamiento de posiciones y los presupuestos de riesgo.
  • Correlación rolling — Mide cómo se mueven juntos dos activos a lo largo del tiempo. Crítica para la diversificación de carteras.

En plataformas como GaiaEx, puedes obtener datos históricos de velas a través de la API de trading, cargarlos en un DataFrame de pandas y calcular estos indicadores en segundos —todo mientras tus activos permanecen seguros en tu monedero MPC.

GroupBy y agregación para el análisis de carteras

Cuando gestionas varios activos, .groupby() se vuelve esencial. Te permite dividir los datos por categoría, aplicar cálculos y combinar resultados —el patrón split-apply-combine.

# DataFrame con varios activos
trades = pd.DataFrame({
    "symbol": ["BTC", "ETH", "BTC", "SOL", "ETH", "BTC"],
    "side": ["buy", "buy", "sell", "buy", "sell", "buy"],
    "pnl": [120.5, -45.2, 89.0, 210.3, 55.8, -30.1],
    "volume": [5000, 3200, 4800, 1500, 2900, 5100],
})

# Rendimiento por activo
summary = trades.groupby("symbol").agg(
    total_pnl=("pnl", "sum"),
    avg_pnl=("pnl", "mean"),
    trade_count=("pnl", "count"),
    total_volume=("volume", "sum"),
    win_rate=("pnl", lambda x: (x > 0).mean()),
)

print(summary.sort_values("total_pnl", ascending=False))

Patrones de agregación avanzados para el trabajo con carteras:

  • GroupBy multinivel — Agrupa por símbolo y lado para ver el rendimiento de largos frente a cortos por activo.
  • Funciones de agregación personalizadas — Calcula el ratio de Sharpe, el ratio de Sortino o el drawdown máximo por grupo de activos.
  • Tablas pivote — Reorganiza los datos para ver los rendimientos mensuales por activo en un formato apto para mapas de calor usando pd.pivot_table().
  • Reagrupación (resampling) con groupby — Combina la reagrupación temporal con el agrupamiento categórico para el análisis de series temporales multiactivo.

Matplotlib: graficar la acción del precio y las señales

Los datos sin visualización son solo números. Matplotlib transforma tu análisis en gráficos que revelan patrones invisibles en los datos brutos.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

fig, axes = plt.subplots(3, 1, figsize=(14, 10),
                         sharex=True, gridspec_kw={"height_ratios": [3, 1, 1]})

# Precio + medias móviles
axes[0].plot(df.index, df["close"], label="Close", linewidth=1.2)
axes[0].plot(df.index, df["sma_20"], label="SMA 20", linestyle="--")
axes[0].fill_between(df.index, df["bb_upper"], df["bb_lower"],
                     alpha=0.1, color="blue", label="Bollinger Bands")
axes[0].set_ylabel("Price (USD)")
axes[0].legend(loc="upper left")

# Barras de volumen
colors = ["green" if c > o else "red"
          for c, o in zip(df["close"], df["open"])]
axes[1].bar(df.index, df["volume"], color=colors, alpha=0.7)
axes[1].set_ylabel("Volume")

# Volatilidad rolling
axes[2].plot(df.index, df["vol_30d"], color="purple")
axes[2].set_ylabel("30d Volatility")
axes[2].axhline(y=0.8, color="red", linestyle=":", alpha=0.5)

axes[2].xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))
plt.tight_layout()
plt.savefig("analysis_dashboard.png", dpi=150)
plt.show()

Esto produce un panel profesional de tres secciones: la acción del precio con Bandas de Bollinger arriba, el volumen en el medio y la volatilidad abajo. Este diseño es similar al que verías en terminales de trading profesionales.

Para la visualización estadística, seaborn se construye sobre Matplotlib con funciones de más alto nivel:

import seaborn as sns

# Distribución de rendimientos
sns.histplot(df["returns"].dropna(), bins=100, kde=True)

# Mapa de calor de correlación entre activos
corr_matrix = portfolio_returns.corr()
sns.heatmap(corr_matrix, annot=True, cmap="RdYlGn", center=0)
Pandas → análisis; Matplotlib → interpretación DataFrame índice + columnas rolling resample groupby Métricas de Series rendimientos, vol, Sharpe matplotlib.pyplot — figure, axes, artists precio volumen indicadores seaborn opcional — misma capa Artist, valores por defecto más bonitos
Pandas prepara tablas ordenadas; Matplotlib las mapea a ejes que puedes anotar y compartir.

Uniéndolo todo: un pipeline de análisis completo

El verdadero poder surge cuando encadenas estas herramientas en un pipeline repetible. Este es un flujo de trabajo que los quants profesionales usan a diario:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def analyze_asset(symbol: str, df: pd.DataFrame) -> dict:
    """Pipeline de análisis completo para un solo activo."""
    df["returns"] = df["close"].pct_change()
    df["log_returns"] = np.log(df["close"] / df["close"].shift(1))

    return {
        "symbol": symbol,
        "total_return": (df["close"].iloc[-1] / df["close"].iloc[0]) - 1,
        "annual_vol": df["returns"].std() * np.sqrt(365),
        "sharpe": df["returns"].mean() / df["returns"].std() * np.sqrt(365),
        "max_drawdown": (df["close"] / df["close"].cummax() - 1).min(),
        "skewness": df["returns"].skew(),
        "kurtosis": df["returns"].kurtosis(),
    }

# Analizar varios activos
results = [analyze_asset(sym, data) for sym, data in assets.items()]
summary = pd.DataFrame(results).set_index("symbol")
print(summary.round(4))

Este pipeline toma datos de precio brutos y produce un perfil de riesgo-rendimiento completo para cada activo. A partir de aquí, puedes introducir estas métricas en un optimizador de carteras, generar recomendaciones de asignación o disparar señales de reequilibrio.

El conjunto pandas-NumPy-Matplotlib es la base sobre la que se construye todo lo demás en las finanzas con Python. Domina estas tres bibliotecas y tendrás las habilidades para analizar cualquier mercado, construir cualquier indicador y visualizar cualquier estrategia —ya sea que operes acciones en el NYSE, criptomonedas en GaiaEx, o derivados en el CME.