Módulo 08 AdmTech · Computação · Semana 6 · 18/11/2026

Da Nuvem à Fronteira

Monte Carlo e Otimização de Markowitz para o A3 e o A4, Sprint 3

Logo Inteli

Agenda do encontro

BlocoMinutosTemaInteração que fecha o bloco
Daily15O que fiz, o que vou fazer, impedimentostempo do motor do grupo para 10.000 carteiras
10 a 15Da covariância às carteiras sorteadasPeer Instruction sobre a melhor sorteada
215 a 30Pesos, retorno e risco em forma vetorialprevisão antes do triângulo de pesos
330 a 45O motor vetorizado de Monte Carlodupla no notebook, seções 1 a 3
445 a 60A melhor sorteada contra a ótimaquantos sorteios faltariam
560 a 75Otimização com restrições e SLSQPprevisão da carteira mais concentrada
675 a 90As duas ótimas e a fronteira de 50 pontosdupla no notebook, seções 4 e 5
790 a 105Quiz e amarração com a Sprint 3quiz de três perguntas

Horários de relógio a confirmar na Adalove; os blocos contam do fim da daily.

Logo Inteli

O otimizador estima 135 parâmetros em 1.423 retornos

A matriz de covariância da Aula 03 entra inteira, na mesma janela: 15 retornos esperados mais 120 variâncias e covariâncias distintas.

Regra da ADR-009: a lacuna de 24/10/2025 é preenchida com o último preço, como no ADR da Aula 01, e a cesta usa a janela comum dos 15 ativos, 1.423 retornos de 14/12/2020 a 31/08/2026.

Com a matriz pronta, como o grupo escolhe os pesos dos 15 ativos?

Trio de hojeVolatilidade, série inteiraVolatilidade, janela comumCorrelação com PETR4
PETR439,25%33,40%1
IVVB1120,15%17,66%-0,09
GOLD1119,80%19,80%-0,13

Custo da janela comum: com a GOLD11, cotada desde 11/12/2020, a cesta perde março de 2020, e a volatilidade da PETR4 cai de 39,25% (série inteira, Aula 02) para 33,40%.

Logo Inteli

Verificação do preparo

Entre 10.000 carteiras sorteadas com os 15 ativos, a de maior Índice de Sharpe é a carteira ótima?

  • Sim: 10.000 sorteios cobrem todas as alocações
  • Sim, a menos de arredondamento
  • Depende da semente: outra semente passa da ótima
  • Não: é só a melhor entre as sorteadas e fica abaixo da ótima
  1. Votar sozinho, sem conversar.
  2. Discutir em dupla por dois minutos, defendendo o voto com o que viram na animação da nuvem.
  3. Votar de novo e só então revelar.
Logo Inteli

A melhor sorteada tem Sharpe 0,41 contra 0,92

CarteiraSharpeRetornoVolatilidadeAtivos com pesoMaior peso
Melhor de 10.000 sorteadas0,4116,62%13,05%1518,17%
Máximo Sharpe, SLSQP0,9225,96%15,91%344,31% em PETR4

Sorteio com semente 42 e pesos Uniform(0,1) divididos pela soma, uma distribuição que acumula as carteiras perto de 1/15 por ativo (slide 14). A carteira ótima concentra o peso em 3 dos 15 ativos e zera os outros 12.

Pesos, retorno e risco em forma vetorial

Uma carteira é um vetor de pesos que soma 1

Logo Inteli

Pesos iguais rendem 8,34%, abaixo do CDI

# mu: retorno esperado anual (15)
# cov: covariância anual (15 x 15)
# rf: CDI anualizado na janela
def metricas(w, mu, cov, rf):
    retorno = w @ mu
    volatilidade = np.sqrt(w @ cov @ w)
    sharpe = (retorno - rf) / volatilidade
    return retorno, volatilidade, sharpe

w = np.full(15, 1 / 15)
metricas(w, mu, cov, rf)
Retornow · μ, a média dos retornos ponderada pelos pesos
VariânciawT Σ w, que soma cada covariância ponderada pelo par de pesos
Sharpe(retorno - CDI) / volatilidade: prêmio sobre o CDI por unidade de risco
Pesos iguaisretorno 8,34% contra CDI de 11,30%, volatilidade 16,31%, Sharpe -0,18

Oito dos 15 ativos rendem abaixo do CDI na janela, e a MGLU3 tem retorno esperado de -42,83% ao ano.

Logo Inteli

Cada ponto do triângulo é uma carteira

Antes de arrastar: anotem onde o ponto cai no plano com 100% em PETR4 e onde fica o maior Sharpe.

Logo Inteli

O motor sorteia 10.000 carteiras em menos de 1 s

def sortear(n, mu, cov, rf, semente=42):
    gerador = np.random.default_rng(semente)
    pesos = gerador.random((n, len(mu)))
    pesos /= pesos.sum(axis=1, keepdims=True)
    retorno = pesos @ mu
    volatilidade = np.sqrt(np.einsum(
        "ij,jk,ik->i", pesos, cov, pesos))
    sharpe = (retorno - rf) / volatilidade
    return pesos, retorno, volatilidade, sharpe

