σμ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 3 · Probabilidade e simulação Monte Carlo›Tópico 3.9·~40 minIntermediário

Geradores de números aleatórios e sementes

Posição no roteiroMódulo 3 de 11 · Tópico 9 de 12
3.9 Geradores de números aleatórios e sementes
—Nota do lab— / 100XP total—Sequência—

Aleatório, mas repetível

A simulação Monte Carlo, o bootstrap e muitos testes precisam de números aleatórios, mas um resultado que ninguém consegue reproduzir não vale nada: não dá para depurá-lo, comparar duas versões de um modelo nem mostrá-lo a um colega. Os números que um computador produz não são realmente aleatórios. Um gerador de números pseudoaleatórios é um algoritmo determinístico que, a partir de um valor inicial chamado semente (seed), produz uma longa sequência que se comporta como sorteios aleatórios. A mesma semente dá a mesma sequência, sempre e em qualquer máquina.

import numpy as np

rng = np.random.default_rng(42)            # a Generator created from the seed 42
print(rng.random(3).round(4).tolist())     # [0.774, 0.4389, 0.8586]

rng = np.random.default_rng(42)            # the same seed again: the same numbers
print(rng.random(3).round(4).tolist())     # [0.774, 0.4389, 0.8586]

rng = np.random.default_rng(43)            # another seed: other numbers
print(rng.random(3).round(4).tolist())     # [0.6523, 0.0438, 0.02]

Use um Generator, não estado global

O código antigo chama np.random.seed(42) uma vez e depois np.random.normal(...) em qualquer lugar: todo o código compartilha um único gerador global oculto. Qualquer biblioteca, ou qualquer linha nova que sorteie um número, desloca a sequência de todos os outros, e os resultados mudam por razões sem relação com o seu modelo. A forma moderna é criar um objeto Generator com np.random.default_rng(seed) e passá-lo explicitamente. Seus métodos random, normal, choice, integers fazem todos os sorteios, e dois geradores nunca interferem.

def simulate_returns(seed, n, mu, sigma):
    rng = np.random.default_rng(seed)              # a private generator, not the global one
    return rng.normal(mu, sigma, size=n)

first = simulate_returns(7, 5, 0.0005, 0.01)
second = simulate_returns(7, 5, 0.0005, 0.01)
print(first.round(5).tolist())                     # [0.00051, 0.00349, -0.00224, -0.00841, -0.00405]
print(np.array_equal(first, second))               # True   repeatable

Reamostragem e fluxos independentes

Um bootstrap reamostra o histórico para ver quanto uma estatística poderia ter variado: sorteiam-se tantos retornos quanto se tem, com reposição, com rng.choice(returns, size=len(returns), replace=True). Alguns dias aparecem duas vezes, outros nenhuma. Quando muitas simulações rodam em paralelo, dar a cada processo as sementes 1, 2, 3 é arriscado porque sementes vizinhas não têm independência garantida. np.random.SeedSequence(seed).spawn(k) deriva k sequências filhas projetadas para não se sobrepor; construa um default_rng(child) de cada uma.

data = np.array([1, 2, 3, 4, 5])
rng = np.random.default_rng(1)
print(rng.choice(data, size=len(data), replace=True).tolist())    # [3, 3, 4, 5, 1]   3 appears twice, 2 not at all

# Three independent streams from one seed, for three parallel simulations
children = np.random.SeedSequence(2026).spawn(3)
streams = [np.random.default_rng(child) for child in children]
print([stream.random(2).round(4).tolist() for stream in streams])
# [[0.3827, 0.0204], [0.6711, 0.158], [0.5508, 0.2339]]
rng = np.random.default_rng(42)
print(rng.integers(1, 7, size=8).tolist())             # [1, 5, 4, 3, 3, 6, 1, 5]   eight dice rolls, repeatable
rng = np.random.default_rng(42)
print(rng.uniform(-0.01, 0.01, 3).round(5).tolist())   # [0.00548, -0.00122, 0.00717]
Fixe a semente de propósito e anote-aUma semente fixa torna uma execução repetível, mas não é controle de qualidade: uma semente de sorte pode fazer uma ideia ruim parecer boa. Rode a análise com várias sementes e verifique se a conclusão se mantém. Imprima ou registre a semente usada para que um resultado de um relatório possa sempre ser regenerado, e nunca escolha uma semente porque dá uma resposta mais agradável.
  • rng = np.random.default_rng(seed): a mesma semente dá sempre os mesmos números; use seus métodos random, normal, choice, integers.
  • Passe o gerador em vez de usar o estado global oculto np.random.seed.
  • choice(..., replace=True) é um bootstrap; SeedSequence(seed).spawn(k) dá k fluxos independentes; registre a semente usada.

A seguir: a amostragem de distribuições, transformando números aleatórios uniformes em sorteios normais, exponenciais e discretos.

Lab: o que é avaliado

  • Criar um gerador repetível com make_rng25 pts
  • Sortear retornos reproduzíveis com simulate_returns25 pts
  • Reamostrar o histórico com bootstrap_returns25 pts
  • Dividir uma semente em fluxos independentes com independent_streams25 pts
Explorador · lab-62-1
▾ lab-62-1
…
bash · no navegador
learner@quantcraft:~/lab-62-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

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