Avaliando Retornos Ajustados ao Risco com Python

Quando se fala em investimentos, muitos pensam apenas em retorno — quanto um ativo rende em determinado período.

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étricaO que medeFórmulaInterpretação
Sharpe RatioRetorno por unidade de risco total(Rₚ - Rf) / σₚQuanto maior, melhor. Acima de 1 é considerado bom.
Sortino RatioRetorno por unidade de risco negativo(Rₚ - Rf) / σₙIgnora volatilidade positiva; mais realista.
BetaSensibilidade ao mercadoCov(Rₚ, Rₘ) / Var(Rₘ)Beta > 1: mais volátil que o mercado.
AlphaRetorno excedente ao previsto pelo riscoRₚ - [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

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

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

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çãoInterpretaçãoAção sugerida
Sharpe alto, Beta baixoRetorno eficiente e estávelIdeal para perfil conservador
Sharpe alto, Beta altoRetorno alto com risco elevadoIndicado para perfil arrojado
Alpha positivoSupera o mercado após ajuste de riscoBom potencial de investimento
Sortino > SharpeBoa proteção contra quedasEstraté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

Postagens mais visitadas deste blog

Python para Computação Quântica: Introdução com Qiskit

Gerando Relatórios em PDF com Python (ReportLab e FPDF)

Estrutura Básica de um Programa C# com exemplos