Avaliando Retornos Ajustados ao Risco com Python
Mas há uma verdade que separa investidores experientes de iniciantes:
Um bom investimento não é o que rende mais, e sim o que entrega o melhor retorno para o nível de risco assumido.
Essa análise é conhecida como retorno ajustado ao risco, e Python fornece todas as ferramentas necessárias para realizar esse tipo de avaliação quantitativa e visual.
1. Conceitos Fundamentais
Antes de mergulhar no código, vamos revisar os principais indicadores usados na análise:
| Métrica | O que mede | Fórmula | Interpretação |
|---|---|---|---|
| Sharpe Ratio | Retorno por unidade de risco total | (Rₚ - Rf) / σₚ | Quanto maior, melhor. Acima de 1 é considerado bom. |
| Sortino Ratio | Retorno por unidade de risco negativo | (Rₚ - Rf) / σₙ | Ignora volatilidade positiva; mais realista. |
| Beta | Sensibilidade ao mercado | Cov(Rₚ, Rₘ) / Var(Rₘ) | Beta > 1: mais volátil que o mercado. |
| Alpha | Retorno excedente ao previsto pelo risco | Rₚ - [Rf + β(Rₘ - Rf)] | Mede o “valor agregado” do gestor. |
📌 Onde:
Rₚ = Retorno do portfólio
Rₘ = Retorno do mercado (ex: Ibovespa ou S&P 500)
Rf = Taxa livre de risco (ex: Tesouro Selic)
σₚ = Desvio padrão total
σₙ = Desvio padrão apenas dos retornos negativos
2. Preparando o Ambiente
Instale as bibliotecas necessárias:
pip install pandas numpy yfinance matplotlib seaborn
3. Coletando Dados com yfinance
Vamos usar ETFs brasileiros como exemplo:
import yfinance as yf
import pandas as pd
import numpy as np
ativos = ["BOVA11.SA", "IVVB11.SA", "SMAL11.SA"]
dados = yf.download(ativos, start="2022-01-01", end="2023-12-31")["Adj Close"]
dados.head()
4. Calculando Retornos Diários e Anuais
retornos = dados.pct_change().dropna()
retornos_anuais = retornos.mean() * 252
volatilidade_anual = retornos.std() * np.sqrt(252)
Vamos assumir uma taxa livre de risco (Rf) de 10% ao ano (Tesouro Selic):
rf = 0.10
5. Sharpe Ratio
O Sharpe Ratio mede o ganho de retorno em relação ao risco total:
sharpe = (retornos_anuais - rf) / volatilidade_anual
print("Sharpe Ratio:\n", sharpe)
📊 Interpretação:
Sharpe < 1 → Baixa eficiência de risco
1 ≤ Sharpe < 2 → Razoável
2 ≤ Sharpe < 3 → Excelente
Sharpe ≥ 3 → Excepcional
6. Sortino Ratio
O Sortino Ratio foca apenas nos retornos negativos (volatilidade ruim):
def sortino_ratio(returns, rf=0.10):
mean_return = returns.mean() * 252
downside = returns[returns < 0].std() * np.sqrt(252)
return (mean_return - rf) / downside
sortino = retornos.apply(sortino_ratio)
print("Sortino Ratio:\n", sortino)
📌 Mais preciso que o Sharpe, pois penaliza apenas quedas.
7. Beta e Alpha
O Beta compara o ativo com um índice de referência, como o Ibovespa (BOVA11):
benchmark = retornos["BOVA11.SA"]
def calcular_beta_alpha(ativo, benchmark, rf=0.10):
cov = np.cov(ativo, benchmark)[0][1]
var = np.var(benchmark)
beta = cov / var
retorno_ativo = ativo.mean() * 252
retorno_mercado = benchmark.mean() * 252
alpha = retorno_ativo - (rf + beta * (retorno_mercado - rf))
return beta, alpha
resultados = {}
for nome in ativos:
if nome != "BOVA11.SA":
beta, alpha = calcular_beta_alpha(retornos[nome], benchmark)
resultados[nome] = {"Beta": beta, "Alpha": alpha}
pd.DataFrame(resultados).T
📈
Beta > 1 → ativo mais volátil que o mercado.
Beta < 1 → ativo mais estável.
Alpha positivo → desempenho acima do esperado.
8. Visualizando Resultados
8.1 Risco vs Retorno
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,6))
sns.scatterplot(x=volatilidade_anual, y=retornos_anuais, s=120)
for ativo in retornos_anuais.index:
plt.text(volatilidade_anual[ativo], retornos_anuais[ativo], ativo)
plt.title("Risco x Retorno (Volatilidade vs Retorno Anual)")
plt.xlabel("Volatilidade Anualizada")
plt.ylabel("Retorno Anualizado")
plt.grid(True)
plt.show()
📌 Esse gráfico mostra a fronteira de eficiência — ativos que rendem mais com menor risco estão melhor posicionados.
8.2 Comparando Sharpe e Sortino
metricas = pd.DataFrame({
"Retorno Anual": retornos_anuais,
"Volatilidade": volatilidade_anual,
"Sharpe": sharpe,
"Sortino": sortino
})
metricas.sort_values("Sharpe", ascending=False)
8.3 Gráfico de Barras de Métricas
metricas[["Sharpe", "Sortino"]].plot(kind="bar", figsize=(10,6))
plt.title("Comparação de Retornos Ajustados ao Risco")
plt.ylabel("Valor do Índice")
plt.show()
📊 Esse gráfico resume visualmente quais ativos entregam melhor performance por unidade de risco.
9. Interpretação Estratégica
| Situação | Interpretação | Ação sugerida |
|---|---|---|
| Sharpe alto, Beta baixo | Retorno eficiente e estável | Ideal para perfil conservador |
| Sharpe alto, Beta alto | Retorno alto com risco elevado | Indicado para perfil arrojado |
| Alpha positivo | Supera o mercado após ajuste de risco | Bom potencial de investimento |
| Sortino > Sharpe | Boa proteção contra quedas | Estratégia defensiva eficiente |
10. Boas Práticas
Sempre compare ativos com mesmo período de análise.
Atualize dados periodicamente para monitoramento contínuo.
Combine métricas (Sharpe + Beta + Alpha) para análise mais completa.
Use benchmarks adequados (Ibovespa, S&P 500, CDI, etc.).
Visualize resultados em dashboards interativos (com Dash ou Streamlit).
11. Conclusão
Com Python, é possível avaliar retornos ajustados ao risco de forma precisa e visual, ajudando investidores e analistas a:
Identificar os ativos mais eficientes;
Comparar portfólios com diferentes níveis de risco;
Calcular métricas como Sharpe, Sortino, Beta e Alpha;
Tomar decisões embasadas em dados quantitativos.
A análise de risco e retorno é um pilar da inteligência financeira moderna, e Python é a ferramenta ideal para colocar isso em prática com flexibilidade e automação.

Comentários
Postar um comentário