σμ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.9·~40 minPrincipiante

Combinar y unir tablas

Posición en la rutaMódulo 2 de 11 · Tema 9 de 20
2.9 Combinar y unir tablas
—Puntuación del lab— / 100XP total—Racha—

Tablas que comparten una clave

Los datos reales rara vez llegan en una sola tabla. Tus posiciones están en una, el sector de cada símbolo en otra, los precios en una tercera. Lo que las conecta es una clave, aquí el símbolo. left.merge(right, on="clave") encuentra, para cada fila de left, las filas de right con la misma clave y las pone una al lado de otra. Es la misma idea que un join en SQL.

import pandas as pd

positions = pd.DataFrame({"symbol": ["AAPL", "MSFT", "TSLA", "GOOG"], "qty": [100, 50, 20, 10]})
reference = pd.DataFrame({"symbol": ["AAPL", "MSFT", "GOOG", "F"], "sector": ["tech", "tech", "tech", "auto"]})

merged = positions.merge(reference, on="symbol")
print(merged)
#   symbol  qty sector
# 0   AAPL  100   tech
# 1   MSFT   50   tech
# 2   GOOG   10   tech

inner, left, right y outer

TSLA desapareció del resultado anterior, y F también. El valor por defecto, how="inner", conserva solo las claves presentes en ambas tablas. Indica lo que quieres: how="left" conserva todas las filas de la tabla izquierda y rellena con NaN los valores que faltan a la derecha, how="right" hace lo contrario y how="outer" conserva las claves de ambas. Para enriquecer una tabla casi siempre quieres left, porque nunca pierde una fila en silencio.

# how="left" keeps every position; TSLA has no sector, so it gets NaN
left = positions.merge(reference, on="symbol", how="left")
print(left)
#   symbol  qty sector
# 0   AAPL  100   tech
# 1   MSFT   50   tech
# 2   TSLA   20    NaN
# 3   GOOG   10   tech

# how="outer" keeps the keys of both tables (sorted); quantities become floats because of the NaN
print(positions.merge(reference, on="symbol", how="outer"))
#   symbol    qty sector
# 0   AAPL  100.0   tech
# 1      F    NaN   auto
# 2   GOOG   10.0   tech
# 3   MSFT   50.0   tech
# 4   TSLA   20.0    NaN

Encontrar lo que no coincide

Un NaN silencioso puede esconder un problema de datos, así que compruébalo. indicator=True añade una columna _merge que indica, para cada fila, si la clave se encontró en left_only, right_only o both. Filtrarla responde a preguntas como «¿qué posiciones no tienen precio?». Las claves duplicadas son la otra trampa: si una clave aparece dos veces a la derecha, cada fila coincidente de la izquierda se repite. Pasa validate="many_to_one" (o "one_to_one") y pandas lanza un error en vez de cambiar en silencio el número de filas.

# Which positions have no sector?
check = positions.merge(reference, on="symbol", how="left", indicator=True)
print(check)
#   symbol  qty sector     _merge
# 0   AAPL  100   tech       both
# 1   MSFT   50   tech       both
# 2   TSLA   20    NaN  left_only
# 3   GOOG   10   tech       both

print(check.loc[check["_merge"] == "left_only", "symbol"].tolist())   # ['TSLA']
# Duplicate keys repeat rows: AAPL has two quotes, so the AAPL position appears twice
quotes = pd.DataFrame({"symbol": ["AAPL", "AAPL", "MSFT"], "price": [184.25, 184.5, 410.1]})
print(len(positions.merge(quotes, on="symbol")))   # 3

# validate turns the surprise into an error
try:
    positions.merge(quotes, on="symbol", validate="one_to_one")
except Exception as error:
    print(type(error).__name__)   # MergeError

Claves con nombres distintos y columnas en conflicto

Cuando la clave tiene nombres distintos en las dos tablas, usa left_on="symbol", right_on="ticker"; se conservan ambas columnas. Cuando las dos tablas tienen una columna con el mismo nombre que no es la clave (aquí qty), pandas conserva las dos y añade los sufijos _x y _y. Elige otros más claros con suffixes=("_a", "_b"). Tras un outer join las cantidades que faltan son NaN y la columna es de coma flotante: usa fillna(0) y luego astype("int64") para recuperar enteros.

# Different key names: both columns are kept
book_a = pd.DataFrame({"symbol": ["AAPL", "MSFT"], "qty": [100, 50]})
book_b = pd.DataFrame({"ticker": ["MSFT", "TSLA"], "qty": [-20, 30]})
print(book_a.merge(book_b, left_on="symbol", right_on="ticker", how="outer", suffixes=("_a", "_b")))
#   symbol  qty_a ticker  qty_b
# 0   AAPL  100.0    NaN    NaN
# 1   MSFT   50.0   MSFT  -20.0
# 2    NaN    NaN   TSLA   30.0

# Same key name, outer join, suffixes, then back to whole numbers
both = book_a.merge(book_b.rename(columns={"ticker": "symbol"}), on="symbol", how="outer", suffixes=("_a", "_b"))
both[["qty_a", "qty_b"]] = both[["qty_a", "qty_b"]].fillna(0).astype("int64")
print(both)
#   symbol  qty_a  qty_b
# 0   AAPL    100      0
# 1   MSFT     50    -20
# 2   TSLA      0     30
Cuenta las filas después de cada mergeUn merge que pierde o repite filas en silencio estropea todo lo que sigue, sin que ningún error avise. Compara len() antes y después, usa how="left" cuando quieras conservar todas las filas y añade validate= cuando creas que las claves son únicas.
  • left.merge(right, on="clave") empareja filas de dos tablas que comparten una clave; left_on / right_on gestionan nombres distintos.
  • how="inner" (por defecto) conserva las claves de ambas, "left" todas las filas de la izquierda, "outer" todas las claves.
  • indicator=True muestra lo que no coincide; validate= y suffixes= protegen de claves duplicadas y nombres en conflicto.

A continuación: los rendimientos simples, que convierten una serie de precios en el cambio porcentual de un periodo al siguiente.

Lab: qué se califica

  • Añadir el sector de cada operación con attach_sector25 pts
  • Valorar las posiciones que tienen precio con value_positions25 pts
  • Encontrar las posiciones sin precio con unpriced_symbols25 pts
  • Unir dos libros en una sola tabla con combine_books25 pts
Explorador · lab-42-1
▾ lab-42-1
…
bash · en el navegador
learner@quantcraft:~/lab-42-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

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