pesos, ret, vol, sharpe = sortear(
    10_000, mu, cov, rf)
Sementeo mesmo sorteio em qualquer máquina, para o teste do SPEC.md
Normalizarcada linha dividida pela própria soma: pesos somam 1, nenhum negativo, e a distribuição se acumula perto de 1/15
einsumwT Σ w das 10.000 linhas de uma vez, sem laço em Python
Requisitoo A3 pede 10.000 carteiras em menos de 10 segundos
Logo Inteli

Prática em dupla: o motor de Monte Carlo

  1. O condutor abre o notebook no Colab e roda as seções 1 a 3, que já vêm prontas; o navegador confere cada saída.
  2. Seção 3: anotem o tempo das 10.000 carteiras e quantas ficaram abaixo do CDI.
  3. Aos 6 minutos, troquem de papel. O navegador aponta em sortear a linha que faz os pesos somarem 1 e a que calcula a variância sem laço.
  4. Comparem o tempo medido com o requisito do A3, menos de 10 segundos.
  5. ExtensãoEscrevam o laço for w in pesos: w @ cov @ w e confiram com np.allclose que ele bate com o einsum.

Checagem aos 6 min: o tempo das 10.000 carteiras e a contagem abaixo do CDI estão anotados. Debrief: ao fim do cronômetro, a turma compara os tempos medidos e a contagem abaixo do CDI entre as duplas.

Abrir o notebook da Aula 04 no Colab

Logo Inteli

8.851 das 10.000 sorteadas rendem abaixo do CDI

Antes de tocar: anotem onde a melhor sorteada vai parar, no meio da nuvem ou na borda de cima.

Logo Inteli

A melhor sorteada sobe de -0,10 para 0,41

Quantos sorteios faltariam para a melhor sorteada encostar na ótima?

Logo Inteli

Um milhão de sorteios chega a Sharpe 0,60

SorteiosMelhor Sharpe
10-0,10
1000,15
1.0000,28
10.0000,41
100.0000,41
1.000.0000,60
SLSQP0,92

O motor soma 15 números Uniform(0,1) e divide cada um pela soma. Essa distribuição acumula os pesos perto de 1/15: o maior peso entre as 10.000 sorteadas é 24,61%.

A ótima põe 44,31% na PETR4 e zera 12 ativos, uma região que essa distribuição quase nunca visita. O slide seguinte troca a distribuição e mantém os 10.000 sorteios.

Quantos sorteios faltariam para a melhor sorteada encostar na ótima?

Logo Inteli

Trocar a distribuição leva o melhor Sharpe a 0,85

10.000 sorteios, semente 42Melhor SharpeMaior peso da melhorAtivos efetivos, medianaCarteiras com peso acima de 25%
Uniform(0,1) dividido pela soma, o motor da aula0,4118,17%11,410,00%
Dirichlet(1), uniforme no simplex0,6455,26%8,3726,21%
Dirichlet(0,2), mais peso nos vértices0,8568,35%3,7094,91%
Máximo Sharpe, SLSQP0,9244,31%2,82 na ótimanão se aplica
Distribuiçãocom o mesmo orçamento, a Dirichlet(1) chega a 0,64 e passa do milhão de sorteios do motor da aula (0,60)
Dimensãono trio PETR4, IVVB11 e GOLD11, as três distribuições chegam a 0,92 com 10.000 sorteios; com 15 ativos, nenhuma chega
Objetivoo sorteio não usa o Sharpe para decidir onde sortear; o SLSQP usa, e por isso o A4 resolve a carteira por otimização

Ativos efetivos = 1 / soma dos pesos ao quadrado: 15 com pesos iguais, 1 com todo o peso num ativo.

Otimização com restrições

Função objetivo, soma 1 e nenhum peso negativo

Logo Inteli

Otimização com SLSQP no SciPy

from scipy.optimize import minimize

n = len(mu)
soma_1 = {"type": "eq",
          "fun": lambda w: w.sum() - 1}
limites = [(0, 1)] * n  # sem venda a descoberto
inicio = np.full(n, 1 / n)

def menos_sharpe(w):
    return -(w @ mu - rf) / np.sqrt(w @ cov @ w)

ms = minimize(menos_sharpe, inicio, method="SLSQP",
              bounds=limites, constraints=[soma_1])
mv = minimize(lambda w: w @ cov @ w, inicio,
              method="SLSQP", bounds=limites,
              constraints=[soma_1])
Objetivoo que se minimiza: a variância, ou o Sharpe com sinal trocado
Restriçãoigualdade: os pesos somam 1
Limitescada peso entre 0 e 1, sem venda a descoberto
Conferirms.success antes de usar ms.x
Logo Inteli

O SLSQP chega ao ótimo do trio em 10 iterações

Antes de rodar: qual das duas, variância mínima ou máximo Sharpe, vai concentrar mais peso num único ativo? A previsão fica no quadro.

