σμ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 AcademyRoteiros
Ctrl K
AO
+1,2 mil alunos
EntrarParticipar ↗
Roteiros
AO
+1,2 mil alunos
Entrar
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Roteiro de Python›Módulo 1 · Fundamentos de Python para quants›Tópico 1.28·~35 minIniciante

Dataclasses

Posição no roteiroMódulo 1 de 11 · Tópico 28 de 33
1.28 Dataclasses
—Nota do lab— / 100XP total—Sequência—

Menos código repetitivo para classes que guardam dados

Muitas classes existem principalmente para guardar alguns campos: uma operação, uma cotação, uma configuração. Escrever __init__, __repr__ e __eq__ para cada uma é repetitivo. O decorador @dataclass do módulo dataclasses os escreve para você a partir de uma lista de campos anotados. Você declara symbol: str, price: float, quantity: int uma vez e obtém um construtor Trade("AAPL", 184.25, 200), um repr legível como Trade(symbol='AAPL', price=184.25, quantity=200) e igualdade campo a campo. As anotações documentam a intenção; o Python não as impõe.

from dataclasses import dataclass

@dataclass
class Trade:
    symbol: str
    price: float
    quantity: int

a = Trade("AAPL", 184.25, 200)
b = Trade("AAPL", 184.25, 200)

print(a)                       # Trade(symbol='AAPL', price=184.25, quantity=200)
print(a == b)                  # True: compared field by field
print(a.price * a.quantity)    # 36850.0

Valores padrão, field() e valores mutáveis

Um campo pode ter um valor padrão (currency: str = "USD"), e os campos com padrão devem vir depois dos que não têm. Para um padrão mutável como uma lista, um simples = [] seria compartilhado por todos os objetos (e o Python recusa); escreva trades: list = field(default_factory=list) para que cada objeto receba sua própria lista nova. field(...) também permite ocultar um campo do repr (repr=False) ou das comparações (compare=False).

from dataclasses import dataclass, field

@dataclass
class Book:
    name: str
    currency: str = "USD"                       # a default
    trades: list = field(default_factory=list)  # a fresh list per object

one = Book("desk-a")
two = Book("desk-b")
one.trades.append(("AAPL", 100))

print(one)                  # Book(name='desk-a', currency='USD', trades=[('AAPL', 100)])
print(two.trades)           # []   (not shared)
print(Book("x", "EUR"))     # Book(name='x', currency='EUR', trades=[])

Seus próprios métodos, __post_init__ e construtores alternativos

Uma dataclass continua sendo uma classe normal, então você pode adicionar métodos. __post_init__(self) roda logo após o __init__ gerado, o lugar para validar ou limpar valores (self.symbol = self.symbol.upper(), raise ValueError(...) para um preço ruim). Um @classmethod recebe a classe como cls e é a forma usual de construir um objeto a partir de outra forma, como texto: Trade.from_line("AAPL,184.25,200") devolve cls(symbol, float(price), int(quantity)), assim a validação continua valendo e as subclasses também funcionam.

from dataclasses import dataclass

@dataclass
class Trade:
    symbol: str
    price: float
    quantity: int

    def __post_init__(self):
        self.symbol = self.symbol.strip().upper()
        if self.price <= 0:
            raise ValueError("price must be positive")

    def notional(self):
        return self.price * abs(self.quantity)

    @classmethod
    def from_line(cls, line):
        symbol, price, quantity = line.split(",")
        return cls(symbol, float(price), int(quantity))

t = Trade.from_line(" aapl,184.25,-200")
print(t)              # Trade(symbol='AAPL', price=184.25, quantity=-200)
print(t.notional())   # 36850.0

Congeladas, ordenadas e quando as classes comuns vencem

@dataclass(frozen=True) torna as instâncias somente leitura (atribuir a um campo gera FrozenInstanceError) e lhes dá um hash, então podem ser chaves de dicionário ou membros de conjunto: ideal para valores que não devem mudar, como a especificação de um contrato. @dataclass(order=True) adiciona <, <=, >, >= comparando os campos em ordem. Use uma dataclass para registros de dados; para objetos com muito comportamento e estado oculto, uma classe escrita à mão com métodos cuidadosos é mais clara.

from dataclasses import dataclass

@dataclass(frozen=True, order=True)
class Contract:
    symbol: str
    expiry: str          # ISO dates sort correctly as text

a = Contract("ESZ5", "2025-12-19")
b = Contract("ESZ5", "2026-03-20")
print(a < b)                          # True
print({a: "front", b: "next"}[a])     # front  (frozen => hashable)

try:
    a.symbol = "NQZ5"
except Exception as error:
    print(type(error).__name__)       # FrozenInstanceError
Valide onde os dados entramAnotações como price: float não impedem que Trade("AAPL", "abc", 1) seja criado. Se valores ruins corromperiam em silêncio cálculos posteriores, verifique-os em __post_init__ e gere ValueError, para que um registro quebrado não possa existir. Crie sempre os objetos pelo construtor normal, inclusive a partir de from_line, para que a verificação não possa ser ignorada.
  • @dataclass transforma campos anotados em __init__, __repr__ e __eq__.
  • Os padrões vêm por último; use field(default_factory=list) para listas e dicionários.
  • __post_init__ valida; @classmethod constrói a partir de outras formas; frozen=True torna os valores somente leitura.

A seguir: derivadas em código, estimar a rapidez com que uma grandeza muda, a ideia por trás das sensibilidades de opções como delta e gama.

Lab: o que é avaliado

  • Limpar e validar uma operação com __post_init__25 pts
  • Calcular o valor negociado com notional25 pts
  • Construir uma operação a partir de texto com from_line25 pts
  • Calcular o saldo das operações de um símbolo com net_quantity25 pts
Explorador · lab-28-1
▾ lab-28-1
…
bash · no navegador
learner@quantcraft:~/lab-28-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-28-1 volta aos arquivos iniciais e o terminal é limpo. Sua solução atual será perdida — isso não pode ser desfeito.

Será redefinido
  • main.py → código inicial
  • Histórico do terminal e saída dos testes
  • Alterações não enviadas
Será mantido
  • Melhor nota do lab
  • Seu XP e sua sequência
  • Progresso da aula e anotações

Entre para executar o seu código.

Todas as aulas são gratuitas para ler. Crie uma conta ou entre para executar código, rodar os testes e enviar este lab.

  • IDE no navegador com terminal bash — nada para instalar
  • Correção instantânea, XP e o seu lugar no roteiro
Criar uma contaEntrar
OU
Continuar com o GitHub