σμ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.15·~40 minIntermedio

Manejo de datos faltantes

Posición en la rutaMódulo 2 de 11 · Tema 15 de 20
2.15 Manejo de datos faltantes
—Puntuación del lab— / 100XP total—Racha—

Huecos en los datos

Las tablas de precios reales tienen huecos: una acción no cotizó ese día, un feed perdió una cotización, un mercado estaba de fiesta. pandas los marca como NaN («not a number»). Antes de decidir qué hacer, mira: df.isna() da una tabla de Verdadero/Falso, .sum() cuenta los huecos por columna y .mean() da su proporción. Una columna vacía al 40 % es un problema distinto de una a la que le falta un solo valor.

import pandas as pd

nan = float("nan")
df = pd.DataFrame(
    {"AAPL": [184.0, nan, 186.5, 187.0, nan], "MSFT": [410.0, 411.0, nan, nan, 415.0]},
    index=pd.bdate_range("2026-03-02", periods=5),
)

print(df.isna().sum().to_dict())           # {'AAPL': 2, 'MSFT': 2}   holes per column
print(df.isna().mean().round(2).to_dict())   # {'AAPL': 0.4, 'MSFT': 0.4}   share of holes

Arrastrar o eliminar

Para los precios, el relleno natural es el último precio conocido: hasta que llega una cotización nueva, el mercado sigue en la antigua. Eso es ffill() (relleno hacia delante). Un hueco largo probablemente significa datos obsoletos, así que ffill(limit=2) rellena como máximo dos días seguidos. Los NaN del mismo comienzo siguen siendo NaN, porque no hay precio anterior que arrastrar. La alternativa es eliminar: dropna() quita toda fila con un hueco, y dropna(subset=["AAPL"]) solo mira las columnas que te importan. Eliminar es seguro, pero reduce los datos y cambia el espaciado entre fechas.

msft = df["MSFT"]
print(msft.ffill().tolist())           # [410.0, 411.0, 411.0, 411.0, 415.0]
print(msft.ffill(limit=1).tolist())    # [410.0, 411.0, 411.0, nan, 415.0]   only one day carried

print(len(df.dropna()))                          # 1   only one row is complete
print(len(df.dropna(subset=["AAPL"])))           # 3   rows where AAPL is known

Interpolación, y lo que nunca se debe rellenar

interpolate() rellena un hueco con una recta entre los valores conocidos a ambos lados. Sirve para magnitudes suaves (una curva de tipos, un nivel de volatilidad) y rara vez para precios, que saltan. Cuidado en los bordes: por defecto interpolate() también copia el último valor en los NaN finales, lo que inventa datos. limit_area="inside" lo restringe a huecos entre dos valores conocidos. Nunca rellenes a ciegas con 0: un precio de 0 es un desplome, un rendimiento de 0 es un día plano, y fillna(0) en la tabla equivocada cambia en silencio todas las medias que calcules después.

gappy = pd.Series([nan, nan, 10.0, nan, nan, 16.0, nan])

print(gappy.interpolate().tolist())
# [nan, nan, 10.0, 12.0, 14.0, 16.0, 16.0]   the last 16.0 is invented

print(gappy.interpolate(limit_area="inside").tolist())
# [nan, nan, 10.0, 12.0, 14.0, 16.0, nan]    only between known values
# Filling with 0 is a decision, not a default: it changes the statistics
print(gappy.fillna(0).tolist())   # [0.0, 0.0, 10.0, 0.0, 0.0, 16.0, 0.0]
print(gappy.mean())                # 13.0   NaN are skipped
print(gappy.fillna(0).mean())      # 3.7142857142857144   the zeros drag the average down
Rellena con el pasado, nunca con el futurobfill() e interpolate() usan valores posteriores al hueco, así que en la fecha del hueco emplean información que aún no existía. En un backtest eso es sesgo de anticipación. Usa ffill() para todo lo que una estrategia ve en tiempo real y reserva la interpolación para limpiar datos históricos que se analizan en conjunto.
  • df.isna().sum() cuenta los huecos por columna; mira los datos antes de decidir cómo tratarlos.
  • ffill(limit=n) arrastra el último valor conocido (la opción correcta para precios); dropna(subset=...) quita las filas incompletas.
  • interpolate(limit_area="inside") solo salva los huecos interiores; nunca rellenes con 0 ni con el futuro por costumbre.

A continuación: la detección de valores atípicos, encontrar los valores presentes que no pueden ser correctos.

Lab: qué se califica

  • Contar los huecos de cada columna con count_missing25 pts
  • Arrastrar el último precio con forward_fill25 pts
  • Conservar solo las filas fiables con complete_rows25 pts
  • Rellenar los huecos dentro de los datos con fill_gaps25 pts
Explorador · lab-48-1
▾ lab-48-1
…
bash · en el navegador
learner@quantcraft:~/lab-48-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-48-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