Carteira Diversificada 2025: Como Construir Portfolio Eficiente na B3
A diversificação é a única estratégia comprovada para reduzir riscos sem sacrificar retornos. Aprenda como construir, monitorar e rebalancear uma carteira eficiente usando dados em tempo real da brapi.dev em 2025.
Por Que Diversificação é a Regra de Ouro dos Investimentos?
A diversificação é a única estratégia gratuita para reduzir riscos sem necessariamente reduzir retornos esperados. Harry Markowitz provou que carteiras bem diversificadas têm melhor relação risco-retorno que ativos individuais.
Exemplo prático: Uma carteira com 50% Petrobras e 50% Vale pode ter volatilidade maior que uma carteira com 20 ações diferentes de setores diversos.
Benefícios Comprovados da Diversificação:
- Reduz risco específico de empresas individuais
- Minimiza impacto de crises setoriais
- Suaviza volatilidade da carteira total
- Protege contra ciclos econômicos
- Melhora relação risco-retorno
- Setores defensivos vs. cíclicos
- Proteção contra inflação e recessão
3. Otimização Risco-Retorno
- Fronteira eficiente de Markowitz
- Máximo retorno para cada nível de risco
- Sleep well at night factor
Estrutura de uma Carteira Diversificada
Modelo Clássico de Alocação
carteira_modelo = {
'renda_variavel': {
'acoes_nacionais': 40, # Ações brasileiras
'fiis': 15, # Fundos imobiliários
'acoes_internacionais': 10 # Via ETFs ou BDRs
},
'renda_fixa': {
'tesouro_direto': 20, # Títulos públicos
'cdb_lci_lca': 10, # Renda fixa privada
'fundos_rf': 5 # Fundos de renda fixa
}
}
print("📊 Alocação Total:")
for categoria, subcategorias in carteira_modelo.items():
total_categoria = sum(subcategorias.values())
print(f"{categoria.replace('_', ' ').title()}: {total_categoria}%")
Diversificação por Setor (Ações)
def obter_diversificacao_setorial():
"""Modelo de diversificação setorial para ações brasileiras"""
return {
'financeiro': {
'alvo': 25,
'tickers': ['ITUB4', 'BBDC4', 'BBAS3', 'BBSE3'],
'caracteristicas': 'Dividendos, sensível a juros'
},
'commodities': {
'alvo': 20,
'tickers': ['VALE3', 'PETR4', 'SUZB3', 'USIM5'],
'caracteristicas': 'Cíclico, proteção inflação'
},
'utilities': {
'alvo': 15,
'tickers': ['EGIE3', 'SBSP3', 'CPLE6', 'TAEE11'],
'caracteristicas': 'Defensivo, dividendos estáveis'
},
'consumo': {
'alvo': 15,
'tickers': ['ABEV3', 'BRFS3', 'JBSS3', 'MGLU3'],
'caracteristicas': 'Crescimento, consumo interno'
},
'industrial': {
'alvo': 15,
'tickers': ['WEGE3', 'RAIL3', 'AZUL4', 'EMBR3'],
'caracteristicas': 'Crescimento, tecnologia'
},
'outros': {
'alvo': 10,
'tickers': ['TOTS3', 'RENT3', 'LWSA3', 'HAPV3'],
'caracteristicas': 'Diversificação adicional'
}
}
Construindo a Carteira com brapi.dev
1. Análise e Seleção de Ativos
import requests
import pandas as pd
from datetime import datetime, timedelta
class ConstrutorCarteira:
def __init__(self, token):
self.token = token
self.base_url = "https://brapi.dev/api"
def obter_dados_acao(self, ticker):
"""Obtém dados fundamentalistas de uma ação"""
url = f"{self.base_url}/quote/{ticker}?modules=defaultKeyStatistics,financialData&token={self.token}"
response = requests.get(url)
data = response.json()
acao = data['results'][0]
stats = acao.get('defaultKeyStatistics', {})
financials = acao.get('financialData', {})
return {
'ticker': ticker,
'nome': acao['shortName'],
'preco': acao['regularMarketPrice'],
'setor': acao.get('sector', 'N/A'),
'pl': stats.get('forwardPE', 0),
'pvp': stats.get('priceToBook', 0),
'dy': stats.get('dividendYield', 0) * 100,
'roe': financials.get('returnOnEquity', 0) * 100,
'margemLiquida': financials.get('profitMargins', 0) * 100,
'marketCap': stats.get('marketCap', 0) / 1e9
}
def screening_acoes(self, lista_tickers, criterios):
"""Faz screening baseado em critérios fundamentalistas"""
acoes_aprovadas = []
for ticker in lista_tickers:
try:
dados = self.obter_dados_acao(ticker)
# Aplicar critérios
if (dados['pl'] > 0 and dados['pl'] < criterios['pl_max'] and
dados['pvp'] > 0 and dados['pvp'] < criterios['pvp_max'] and
dados['dy'] > criterios['dy_min'] and
dados['roe'] > criterios['roe_min']):
# Calcular score de qualidade
score = self.calcular_score_qualidade(dados)
dados['score'] = score
acoes_aprovadas.append(dados)
except Exception as e:
print(f"Erro ao processar {ticker}: {e}")
continue
return sorted(acoes_aprovadas, key=lambda x: x['score'], reverse=True)
def calcular_score_qualidade(self, dados):
"""Calcula score de qualidade (0-100)"""
score = 0
# P/L baixo é melhor
if dados['pl'] < 10: score += 20
elif dados['pl'] < 15: score += 15
elif dados['pl'] < 20: score += 10
# P/VP baixo é melhor
if dados['pvp'] < 1: score += 20
elif dados['pvp'] < 1.5: score += 15
elif dados['pvp'] < 2: score += 10
# DY alto é melhor
if dados['dy'] > 8: score += 20
elif dados['dy'] > 5: score += 15
elif dados['dy'] > 3: score += 10
# ROE alto é melhor
if dados['roe'] > 20: score += 20
elif dados['roe'] > 15: score += 15
elif dados['roe'] > 10: score += 10
# Margem líquida alta é melhor
if dados['margemLiquida'] > 20: score += 20
elif dados['margemLiquida'] > 10: score += 15
elif dados['margemLiquida'] > 5: score += 10
return score
# Configurar critérios de seleção
criterios = {
'pl_max': 20,
'pvp_max': 3,
'dy_min': 2, # 2% mínimo
'roe_min': 10 # 10% mínimo
}
# Universo de ações para análise
universo_acoes = [
# Financeiro
'ITUB4', 'BBDC4', 'BBAS3', 'BBSE3', 'SANB11', 'BPAC11',
# Commodities
'VALE3', 'PETR4', 'SUZB3', 'KLBN11', 'GGBR4', 'USIM5',
# Utilities
'EGIE3', 'SBSP3', 'CPLE6', 'TAEE11', 'CMIG4', 'ELET3',
# Consumo
'ABEV3', 'BRFS3', 'JBSS3', 'MGLU3', 'LREN3', 'AMER3',
# Industrial
'WEGE3', 'RAIL3', 'EMBR3', 'AZUL4', 'GOAU4', 'RENT3'
]
# Criar instância do construtor
construtor = ConstrutorCarteira('SEU_TOKEN')
# Fazer screening
acoes_selecionadas = construtor.screening_acoes(universo_acoes, criterios)
print("🎯 TOP 20 AÇÕES SELECIONADAS:")
print("-" * 80)
for i, acao in enumerate(acoes_selecionadas[:20], 1):
print(f"{i:2d}. {acao['ticker']} - {acao['nome']}")
print(f" P/L: {acao['pl']:.1f} | ROE: {acao['roe']:.1f}% | DY: {acao['dy']:.1f}% | Score: {acao['score']:.1f}")
2. Seleção de FIIs
def analisar_fiis(lista_fiis, token):
"""Análise específica para Fundos Imobiliários"""
fiis_analisados = []
for fii in lista_fiis:
try:
url = f"https://brapi.dev/api/quote/{fii}?modules=defaultKeyStatistics&token={token}"
response = requests.get(url)
data = response.json()
fii_data = data['results'][0]
stats = fii_data.get('defaultKeyStatistics', {})
analise = {
'ticker': fii,
'nome': fii_data['shortName'],
'preco': fii_data['regularMarketPrice'],
'dy': stats.get('dividendYield', 0) * 100,
'pvp': stats.get('priceToBook', 0),
'liquidez': fii_data.get('regularMarketVolume', 0),
'categoria': identificar_categoria_fii(fii_data['shortName'])
}
fiis_analisados.append(analise)
except Exception as e:
print(f"Erro ao processar FII {fii}: {e}")
continue
return sorted(fiis_analisados, key=lambda x: x['dy'], reverse=True)
def identificar_categoria_fii(nome):
"""Identifica categoria do FII baseado no nome"""
nome_lower = nome.lower()
if any(palavra in nome_lower for palavra in ['shopping', 'mall', 'varejo']):
return 'Varejo'
elif any(palavra in nome_lower for palavra in ['logístico', 'logistica', 'galpão', 'galpao']):
return 'Logístico'
elif any(palavra in nome_lower for palavra in ['escritório', 'escritorio', 'corporativo', 'laje']):
return 'Corporativo'
elif any(palavra in nome_lower for palavra in ['papel', 'renda', 'recebiveis']):
return 'Papel'
elif any(palavra in nome_lower for palavra in ['híbrido', 'hibrido', 'multi']):
return 'Híbrido'
else:
return 'Outros'
# Lista de FIIs para análise
fiis_universo = [
'HGLG11', 'XPML11', 'VISC11', 'MXRF11', 'BTLG11',
'HGRE11', 'XPLG11', 'IRDM11', 'KNRI11', 'KNCR11',
'VILG11', 'MALL11', 'XPCI11', 'ALZR11', 'BCFF11'
]
fiis_selecionados = analisar_fiis(fiis_universo, 'SEU_TOKEN')
print("🏢 TOP 10 FIIs SELECIONADOS:")
print("-" * 60)
for i, fii in enumerate(fiis_selecionados[:10], 1):
print(f"{i:2d}. {fii['ticker']} - {fii['categoria']}")
print(f" DY: {fii['dy']:.2f}% | P/VP: {fii['pvp']:.2f}")
3. Montagem da Carteira Final
def montar_carteira_otimizada(acoes_selecionadas, fiis_selecionados, valor_total=100000):
"""Monta carteira otimizada respeitando diversificação setorial"""
carteira = {
'valor_total': valor_total,
'alocacao_acoes': valor_total * 0.65, # 65% em ações
'alocacao_fiis': valor_total * 0.15, # 15% em FIIs
'alocacao_rf': valor_total * 0.20, # 20% renda fixa
'posicoes': []
}
# Diversificação setorial para ações
diversificacao = obter_diversificacao_setorial()
acoes_por_setor = agrupar_acoes_por_setor(acoes_selecionadas)
# Alocar ações respeitando diversificação setorial
for setor, config in diversificacao.items():
valor_setor = carteira['alocacao_acoes'] * (config['alvo'] / 100)
acoes_setor = acoes_por_setor.get(setor, [])
if acoes_setor:
# Selecionar até 2 ações por setor
acoes_escolhidas = acoes_setor[:2]
valor_por_acao = valor_setor / len(acoes_escolhidas)
for acao in acoes_escolhidas:
quantidade = int(valor_por_acao / acao['preco'])
if quantidade > 0:
carteira['posicoes'].append({
'tipo': 'Ação',
'ticker': acao['ticker'],
'nome': acao['nome'],
'setor': setor,
'quantidade': quantidade,
'preco': acao['preco'],
'valor_investido': quantidade * acao['preco'],
'dy_esperado': acao['dy']
})
# Alocar FIIs com diversificação por categoria
categorias_fii = {}
for fii in fiis_selecionados:
categoria = fii['categoria']
if categoria not in categorias_fii:
categorias_fii[categoria] = []
categorias_fii[categoria].append(fii)
# Selecionar até 5 FIIs de categorias diferentes
fiis_escolhidos = []
for categoria, fiis_categoria in categorias_fii.items():
if len(fiis_escolhidos) < 5:
fiis_escolhidos.append(fiis_categoria[0]) # Melhor da categoria
if fiis_escolhidos:
valor_por_fii = carteira['alocacao_fiis'] / len(fiis_escolhidos)
for fii in fiis_escolhidos:
quantidade = int(valor_por_fii / fii['preco'])
if quantidade > 0:
carteira['posicoes'].append({
'tipo': 'FII',
'ticker': fii['ticker'],
'nome': fii['nome'],
'setor': fii['categoria'],
'quantidade': quantidade,
'preco': fii['preco'],
'valor_investido': quantidade * fii['preco'],
'dy_esperado': fii['dy']
})
# Adicionar renda fixa (simplificado)
carteira['posicoes'].append({
'tipo': 'Renda Fixa',
'ticker': 'TESOURO SELIC',
'nome': 'Tesouro Selic 2029',
'setor': 'Renda Fixa',
'quantidade': 1,
'preco': carteira['alocacao_rf'],
'valor_investido': carteira['alocacao_rf'],
'dy_esperado': 13.5 # Taxa Selic estimada
})
return carteira
def agrupar_acoes_por_setor(acoes):
"""Agrupa ações por setor para diversificação"""
# Mapeamento simplificado ticker -> setor
mapeamento_setor = {
'ITUB4': 'financeiro', 'BBDC4': 'financeiro', 'BBAS3': 'financeiro', 'BBSE3': 'financeiro',
'VALE3': 'commodities', 'PETR4': 'commodities', 'SUZB3': 'commodities', 'KLBN11': 'commodities',
'EGIE3': 'utilities', 'SBSP3': 'utilities', 'CPLE6': 'utilities', 'TAEE11': 'utilities',
'ABEV3': 'consumo', 'BRFS3': 'consumo', 'MGLU3': 'consumo', 'LREN3': 'consumo',
'WEGE3': 'industrial', 'RAIL3': 'industrial', 'EMBR3': 'industrial', 'RENT3': 'industrial'
}
agrupamento = {}
for acao in acoes:
setor = mapeamento_setor.get(acao['ticker'], 'outros')
if setor not in agrupamento:
agrupamento[setor] = []
agrupamento[setor].append(acao)
return agrupamento
# Montar carteira
carteira_final = montar_carteira_otimizada(acoes_selecionadas, fiis_selecionados, 100000)
# Exibir resultado
print("💼 CARTEIRA MONTADA")
print("=" * 70)
print(f"Valor Total: R$ {carteira_final['valor_total']:,.2f}")
print(f"Ações: R$ {carteira_final['alocacao_acoes']:,.2f} (65%)")
print(f"FIIs: R$ {carteira_final['alocacao_fiis']:,.2f} (15%)")
print(f"Renda Fixa: R$ {carteira_final['alocacao_rf']:,.2f} (20%)")
print("-" * 70)
valor_real_investido = sum(pos['valor_investido'] for pos in carteira_final['posicoes'])
print(f"Valor Real Investido: R$ {valor_real_investido:,.2f}")
print(f"Caixa Restante: R$ {carteira_final['valor_total'] - valor_real_investido:,.2f}")
print("\n📋 POSIÇÕES DA CARTEIRA:")
print("-" * 70)
for pos in carteira_final['posicoes']:
participacao = (pos['valor_investido'] / valor_real_investido) * 100
print(f"{pos['tipo']}: {pos['ticker']} - {pos['setor']}")
print(f" Qtd: {pos['quantidade']} | Preço: R$ {pos['preco']:.2f} | Total: R$ {pos['valor_investido']:,.2f} ({participacao:.1f}%)")
print(f" DY Esperado: {pos['dy_esperado']:.2f}%")
print()
Sistema de Monitoramento da Carteira
Dashboard de Acompanhamento
class MonitorCarteira:
def __init__(self, carteira, token):
self.carteira = carteira
self.token = token
self.base_url = "https://brapi.dev/api"
def atualizar_precos(self):
"""Atualiza preços atuais de todas as posições"""
tickers_acoes = [pos['ticker'] for pos in self.carteira['posicoes'] if pos['tipo'] in ['Ação', 'FII']]
if tickers_acoes:
tickers_str = ','.join(tickers_acoes)
url = f"{self.base_url}/quote/{tickers_str}?token={self.token}"
try:
response = requests.get(url)
data = response.json()
# Criar dicionário de preços atuais
precos_atuais = {resultado['symbol']: resultado['regularMarketPrice']
for resultado in data['results']}
# Atualizar posições
for posicao in self.carteira['posicoes']:
if posicao['ticker'] in precos_atuais:
posicao['preco_atual'] = precos_atuais[posicao['ticker']]
posicao['valor_atual'] = posicao['quantidade'] * posicao['preco_atual']
posicao['resultado'] = posicao['valor_atual'] - posicao['valor_investido']
posicao['rentabilidade'] = (posicao['resultado'] / posicao['valor_investido']) * 100
else:
# Para renda fixa, manter valor original
posicao['preco_atual'] = posicao['preco']
posicao['valor_atual'] = posicao['valor_investido']
posicao['resultado'] = 0
posicao['rentabilidade'] = 0
except Exception as e:
print(f"Erro ao atualizar preços: {e}")
def gerar_relatorio_performance(self):
"""Gera relatório de performance da carteira"""
self.atualizar_precos()
# Calcular métricas gerais
valor_investido_total = sum(pos['valor_investido'] for pos in self.carteira['posicoes'])
valor_atual_total = sum(pos.get('valor_atual', pos['valor_investido']) for pos in self.carteira['posicoes'])
resultado_total = valor_atual_total - valor_investido_total
rentabilidade_total = (resultado_total / valor_investido_total) * 100
# Calcular dividend yield médio
dy_ponderado = sum(pos['dy_esperado'] * pos['valor_investido'] for pos in self.carteira['posicoes']) / valor_investido_total
relatorio = {
'data_relatorio': datetime.now(),
'valor_investido': valor_investido_total,
'valor_atual': valor_atual_total,
'resultado': resultado_total,
'rentabilidade': rentabilidade_total,
'dy_medio': dy_ponderado,
'posicoes': self.carteira['posicoes'].copy(),
'distribuicao_setorial': self.calcular_distribuicao_setorial(),
'distribuicao_tipo': self.calcular_distribuicao_tipo()
}
return relatorio
def calcular_distribuicao_setorial(self):
"""Calcula distribuição por setor"""
distribuicao = {}
valor_total = sum(pos.get('valor_atual', pos['valor_investido']) for pos in self.carteira['posicoes'])
for pos in self.carteira['posicoes']:
setor = pos['setor']
valor = pos.get('valor_atual', pos['valor_investido'])
if setor not in distribuicao:
distribuicao[setor] = 0
distribuicao[setor] += valor
# Converter para percentual
for setor in distribuicao:
distribuicao[setor] = (distribuicao[setor] / valor_total) * 100
return dict(sorted(distribuicao.items(), key=lambda x: x[1], reverse=True))
def calcular_distribuicao_tipo(self):
"""Calcula distribuição por tipo de ativo"""
distribuicao = {}
valor_total = sum(pos.get('valor_atual', pos['valor_investido']) for pos in self.carteira['posicoes'])
for pos in self.carteira['posicoes']:
tipo = pos['tipo']
valor = pos.get('valor_atual', pos['valor_investido'])
if tipo not in distribuicao:
distribuicao[tipo] = 0
distribuicao[tipo] += valor
# Converter para percentual
for tipo in distribuicao:
distribuicao[tipo] = (distribuicao[tipo] / valor_total) * 100
return distribuicao
def verificar_necessidade_rebalanceamento(self, tolerancia=5):
"""Verifica se é necessário rebalancear a carteira"""
distribuicao_atual = self.calcular_distribuicao_tipo()
# Targets ideais
targets = {'Ação': 65, 'FII': 15, 'Renda Fixa': 20}
necessita_rebalanceamento = False
sugestoes = []
for tipo, target in targets.items():
atual = distribuicao_atual.get(tipo, 0)
diferenca = abs(atual - target)
if diferenca > tolerancia:
necessita_rebalanceamento = True
if atual > target:
sugestoes.append(f"Reduzir {tipo}: {atual:.1f}% → {target}% (diferença: {diferenca:.1f}%)")
else:
sugestoes.append(f"Aumentar {tipo}: {atual:.1f}% → {target}% (diferença: {diferenca:.1f}%)")
return {
'necessita_rebalanceamento': necessita_rebalanceamento,
'distribuicao_atual': distribuicao_atual,
'targets': targets,
'sugestoes': sugestoes
}
# Criar monitor da carteira
monitor = MonitorCarteira(carteira_final, 'SEU_TOKEN')
# Gerar relatório de performance
relatorio = monitor.gerar_relatorio_performance()
print("📊 RELATÓRIO DE PERFORMANCE")
print("=" * 50)
print(f"Data: {relatorio['data_relatorio'].strftime('%d/%m/%Y %H:%M')}")
print(f"Valor Investido: R$ {relatorio['valor_investido']:,.2f}")
print(f"Valor Atual: R$ {relatorio['valor_atual']:,.2f}")
print(f"Resultado: R$ {relatorio['resultado']:+,.2f}")
print(f"Rentabilidade: {relatorio['rentabilidade']:+.2f}%")
print(f"Dividend Yield Médio: {relatorio['dy_medio']:.2f}%")
print("\n🏭 DISTRIBUIÇÃO SETORIAL:")
for setor, percentual in relatorio['distribuicao_setorial'].items():
print(f" {setor.title()}: {percentual:.1f}%")
print("\n📈 DISTRIBUIÇÃO POR TIPO:")
for tipo, percentual in relatorio['distribuicao_tipo'].items():
print(f" {tipo}: {percentual:.1f}%")
# Verificar necessidade de rebalanceamento
rebalanceamento = monitor.verificar_necessidade_rebalanceamento()
if rebalanceamento['necessita_rebalanceamento']:
print("\n⚖️ REBALANCEAMENTO NECESSÁRIO:")
for sugestao in rebalanceamento['sugestoes']:
print(f" • {sugestao}")
else:
print("\n✅ Carteira balanceada - não necessita rebalanceamento")
Estratégias de Rebalanceamento
Rebalanceamento Automático
def calcular_rebalanceamento(carteira_atual, targets, valor_adicional=0):
"""Calcula operações necessárias para rebalanceamento"""
# Valor total após aportes
valor_total_atual = sum(pos.get('valor_atual', pos['valor_investido']) for pos in carteira_atual['posicoes'])
valor_total_final = valor_total_atual + valor_adicional
# Calcular valores alvo
valores_alvo = {
'Ação': valor_total_final * targets['Ação'] / 100,
'FII': valor_total_final * targets['FII'] / 100,
'Renda Fixa': valor_total_final * targets['Renda Fixa'] / 100
}
# Calcular valores atuais por tipo
valores_atuais = {}
for pos in carteira_atual['posicoes']:
tipo = pos['tipo']
valor = pos.get('valor_atual', pos['valor_investido'])
if tipo not in valores_atuais:
valores_atuais[tipo] = 0
valores_atuais[tipo] += valor
# Calcular diferenças
operacoes = []
for tipo in targets.keys():
atual = valores_atuais.get(tipo, 0)
alvo = valores_alvo[tipo]
diferenca = alvo - atual
if abs(diferenca) > 100: # Só rebalancear diferenças > R$ 100
if diferenca > 0:
operacoes.append({
'tipo': 'COMPRAR',
'categoria': tipo,
'valor': diferenca,
'descricao': f"Comprar R$ {diferenca:,.2f} em {tipo}"
})
else:
operacoes.append({
'tipo': 'VENDER',
'categoria': tipo,
'valor': abs(diferenca),
'descricao': f"Vender R$ {abs(diferenca):,.2f} em {tipo}"
})
return {
'valores_atuais': valores_atuais,
'valores_alvo': valores_alvo,
'operacoes': operacoes,
'valor_adicional': valor_adicional
}
# Exemplo de rebalanceamento com aporte
targets_ideais = {'Ação': 65, 'FII': 15, 'Renda Fixa': 20}
aporte_mensal = 5000
rebal = calcular_rebalanceamento(carteira_final, targets_ideais, aporte_mensal)
print("⚖️ PLANO DE REBALANCEAMENTO")
print("=" * 50)
print(f"Aporte adicional: R$ {rebal['valor_adicional']:,.2f}")
print("\nOperações necessárias:")
for op in rebal['operacoes']:
print(f" {op['tipo']}: {op['descricao']}")
Alertas e Monitoramento Automatizado
Sistema de Alertas
def configurar_alertas_carteira(carteira, parametros_alerta):
"""Configura alertas para a carteira"""
alertas = {
'queda_posicao': [], # Posições com queda > X%
'concentracao': [], # Posições muito concentradas
'rebalanceamento': [], # Necessidade de rebalanceamento
'dividendos': [] # Próximos pagamentos de dividendos
}
# Verificar quedas significativas
for pos in carteira['posicoes']:
if pos.get('rentabilidade', 0) < parametros_alerta['queda_maxima']:
alertas['queda_posicao'].append({
'ticker': pos['ticker'],
'rentabilidade': pos.get('rentabilidade', 0),
'valor_perda': pos.get('resultado', 0)
})
# Verificar concentração
valor_total = sum(pos.get('valor_atual', pos['valor_investido']) for pos in carteira['posicoes'])
for pos in carteira['posicoes']:
participacao = (pos.get('valor_atual', pos['valor_investido']) / valor_total) * 100
if participacao > parametros_alerta['concentracao_maxima']:
alertas['concentracao'].append({
'ticker': pos['ticker'],
'participacao': participacao
})
return alertas
def enviar_alertas_telegram(alertas, bot_token, chat_id):
"""Envia alertas via Telegram"""
import requests
if not any(alertas.values()):
return # Nenhum alerta para enviar
mensagem = "🚨 <b>ALERTAS DA CARTEIRA</b>\n\n"
if alertas['queda_posicao']:
mensagem += "📉 <b>Quedas Significativas:</b>\n"
for alerta in alertas['queda_posicao']:
mensagem += f"• {alerta['ticker']}: {alerta['rentabilidade']:+.2f}%\n"
mensagem += "\n"
if alertas['concentracao']:
mensagem += "⚠️ <b>Concentração Excessiva:</b>\n"
for alerta in alertas['concentracao']:
mensagem += f"• {alerta['ticker']}: {alerta['participacao']:.1f}% da carteira\n"
mensagem += "\n"
url = f"https://api.telegram.org/bot{bot_token}/sendMessage"
payload = {
'chat_id': chat_id,
'text': mensagem,
'parse_mode': 'HTML'
}
try:
requests.post(url, json=payload)
print("Alertas enviados via Telegram")
except Exception as e:
print(f"Erro ao enviar alertas: {e}")
# Configurar parâmetros de alerta
parametros = {
'queda_maxima': -10, # Alerta se posição cair mais de 10%
'concentracao_maxima': 15 # Alerta se posição > 15% da carteira
}
alertas = configurar_alertas_carteira(carteira_final, parametros)
Análise de Performance Histórica
Backtesting da Estratégia
def simular_performance_historica(tickers_carteira, pesos, periodo_anos=3, token=''):
"""Simula performance histórica da carteira"""
from datetime import datetime, timedelta
import numpy as np
# Buscar dados históricos
dados_historicos = {}
for ticker in tickers_carteira:
url = f"https://brapi.dev/api/quote/{ticker}?range={periodo_anos}y&interval=1mo&token={token}"
try:
response = requests.get(url)
data = response.json()
historico = data['results'][0]['historicalDataPrice']
precos = [item['close'] for item in historico]
datas = [datetime.fromtimestamp(item['date']) for item in historico]
dados_historicos[ticker] = {
'precos': precos,
'datas': datas
}
except Exception as e:
print(f"Erro ao buscar dados de {ticker}: {e}")
# Calcular retornos da carteira
if not dados_historicos:
return None
# Alinhar datas (usar intersecção)
datas_comuns = set(dados_historicos[list(dados_historicos.keys())[0]]['datas'])
for ticker_data in dados_historicos.values():
datas_comuns = datas_comuns.intersection(set(ticker_data['datas']))
datas_ordenadas = sorted(list(datas_comuns))
# Calcular retornos mensais da carteira
retornos_carteira = []
for i in range(1, len(datas_ordenadas)):
retorno_mensal = 0
for ticker, peso in pesos.items():
if ticker in dados_historicos:
data_atual = datas_ordenadas[i]
data_anterior = datas_ordenadas[i-1]
# Encontrar preços nas datas
precos = dados_historicos[ticker]['precos']
datas = dados_historicos[ticker]['datas']
idx_atual = datas.index(data_atual) if data_atual in datas else -1
idx_anterior = datas.index(data_anterior) if data_anterior in datas else -1
if idx_atual >= 0 and idx_anterior >= 0:
retorno_ativo = (precos[idx_atual] - precos[idx_anterior]) / precos[idx_anterior]
retorno_mensal += retorno_ativo * peso
retornos_carteira.append(retorno_mensal)
# Calcular métricas de performance
retorno_anualizado = (np.prod([1 + r for r in retornos_carteira]) ** (12 / len(retornos_carteira))) - 1
volatilidade_anualizada = np.std(retornos_carteira) * np.sqrt(12)
sharpe_ratio = retorno_anualizado / volatilidade_anualizada if volatilidade_anualizada > 0 else 0
# Drawdown máximo
patrimonio_acumulado = [10000] # Valor inicial
for retorno in retornos_carteira:
patrimonio_acumulado.append(patrimonio_acumulado[-1] * (1 + retorno))
picos = [patrimonio_acumulado[0]]
for valor in patrimonio_acumulado[1:]:
picos.append(max(picos[-1], valor))
drawdowns = [(patrimonio_acumulado[i] - picos[i]) / picos[i] for i in range(len(patrimonio_acumulado))]
max_drawdown = min(drawdowns)
return {
'retorno_anualizado': retorno_anualizado * 100,
'volatilidade_anualizada': volatilidade_anualizada * 100,
'sharpe_ratio': sharpe_ratio,
'max_drawdown': max_drawdown * 100,
'retornos_mensais': retornos_carteira,
'patrimonio_final': patrimonio_acumulado[-1]
}
# Simular performance da carteira montada
pesos_carteira = {}
valor_total = sum(pos['valor_investido'] for pos in carteira_final['posicoes'])
for pos in carteira_final['posicoes']:
if pos['tipo'] in ['Ação', 'FII']:
peso = pos['valor_investido'] / valor_total
pesos_carteira[pos['ticker']] = peso
performance = simular_performance_historica(list(pesos_carteira.keys()), pesos_carteira, 3, 'SEU_TOKEN')
if performance:
print("📈 PERFORMANCE HISTÓRICA (3 anos)")
print("=" * 40)
print(f"Retorno Anualizado: {performance['retorno_anualizado']:+.2f}%")
print(f"Volatilidade: {performance['volatilidade_anualizada']:.2f}%")
print(f"Sharpe Ratio: {performance['sharpe_ratio']:.2f}")
print(f"Drawdown Máximo: {performance['max_drawdown']:+.2f}%")
print(f"R$ 10.000 viraram: R$ {performance['patrimonio_final']:,.2f}")
Conclusão
Construir uma carteira diversificada é um processo contínuo que requer disciplina, acompanhamento e rebalanceamento periódico. Com as ferramentas da brapi.dev, é possível:
Vantagens da Abordagem Sistemática:
- Redução de Riscos: Diversificação eficiente entre setores e ativos
- Monitoramento Automático: Acompanhamento em tempo real da performance
- Rebalanceamento Inteligente: Manutenção das alocações ideais
- Análise Baseada em Dados: Decisões fundamentadas em métricas objetivas
Próximos Passos:
- Crie sua conta na brapi.dev para acessar dados completos
- Implemente os códigos apresentados neste guia
- Adapte as estratégias ao seu perfil de risco
- Monitore regularmente sua carteira
Recursos Adicionais:
- Documentação completa da API
- Dados históricos para backtesting
- Exemplos práticos de implementação
Lembre-se: Diversificação não elimina riscos, mas os reduz significativamente. Sempre invista apenas o que pode perder e mantenha uma reserva de emergência adequada!