Logo Inteli

O máximo Sharpe põe 44,31% na PETR4

MedidaVariância mínimaMáximo Sharpe
Retorno14,10%25,96%
Volatilidade9,67%15,91%
Sharpe0,290,92
Ativos com peso103
Maior peso26,78% IVVB1144,31% PETR4
AtivoVariância mínimaMáximo Sharpe
PETR45,06%44,31%
IVVB1126,78%23,97%
GOLD1124,71%31,72%
EGIE317,20%0%
outros 626,27%0%

Confiram a previsão do quadro. A variância mínima espalha o peso em 10 ativos e fica com a menor volatilidade possível da cesta.

Logo Inteli

Nenhuma das 10.000 sorteadas passa da fronteira

Cada um dos 50 pontos é a carteira de menor volatilidade para um retorno alvo, de 14,10% (variância mínima) a 37,53% (só PETR4).

Logo Inteli

Prática em dupla: as duas ótimas e a fronteira

  1. Rodem as seções 1 a 5, que já vêm prontas, e confiram que as duas otimizações terminam com success.
  2. Na tabela de pesos, apontem os ativos com peso zero no máximo Sharpe: neles o limite inferior está ativo.
  3. Aos 6 minutos, troquem de papel. No gráfico da seção 5, escolham uma sorteada e o ponto da fronteira que tem mais retorno com a mesma volatilidade.
  4. Escrevam uma frase: para qual perfil de investidor do parceiro cada carteira faz sentido.
  5. ExtensãoSeção 6: completem maximo_sharpe_com_teto e comparem os pesos com os da seção 4.

Checagem aos 6 min: a tabela das duas ótimas está na tela, com os ativos de peso zero apontados. Debrief: ao fim do cronômetro, duas duplas leem a frase do perfil, e a sala confere se alguma sorteada passa da fronteira.

Logo Inteli

Quiz de verificação

1. Por que o sorteio não encontra a carteira de máximo Sharpe?

  • 10.000 são poucos; 100.000 resolvem
  • A distribuição dos pesos quase nunca concentra
  • A semente está errada

2. O que impede venda a descoberto no SLSQP?

  • A restrição de soma 1
  • Os limites de 0 a 1
  • O ponto inicial

3. Qual ótima tem a menor volatilidade?

  • Variância mínima
  • Máximo Sharpe
  • A melhor sorteada
Logo Inteli

Notebook da aula

SeçãoO que entrega
1 e 2Retornos, mu, cov, o CDI e as métricas em forma vetorial
3O motor vetorizado, o tempo medido e a nuvem colorida por Sharpe
4Variância mínima e máximo Sharpe com SLSQP, e a tabela comparativa
5A fronteira de 50 pontos sobre a nuvem
6Desafio: peso máximo por ativo e a comparação com os pesos da aula

Notebook no GitHub · Abrir no Colab

Logo Inteli

Artefatos A3 e A4 da Sprint 3

Critério do A3PesoO que hoje já adiantou
Corretude da simulação30%pesos normalizados e as três métricas por carteira
Desempenho10%motor vetorizado, bem abaixo dos 10 segundos
Qualidade do gráfico10%nuvem colorida por Sharpe, com o CDI marcado
Leitura analítica15%por que a simulação não substitui a otimização: 0,41 contra 0,92
Especificação e documentação15%SPEC.md com teste de semente fixa e pesos somando 1
ADRs, nota individual20%número de simulações e vetorização, com o tempo medido

A3 vale 3 pontos: review da Sprint 3 em 19/11/2026 e entrega na sexta, 20/11/2026, 23h59. O A4 (3 pontos) leva o otimizador de hoje para um módulo Python; a Adalove o lista nas Sprints 3 e 4.

Logo Inteli

Referências

  1. dados/README.md: snapshot do case, cesta de 15 ativos e falhas do provedor.
  2. CAETANO, M. A. L. Python e mercado financeiro. Blucher, 2021. cap. 9, seções 9.2 e 9.5. Autoestudo: Carteiras e simulação de Monte Carlo com Python.
  3. CAETANO, M. A. L. Python e mercado financeiro. Blucher, 2021. cap. 9, seção 9.3. Autoestudo: Da nuvem à fronteira eficiente de Markowitz.
  4. MARKOWITZ, H. Portfolio Selection. The Journal of Finance, v. 7, n. 1, p. 77-91, 1952.
  5. SHARPE, W. F. Mutual Fund Performance. The Journal of Business, v. 39, n. 1, p. 119-138, 1966.
  6. SciPy: minimize com method='SLSQP'.
  7. NumPy: Random Generator.
  8. Banco Central, dados abertos do SGS: série 12, CDI.
  9. DEVROYE, L. Non-Uniform Random Variate Generation. Springer, 1986. cap. V, seção 2, e cap. XI, seção 4: amostragem uniforme no simplex e distribuição de Dirichlet.

Até 01/12/2026

Aula 05: Validação e Robustez do Modelo

Prof. José Romualdo