σμ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.11·~35 minIntermedio

Rendimientos logarítmicos

Posición en la rutaMódulo 2 de 11 · Tema 11 de 20
2.11 Rendimientos logarítmicos
—Puntuación del lab— / 100XP total—Racha—

El logaritmo del cociente de precios

Un rendimiento logarítmico es el logaritmo natural del cociente entre dos precios. En lugar de P_t / P_{t-1} - 1 se calcula ln(P_t / P_{t-1}). Para movimientos pequeños ambos son casi iguales (una subida del 2 % es 0,0198 en logaritmos), pero la versión logarítmica tiene propiedades que la hacen la elección estándar en estadística y modelado. En pandas, toma el logaritmo de toda la Series de precios con np.log y aplica diff: restar logaritmos es dividir precios.

r_t = ln(P_t / P_{t-1}) = ln(P_t) - ln(P_{t-1})
import numpy as np
import pandas as pd

prices = pd.Series([100.0, 102.0, 100.98, 103.0], index=["Mon", "Tue", "Wed", "Thu"])

log_ret = np.log(prices).diff()
print(log_ret.round(4))
# Mon       NaN
# Tue    0.0198
# Wed   -0.0101
# Thu    0.0198
# dtype: float64

print(prices.pct_change().round(4).tolist())   # [nan, 0.02, -0.01, 0.02]   the simple returns, for comparison

Los rendimientos logarítmicos se suman en el tiempo

Esta es la razón principal para usarlos. Como ln(a) - ln(c) = (ln(a) - ln(b)) + (ln(b) - ln(c)), el rendimiento logarítmico de varios periodos es simplemente la suma de los rendimientos por periodo, sin composición. El rendimiento de dos días es la suma de dos diarios, el mensual es la suma de los diarios, y exp(total) - 1 devuelve el resultado a un rendimiento simple. Los rendimientos logarítmicos también son simétricos: un precio que se duplica y luego se reduce a la mitad tiene rendimientos logarítmicos de +0,6931 y -0,6931, que se anulan, mientras que los simples eran +100 % y -50 %.

# The sum of the daily log returns is the log return over the whole period
print(round(log_ret.sum(), 6))                         # 0.029559
print(round(np.log(prices.iloc[-1] / prices.iloc[0]), 6))   # 0.029559   end price over start price

# exp(total) - 1 is the simple return of the whole period
print(round(np.exp(log_ret.sum()) - 1, 6))             # 0.03
# Symmetry: the price doubles, then halves
doubling = pd.Series([100.0, 200.0, 100.0])
print(doubling.pct_change().tolist())               # [nan, 1.0, -0.5]
print(np.log(doubling).diff().round(4).tolist())    # [nan, 0.6931, -0.6931]

Conversión y movimientos de varios días

Para volver a un rendimiento simple usa np.exp(r) - 1 (o np.expm1(r), más preciso para valores muy pequeños). Ambos coinciden bien en movimientos pequeños y se separan en los grandes: un rendimiento simple de +50 % es 0,4055 en logaritmos. np.log y np.exp trabajan sobre una Series entera, así que no hay bucle. Para medir un movimiento de varios días, diff acepta un número de periodos: np.log(prices).diff(5) es el rendimiento logarítmico de cinco días, igual a la suma de cinco rendimientos logarítmicos diarios.

# Small moves agree with the simple return, big moves do not
for simple in [0.01, 0.1, 0.5, -0.5]:
    print(simple, round(np.log1p(simple), 4))   # log1p(r) is ln(1 + r)
# 0.01 0.01
# 0.1 0.0953
# 0.5 0.4055
# -0.5 -0.6931

# Back to simple returns, on the whole Series at once
print((np.exp(log_ret) - 1).round(4).tolist())   # [nan, 0.02, -0.01, 0.02]

# The log return over 2 days: diff takes a number of periods
print(np.log(prices).diff(2).round(4).tolist())   # [nan, nan, 0.0098, 0.0098]
Súmalos en el tiempo, no entre activosLos rendimientos logarítmicos se suman entre periodos, pero el rendimiento de una cartera es la suma ponderada de los rendimientos simples de sus activos. Dos posiciones iguales con rendimientos logarítmicos de +10 % y -10 % no dan una cartera del 0 %: en simple son +10,5 % y -9,5 %, así que la cartera gana +0,5 %. Convierte primero a rendimientos simples, pondera y vuelve a convertir si necesitas logaritmos.
  • Un rendimiento logarítmico es ln(precio / precio anterior): np.log(prices).diff(); la primera entrada es NaN.
  • En el tiempo simplemente se suman: log_ret.sum(), y np.exp(total) - 1 da el rendimiento simple.
  • diff(k) da el movimiento de k periodos; entre activos, pondera los rendimientos simples, no los logarítmicos.

A continuación: DatetimeIndex e indexación temporal, para dar fechas reales a una serie de precios y cortarla por mes o por día de la semana.

Lab: qué se califica

  • Convertir precios en rendimientos logarítmicos con log_returns25 pts
  • Convertir rendimientos logarítmicos en simples con simple_from_log25 pts
  • Sumar los rendimientos logarítmicos por periodo con total_log_return25 pts
  • Medir el movimiento de varios días con multi_day_log_return25 pts
Explorador · lab-44-1
▾ lab-44-1
…
bash · en el navegador
learner@quantcraft:~/lab-44-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

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