σμ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 1 · Fundamentos de Python para quants›Tema 1.26·~45 minPrincipiante

Clases y objetos

Posición en la rutaMódulo 1 de 11 · Tema 26 de 33
1.26 Clases y objetos
—Puntuación del lab— / 100XP total—Racha—

Datos y comportamiento juntos

Hasta ahora una posición podía ser una tupla o un diccionario, con funciones separadas que trabajan sobre ella. Una clase agrupa los datos y las funciones que les pertenecen en un tipo nuevo. class Position: define el plano; llamarla, Position("AAPL", 100, 180.0), construye un objeto (también llamado instancia) a partir de ese plano. Cada objeto guarda sus propios datos, y las funciones definidas en la clase, llamadas métodos, trabajan sobre ese objeto.

class Position:
    def __init__(self, symbol, quantity=0):
        self.symbol = symbol          # attributes belong to this object
        self.quantity = quantity

    def describe(self):
        return f"{self.quantity} x {self.symbol}"

apple = Position("AAPL", 100)
tesla = Position("TSLA")

print(apple.describe())   # 100 x AAPL
print(tesla.describe())   # 0 x TSLA
print(apple.quantity, tesla.quantity)  # 100 0

__init__ y self

__init__ es el constructor: Python lo ejecuta automáticamente al crear un objeto y guarda los valores iniciales. Cada método recibe el propio objeto como primer parámetro, llamado por convención self; no lo pasas tú, lo pasa Python (apple.describe() llama a Position.describe(apple)). Lo que se guarda con self.nombre = valor es un atributo de ese objeto y permanece ahí entre llamadas a métodos. __init__ prepara las cosas y no devuelve nada.

class Account:
    def __init__(self, cash):
        self.cash = cash

    def deposit(self, amount):
        self.cash += amount          # changes this object's attribute
        return self.cash

first = Account(1000)
second = Account(50)

first.deposit(500)
print(first.cash, second.cash)       # 1500 50  (separate objects, separate data)

same = first                          # a second name for the same object
same.deposit(1)
print(first.cash)                     # 1501

Métodos que cambian el estado o responden preguntas

Algunos métodos responden una pregunta sobre el objeto sin cambiarlo (market_value(price)); solo deben devolver un resultado y dejar los atributos en paz. Otros cambian el objeto (apply_fill), actualizan atributos y a menudo devuelven algo útil como la ganancia realizada. Un método puede llamar a otro con self.otro_metodo(...), lo que mantiene las reglas en un solo lugar: si unrealized_pnl necesita el valor de mercado, pregunta a self.market_value(price) en vez de repetir la fórmula.

class Position:
    def __init__(self, symbol, quantity=0, avg_price=0.0):
        self.symbol = symbol
        self.quantity = quantity
        self.avg_price = avg_price

    def market_value(self, price):
        return self.quantity * price

    def unrealized_pnl(self, price):
        return self.market_value(price) - self.quantity * self.avg_price

pos = Position("AAPL", 100, 180.0)
print(pos.market_value(185.0))       # 18500.0
print(pos.unrealized_pnl(185.0))     # 500.0

Trampas y cuándo usar una clase

Olvidar self. es el descuido clásico: quantity = 5 dentro de un método crea una variable local desechable, no un atributo. Usa CapWords para los nombres de clase (Position) y minúsculas con guiones bajos para atributos y métodos; un guion bajo inicial (_cache) marca algo como interno. Nunca uses un valor por defecto mutable como def __init__(self, fills=[]): todos los objetos compartirían esa única lista; usa fills=None y crea [] dentro. Crea una clase cuando los datos y las reglas sobre ellos viajan juntos; una función simple o un diccionario suele ser más sencillo.

class Wrong:
    def __init__(self, quantity):
        quantity = quantity          # forgot self.: nothing is stored

class Shared:
    def __init__(self, fills=[]):    # one list shared by every object
        self.fills = fills

class Right:
    def __init__(self, fills=None):
        self.fills = [] if fills is None else list(fills)

a, b = Shared(), Shared()
a.fills.append(100)
print(b.fills)                        # [100]  (surprise!)

c, d = Right(), Right()
c.fills.append(100)
print(d.fills)                        # []

print(hasattr(Wrong(5), "quantity"))  # False
Comprueba que cada objeto conserva su propio estadoUn buen hábito al escribir una clase: crea dos objetos, cambia uno e imprime el otro. Si el segundo también cambió, se comparte algo que no debería. Las pruebas del lab hacen exactamente eso, y también comprueban que un método que solo debe responder una pregunta deja los atributos sin cambios.
  • class Nombre: define un tipo; Nombre(args) construye un objeto y ejecuta __init__.
  • self.attr = valor guarda datos en el objeto; cada método recibe self primero.
  • Los métodos de consulta devuelven respuestas; los de actualización cambian atributos; evita los valores por defecto mutables.

A continuación: métodos especiales como __repr__ y __eq__, que hacen que tus objetos se impriman bien y se comparen como esperas.

Lab: qué se califica

  • Construir una posición con __init__25 pts
  • Valorar la posición con market_value25 pts
  • Medir la ganancia latente con unrealized_pnl25 pts
  • Actualizar la posición tras una operación con apply_fill25 pts
Explorador · lab-26-1
▾ lab-26-1
…
bash · en el navegador
learner@quantcraft:~/lab-26-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

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