σμ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 10 · Engenharia Python de alto desempenho›Tópico 10.2·~45 minAvançado

Type hints e verificação estática

Posição no roteiroMódulo 10 de 11 · Tópico 2 de 13
10.2 Type hints e verificação estática
—Nota do lab— / 100XP total—Sequência—

As anotações são documentação que uma ferramenta pode verificar

Python é de tipagem dinâmica: uma variável pode conter qualquer coisa, e um tipo errado só aparece quando a linha roda, talvez em pleno pregão. As anotações de tipo permitem escrever o que uma função espera e devolve: def mid_price(bid: float, ask: float) -> float. O Python as ignora ao executar. O valor delas é que um editor e um verificador estático como mypy ou pyright as leem e avisam de uma chamada errada antes de o código rodar, e que documentam a função melhor que um comentário que envelhece.

# Hints describe the function; Python does not enforce them when it runs
def mid_price(bid: float, ask: float) -> float:
    return (bid + ask) / 2

print(mid_price(100.0, 100.5))                      # 100.25
print(mid_price.__annotations__)                    # {'bid': <class 'float'>, 'ask': <class 'float'>, 'return': <class 'float'>}
print(mid_price(10, 12))                            # 11.0   an int is accepted where float is hinted
try:
    mid_price("a", "b")                             # a checker flags this line before the code runs
except TypeError as error:
    print("only fails when it runs:", error)       # only fails when it runs: unsupported operand type(s) for /

Contêineres, None e uniões

Os contêineres embutidos recebem o tipo dos elementos entre colchetes: list[float], dict[str, float], tuple[str, float] (um tipo por posição). Um valor que pode faltar é float | None, o que obriga o chamador a tratar None; o verificador reclama se ele usar o resultado como número sem checar. Dentro da função, um if x is None: return estreita o tipo e o resto sabe que é um float. Para argumentos só lidos, prefira um tipo geral como Sequence[float] (listas, tuplas) a list[float], para caberem mais chamadores; devolva um tipo concreto, como list[float].

# Containers, an optional result, and narrowing with an is None check
def best_quote(quotes: list[tuple[str, float]]) -> tuple[str, float] | None:
    if not quotes:
        return None
    return min(quotes, key=lambda quote: quote[1])

def describe(quotes: list[tuple[str, float]]) -> str:
    best = best_quote(quotes)
    if best is None:                                 # after this check the checker knows best is a tuple
        return "no quotes"
    venue, price = best
    return f"{venue} at {price:.2f}"

print(describe([("XNAS", 100.02), ("ARCX", 100.01)]))     # ARCX at 100.01
print(describe([]))                                       # no quotes

Formas de dados e o verificador em ação

Um dicionário de chaves fixas, como uma ordem, é melhor descrito do que deixado como dict. Um TypedDict ou uma dataclass nomeia cada campo e seu tipo, de modo que um erro de digitação como order["quantiy"] vira erro no editor e não um KeyError às 15:59. O verificador roda na linha de comando (mypy main.py); imprime cada ponto em que o código contradiz suas anotações e sai com código diferente de zero, então encaixa nas verificações automáticas que você verá adiante. As anotações podem ser adicionadas aos poucos: Any desliga a checagem de um valor e o código sem tipos é simplesmente ignorado. As anotações também são dados que as ferramentas leem em tempo de execução com typing.get_type_hints, exatamente como este laboratório as verifica.

# A TypedDict names the fields of an order; the checker would flag order["quantiy"]
from typing import TypedDict

class Order(TypedDict):
    symbol: str
    quantity: int
    price: float

def notional(order: Order) -> float:
    return order["quantity"] * order["price"]

order: Order = {"symbol": "AAPL", "quantity": 100, "price": 184.5}
print(notional(order))                              # 18450.0
print(Order.__annotations__)                        # {'symbol': <class 'str'>, 'quantity': <class 'int'>, 'price': <class 'float'>}
# The hints can be read at run time, which is how tools (and this lab) inspect a function
import typing

def apply_fee(prices: typing.Sequence[float], fee_rate: float = 0.001) -> list[float]:
    return [price * (1 + fee_rate) for price in prices]

hints = typing.get_type_hints(apply_fee)
print(hints["fee_rate"], hints["return"])           # <class 'float'> list[float]
print(typing.get_origin(hints["prices"]).__name__)  # Sequence
print(apply_fee((100.0, 200.0)))                    # a tuple is accepted: [100.1, 200.2]
Anotações não são validaçãoUma anotação não impede um valor errado em tempo de execução: dados vindos de um arquivo, uma API ou um websocket continuam sendo o que são. Valide os dados externos explicitamente (ou com uma biblioteca que constrói objetos a partir das anotações) e use as anotações para pegar erros nas suas próprias chamadas entre funções. Um verificador verde significa que as anotações concordam entre si, não que os números estejam certos; os testes continuam fazendo esse trabalho.
  • As anotações (bid: float, -> float) documentam uma função e são ignoradas ao executar; um verificador como o mypy as lê.
  • Contêineres recebem tipos de elementos (list[tuple[str, float]]); um valor ausente é float | None; argumentos só de leitura podem ser um Sequence[float] geral.
  • Use TypedDict ou dataclass para registros, rode o verificador nas suas verificações automáticas, e continue validando dados externos e testando os números.

A seguir: testes com pytest, fixtures, casos parametrizados e as verificações que mantêm uma estratégia honesta.

Lab: o que é avaliado

  • Anotar números com mid_price25 pts
  • Tipar um contêiner com best_quote25 pts
  • Admitir um valor ausente em safe_ratio25 pts
  • Aceitar qualquer sequência em apply_fee25 pts
Explorador · lab-118-1
▾ lab-118-1
…
bash · no navegador
learner@quantcraft:~/lab-118-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-118-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